ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Kubernetes] EKS Workshop #2
    Kubernetes/EKS 2024. 6. 9. 19:11

    인그레스 컨트롤러 만들기(Ingress Controller)

    - 인그레스는 클러스터 외부에서 내부로 접근할때, 요청들을 어떻게 처리할지 정의해놓은 규칙

    - 외부 요청에 대한 로드 밸런성, TLS/SSL 인증서 처리, HTTP 경로에 대한 라우팅 등 설정 (L7의 영역)

    - Nodeport나 LoadBalancer로도 외부에 노출할 순 있지만,, 라우팅 규칙등의 상세한 옵션을 더 추가해야함-> 인그레스 필요

    - 인그레스 설정을 동작하기 위해 인그레스 컨트롤러를 만들어야함 -> 이 컨트롤러는 클러스터 생성할때 자동으로 생성되는게 아니라 직접 구현이 필요함

    AWS Load Balancer 컨트롤러 만들기

    - 클러스터에 인그레이스 자원이 생성될 때 ALB 및 필요한 자원이 새성되로록 트리거하는 컨트롤러임

    - 구성해놓은걸 가지고 ALB를 만들고 http(s) 트래픽을 파드로 라우팅 시켜줌

    • 쿠버네티스의 Ingress의 경우, Application Load Balancers으로 프로비저닝
    • 쿠버네티스의 Service의 경우, Network Load Balancers으로 프로비저닝

    AWS Load Balancer 컨트롤러에서 지원하는 트래픽 모드는 아래의 두 가지

    • Instance(default): 클러스터 내 노드를 ALB의 대상으로 등록/ ALB에 도달하는 트래픽은 NodePort로 라우팅된 다음 파드로 프록시
    • IP: 파드를 ALB 대상으로 등록함 / ALB에 도달하는 트래픽은 파드로 직접 라우팅됨 / 해당 트래픽 모드를 사용하기 위해선 ingress.yaml 파일에 주석을 사용하여 명시적으로 지정해야 함

    # 인그레스 컨트롤러 설정할 위치
    cd ~/environment
    
    mkdir -p manifests/alb-ingress-controller && cd manifests/alb-ingress-controller
    
    # 최종 폴더 위치
    /home/ec2-user/environment/manifests/alb-ingress-controller

     

    - 컨트롤러가 워커노드위에서 동작하기 때문에 IAM permission을 통해 LB에 접근하도록 만들어야함. iam role 붙이기!

    # IAM OIDC(OpenID Connect) identity Provider 생성
    # service account에 얘를 생성해야함
    
    eksctl utils associate-iam-oidc-provider \
        --region ${AWS_REGION} \
        --cluster eks-demo \
        --approve
    
    # 클러스터의 OIDV provider URL 확인
    aws eks describe-cluster --name eks-demo --query "cluster.identity.oidc.issuer" --output text
    
    # /id/ 뒤 값 복사하고 grep
    aws iam list-open-id-connect-providers | grep 8A6E78112D7F1C4DC352B1B511DD13CF

     

     

    # IAM 정책 생성하는 작업 수행
    curl -O https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/v2.5.4/docs/install/iam_policy.json
    
    aws iam create-policy \
        --policy-name AWSLoadBalancerControllerIAMPolicy \
        --policy-document file://iam_policy.json
    
    # AWS Load Balancer Controller를 위한 ServiceAccount를 생성
    eksctl create iamserviceaccount \
        --cluster eks-demo \
        --namespace kube-system \
        --name aws-load-balancer-controller \
        --attach-policy-arn arn:aws:iam::$ACCOUNT_ID:policy/AWSLoadBalancerControllerIAMPolicy \
        --override-existing-serviceaccounts \
        --approve

     

    클러스터에 컨트롤러 추가하기

    - Cert-manager는 쿠버네티스 클러스터 내에서 TLS인증서를 자동으로 프로비저닝 및 관리하는 오픈 소스

    # cert-manager 설치
    kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.12.0/cert-manager.yaml
    
    # lb controller yaml 파일 다운로드
    curl -Lo v2_5_4_full.yaml https://github.com/kubernetes-sigs/aws-load-balancer-controller/releases/download/v2.5.4/v2_5_4_full.yaml
    
    # 기존 manifest파일의 service account 제거
    sed -i.bak -e '596,604d' ./v2_5_4_full.yaml
    
    # 클러스터 이름 변경
    sed -i.bak -e 's|your-cluster-name|eks-demo|' ./v2_5_4_full.yaml
    
    # AWS Load Balancer controller 파일을 배포
    kubectl apply -f v2_5_4_full.yaml
    
    # IngressClass 및 IngressClassParams 매니페스트를 다운로드
    curl -Lo v2_5_4_ingclass.yaml https://github.com/kubernetes-sigs/aws-load-balancer-controller/releases/download/v2.5.4/v2_5_4_ingclass.yaml
    kubectl apply -f v2_5_4_ingclass.yaml
    
    # 배포 성공 여부
    kubectl get deployment -n kube-system aws-load-balancer-controller
    
    # service account 생성 확인
    kubectl get sa aws-load-balancer-controller -n kube-system -o yaml

     

     

     

     

    서비스 배포하기 

    - 웹서비스를 구성하는 백엔드, 프론트앤드를 eks에 배포해보자

     

    • 소스 코드 다운로드
    • Amazon ECR에 각 서비스에 대한 리포지토리 생성
    • Dockerfile을 포함한 소스 코드 위치에서 컨테이너 이미지 빌드 후, 리포지토리에 푸시
    • 각 서비스에 대한 Deployment, Service, Ingress 매니페스트 파일 생성 및 배포

    1) 첫번째 백엔드 배포 (flask 백엔드 배포)

    # 매니페스트 폴더 위치
    cd ~/environment/manifests/
    
    # deploy manifest yaml파일 작성
    cat <<EOF> flask-deployment.yaml
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: demo-flask-backend
      namespace: default
    spec:
      replicas: 3
      selector:
        matchLabels:
          app: demo-flask-backend
      template:
        metadata:
          labels:
            app: demo-flask-backend
        spec:
          containers:
            - name: demo-flask-backend
              image: $ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com/demo-flask-backend:latest
              imagePullPolicy: Always
              ports:
                - containerPort: 8080
    EOF
    # service manifest
    cat <<EOF> flask-service.yaml
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: demo-flask-backend
      annotations:
        alb.ingress.kubernetes.io/healthcheck-path: "/contents/aws"
    spec:
      selector:
        app: demo-flask-backend
      type: NodePort
      ports:
        - port: 8080 # 서비스가 생성할 포트  
          targetPort: 8080 # 서비스가 접근할 pod의 포트
          protocol: TCP
    EOF
    # ingress
    cat <<EOF> flask-ingress.yaml
    ---
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
        name: "flask-backend-ingress"
        namespace: default
        annotations:
          alb.ingress.kubernetes.io/scheme: internet-facing
          alb.ingress.kubernetes.io/target-type: ip
          alb.ingress.kubernetes.io/group.name: eks-demo-group
          alb.ingress.kubernetes.io/group.order: '1'
    spec:
        ingressClassName: alb
        rules:
        - http:
            paths:
              - path: /contents
                pathType: Prefix
                backend:
                  service:
                    name: "demo-flask-backend"
                    port:
                      number: 8080
    EOF

     

    순서대로 배포

    kubectl apply -f flask-deployment.yaml
    kubectl apply -f flask-service.yaml
    kubectl apply -f flask-ingress.yaml
    
    
    echo http://$(kubectl get ingress/flask-backend-ingress -o jsonpath='{.status.loadBalancer.ingress[*].hostname}')/contents/aws

     

    2) 두번째 백엔드 배포 (express 백엔드 배포)

    # 매니페스트 폴더 위치
    cd ~/environment/manifests/
    
    # deploy manifest yaml파일 작성
    cat <<EOF> nodejs-deployment.yaml
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: demo-nodejs-backend
      namespace: default
    spec:
      replicas: 3
      selector:
        matchLabels:
          app: demo-nodejs-backend
      template:
        metadata:
          labels:
            app: demo-nodejs-backend
        spec:
          containers:
            - name: demo-nodejs-backend
              image: public.ecr.aws/y7c9e1d2/joozero-repo:latest
              imagePullPolicy: Always
              ports:
                - containerPort: 3000
    EOF
    # service manifest
    cat <<EOF> nodejs-service.yaml
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: demo-nodejs-backend
      annotations:
        alb.ingress.kubernetes.io/healthcheck-path: "/services/all"
    spec:
      selector:
        app: demo-nodejs-backend
      type: NodePort
      ports:
        - port: 8080
          targetPort: 3000
          protocol: TCP
    EOF
    # ingress
    cat <<EOF> nodejs-ingress.yaml
    ---
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: "nodejs-backend-ingress"
      namespace: default
      annotations:
        alb.ingress.kubernetes.io/scheme: internet-facing
        alb.ingress.kubernetes.io/target-type: ip
        alb.ingress.kubernetes.io/group.name: eks-demo-group
        alb.ingress.kubernetes.io/group.order: '2'
    spec:
      ingressClassName: alb
      rules:
      - http:
            paths:
              - path: /services
                pathType: Prefix
                backend:
                  service:
                    name: "demo-nodejs-backend"
                    port:
                      number: 8080
    EOF

     

    순서대로 배포

    kubectl apply -f nodejs-deployment.yaml
    kubectl apply -f nodejs-service.yaml
    kubectl apply -f nodejs-ingress.yaml
    
    
    
    echo http://$(kubectl get ingress/nodejs-backend-ingress -o jsonpath='{.status.loadBalancer.ingress[*].hostname}')/services/all

     

     

     

    3) React 프론트엔드 배포하기

    # 소스코드 다운로드
    cd /home/ec2-user/environment
    git clone https://github.com/joozero/amazon-eks-frontend.git
    
    # 리포지토리 생성
    aws ecr create-repository \
    --repository-name demo-frontend \
    --image-scanning-configuration scanOnPush=true \
    --region ${AWS_REGION}
    
    # flask 인그레스 주소 
    echo http://$(kubectl get ingress/flask-backend-ingress -o jsonpath='{.status.loadBalancer.ingress[*].hostname}')/contents/'${search}'
    
    # node 인그레스 주소
    echo http://$(kubectl get ingress/nodejs-backend-ingress -o jsonpath='{.status.loadBalancer.ingress[*].hostname}')/services/all

    cd /home/ec2-user/environment/amazon-eks-frontend
    npm install
    npm run build

     

    ecr 에 이미지 똑같이 push하고, 프론트엔드용 manifest 폴더 배포하기

    cd /home/ec2-user/environment/manifests
    
    cat <<EOF> frontend-deployment.yaml
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: demo-frontend
      namespace: default
    spec:
      replicas: 3
      selector:
        matchLabels:
          app: demo-frontend
      template:
        metadata:
          labels:
            app: demo-frontend
        spec:
          containers:
            - name: demo-frontend
              image: $ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com/demo-frontend:latest
              imagePullPolicy: Always
              ports:
                - containerPort: 80
    EOF
    cat <<EOF> frontend-service.yaml
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: demo-frontend
      annotations:
        alb.ingress.kubernetes.io/healthcheck-path: "/"
    spec:
      selector:
        app: demo-frontend
      type: NodePort
      ports:
        - protocol: TCP
          port: 80
          targetPort: 80
    EOF
    cat <<EOF> frontend-ingress.yaml
    ---
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: "frontend-ingress"
      namespace: default
      annotations:
        alb.ingress.kubernetes.io/scheme: internet-facing
        alb.ingress.kubernetes.io/target-type: ip
        alb.ingress.kubernetes.io/group.name: eks-demo-group
        alb.ingress.kubernetes.io/group.order: '3'
    spec:
      ingressClassName: alb
      rules:
        - http:
            paths:
              - path: /
                pathType: Prefix
                backend:
                  service:
                    name: "demo-frontend"
                    port:
                      number: 80
    EOF
    kubectl apply -f frontend-deployment.yaml
    kubectl apply -f frontend-service.yaml
    kubectl apply -f frontend-ingress.yaml
    
    
    echo http://$(kubectl get ingress/frontend-ingress -o jsonpath='{.status.loadBalancer.ingress[*].hostname}')

     

     

    배포 성공?

    'Kubernetes > EKS' 카테고리의 다른 글

    [EKS] EKS 업그레이드 후기  (2) 2024.10.27
    [Kubernetes] EKS Workshop #3  (0) 2024.06.09
    [Kubernetes] EKS Workshop #1  (1) 2024.06.09
Designed by Tistory.