[EKS] AWS LoadBalancer Controller 설치 및 Ingress(ALB), Service(NLB) 배포

vinca·2024년 2월 13일
1

🦓 EKS

목록 보기
10/23
post-thumbnail

Amazon EKS 원클릭 배포 환경에서 진행

AWS LoadBalancer Controller 설치

OIDC 공급자 확인

먼저 OIDC 공급자를 확인해보자.

aws eks describe-cluster --name $CLUSTER_NAME \
  --query "cluster.identity.oidc.issuer" \
  --output text

AWS LoadBalancer Controller를 사용하기 위한 과정

쿠버네티스가 AWS 서비스에 접근하고 AWS LoadBalancer를 사용하기 위해서는 쿠버네티스 Service Account에 적절한 IAM 역할이 부여되어야 한다.
이 과정은 어떻게 수행되는 것일까?

AWS LoadBalancer Controller를 사용하기 위해서는 다음과 같은 과정이 필요하다.

IAM 정책 생성 ➡️ IAM Role에 정책을 붙임 ➡️ IAM Role과 SA를 연결 (IRSA) ➡️ 해당 SA로 AWS LB Controller 설치(생성)

이 과정에서 2번째 과정인 IAM Role에 정책을 붙임을 할 때 신뢰관계에 정책에 OIDC 인증 방식이 사용된다.

OIDC 인증 방식이란?

OIDC 즉, OpenID Connect의 약자로 일종의 권한을 갖기위한 열쇠다.
쿠버네티스 클러스터를 생성하면 자동적으로 OIDC 공급자 URL이 생성되는데, 이 공급자 URL을 사용해서 IAM Role의 신뢰관계 정책을 생성한다.

다음과 같이 실제로 IAM Role을 생성 시, 쿠버네티스의 OIDC를 정책을 다룰 주체(Principal)에 넣어 IAM Role을 생성하는 것을 볼 수 있다.

실제 이후 과정을 수행해보게 되면, IAM Role에 신뢰관계 정책으로 OIDC 인증 방식을 등록하는 것을 볼 수 있다.

💡이처럼 IAM Role을 생성할 때, 이 IAM Role을 누가맡을 지를 OIDC를 통해 신뢰관계 정책에 정의해 두었으므로, 이후 IRSA 과정에서 문제 없이 쿠버네티스의 SA가 IAM Role을 가질 수 있는 것이다.

정책 생성

AWSLoadBalancerControllerIAMPolicy를 생성해 주어야한다. 기본적으로 AWS ELB를 다루기 위한 정책으로 AWS 계정 내 해당 정책은 기본적으로는 없으므로 생성해준다.

// IAM Policy json 파일 다운로드
curl -o iam_policy.json https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/v2.4.7/docs/install/iam_policy.json

// AWSLoadBalancerControllerIAMPolicy 생성
aws iam create-policy --policy-name AWSLoadBalancerControllerIAMPolicy --policy-document file://iam_policy.json

IRSA 과정 수행

이후, 생성한 IAM 정책을 IAM Role에 연결하고(OIDC를 신뢰관계 정책에 넣는 과정 포함) SA를 생성한 뒤, IAM Role과 연결하는 과정까지 한번에 수행해보자.

// IRSA 수행
eksctl create iamserviceaccount \
  --cluster=$CLUSTER_NAME \
  --namespace=kube-system \
  --name=aws-load-balancer-controller \
  --attach-policy-arn=arn:aws:iam::$ACCOUNT_ID:policy/AWSLoadBalancerControllerIAMPolicy \
  --override-existing-serviceaccounts \
  --approve

// IRSA 정보 확인
eksctl get iamserviceaccount --cluster $CLUSTER_NAME

// Kubernetes 서비스 어카운트 확인
kubectl get serviceaccounts -n kube-system aws-load-balancer-controller -o yaml | yh

AWS Load Balancer Controller 설치

이제 AWS Load Balancer Controller를 Helm을 통해서 설치해보자.

// Helm Chart Repository 추가 및 업데이트
helm repo add eks https://aws.github.io/eks-charts
helm repo update

// Helm Chart - AWS Load Balancer Controller 설치
helm install aws-load-balancer-controller eks/aws-load-balancer-controller -n kube-system \
  --set clusterName=$CLUSTER_NAME \
  --set serviceAccount.create=false \
  --set serviceAccount.name=aws-load-balancer-controller

다음과 같이 파드형태로 AWS Load Balancer Controller가 설치되는 것을 확인할 수 있다.

확인

다음과 같이 AWS Load Balancer Controller를 생성하면서 함께 만들어진 CRD 및 ClusterRole
그리고 AWS Load Balancer Controller의 상세 정보를 확인할 수 있다.

// Kubernetes CRD 확인
kubectl get crd

// AWS Load Balancer Controller Role 확인
kubectl describe clusterroles.rbac.authorization.k8s.io aws-load-balancer-controller-role

// AWS Load Balancer Controller 확인
kubectl get deployment -n kube-system aws-load-balancer-controller

kubectl describe deploy -n kube-system aws-load-balancer-controller


NLB

NLB는 4계층 로드밸런서로 EKS에서는 Service(LoadBalancer)에 해당한다.

모니터링 터미널 생성

// 파드, 서비스, 엔드포인트 모니터링
watch -d kubectl get pod,svc,ep

NLB를 배포하기 전에 터미널을 추가로 하나 더 만들고, 어떤 방식으로 AWS LoadBalancer Controller로 배포한 NLB가 동작하는지 확인해 보도록 하자.

파드 및 NLB 생성

쿠버네티스에서 AWS LoadBalancer Controller 설치한 상태에서 Service를 LoadBalancer로 하고, nlb 어노테이션과 함께 배포하게 되면, AWS LoadBalancer로 NLB가 생성된다.

# 파드 배포
apiVersion: apps/v1
kind: Deployment
metadata:
  name: deploy-echo
spec:
  replicas: 2
  selector:
    matchLabels:
      app: deploy-websrv
  template:
    metadata:
      labels:
        app: deploy-websrv
    spec:
      terminationGracePeriodSeconds: 0
      containers:
      - name: akos-websrv
        image: k8s.gcr.io/echoserver:1.5
        ports:
        - containerPort: 8080
---
# NLB 배포
apiVersion: v1
kind: Service
metadata:
  name: svc-nlb-ip-type
  annotations:
    service.beta.kubernetes.io/aws-load-balancer-nlb-target-type: ip
    service.beta.kubernetes.io/aws-load-balancer-scheme: internet-facing
    service.beta.kubernetes.io/aws-load-balancer-healthcheck-port: "8080"
    service.beta.kubernetes.io/aws-load-balancer-cross-zone-load-balancing-enabled: "true"
spec:
  ports:
    - port: 80
      targetPort: 8080
      protocol: TCP
  type: LoadBalancer
  loadBalancerClass: service.k8s.aws/nlb
  selector:
    app: deploy-websrv

위와 같이 yaml 파일을 적절하게 만들어 주고, 해당 파일을 배포하도록 한다.

// 디플로이먼트 & 서비스 배포
kubectl apply -f echo-service-nlb.yaml

// 정보 확인
kubectl get pod -owide

kubectl get targetgroupbindings

배포 확인

배포된 파드와 해당 파드들을 타켓 그룹으로 가지는 서비스(NLB)를 확인할 수 있다.

새로운 로드밸런서 서비스(NLB)가 생성되었고, 생성된 서비스(NLB)의 엔드포인트가 각 파드의 IP를 가리키고 있다.

AWS 콘솔에서 확인

실제로 NLB가 생성된 것을 AWS콘솔에서 직접 확인해 보자.

먼저 EC2의 로드밸런서 탭에 진입하면, 실제로 NLB가 생성된 것을 확인할 수 있다.

이제 이러한 NLB가 실제로 로드밸런싱하는 타겟 그룹(대상 그룹)을 확인해 보자.
대상은 실제로 이전 확인했던 파드 IP라는 것을 확인할 수 있다.

트래픽 확인

이제 트래픽을 보내보고 확인해 보자.

// 웹 접속 주소 확인
kubectl get svc svc-nlb-ip-type -o jsonpath={.status.loadBalancer.ingress[0].hostname} | awk '{ print "Pod Web URL = http://"$1 }'

// NLB 도메인 변수 선언
NLB=$(kubectl get svc svc-nlb-ip-type -o jsonpath={.status.loadBalancer.ingress[0].hostname})
// 확인
echo $NLB

// 웹 접속 확인 (1)
curl -s $NLB

// 웹 접속 확인 (100회 - 카운팅)
for i in {1..100}; do curl -s $NLB | grep Hostname ; done | sort | uniq -c | sort -nr

NLB를 통해서 2개의 파드에게 대략 5:5의 비율로 로드밸런싱이 수행되는 것을 확인할 수 있다.

파드의 수량 조정

파드의 수를 변경하면🆙 어떻게 될까? 자동으로 타켓 그룹으로 새롭게 생긴 파드도 들어갈까?

// 파드 3대로 조정
kubectl scale deployment deploy-echo --replicas=3

// 웹 접속 확인 (100회 - 카운팅)
for i in {1..100}; do curl -s $NLB | grep Hostname ; done | sort | uniq -c | sort -nr

새롭게 생성된 파드 또한 자동으로 같은 타겟 그룹에 들어가 NLB를 통해서 트래픽을 함께 나눠받는 것을 확인할 수 있다.


ALB

ALB는 7계층 로드밸런서로 EKS에서 Ingress에 해당한다.
Ingress 생성 시 자동으로 생성되며, Ingress를 사용하므로 파드까지의 라우팅을 담당하는 k8s 내부 서비스(ClusterIP 또는 NodePort)가 필요하다.

파드 배포 및 Ingress 배포

파드를 배포하고 인그레스를 생성하도록 하자.
인그레스를 배포하므로 앞서 말했듯, 인그레스가 라우팅할 k8s 서비스가 당연히 필요로 하다. (여기서는 NodePort 형식으로 사용하였다)

apiVersion: v1
kind: Namespace
metadata:
  name: game-2048
---
apiVersion: apps/v1
kind: Deployment
metadata:
  namespace: game-2048
  name: deployment-2048
spec:
  selector:
    matchLabels:
      app.kubernetes.io/name: app-2048
  replicas: 2
  template:
    metadata:
      labels:
        app.kubernetes.io/name: app-2048
    spec:
      containers:
      - image: public.ecr.aws/l6m2t8p7/docker-2048:latest
        imagePullPolicy: Always
        name: app-2048
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  namespace: game-2048
  name: service-2048
spec:
  ports:
    - port: 80
      targetPort: 80
      protocol: TCP
  type: NodePort
  selector:
    app.kubernetes.io/name: app-2048
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  namespace: game-2048
  name: ingress-2048
  annotations:
    alb.ingress.kubernetes.io/scheme: internet-facing
    alb.ingress.kubernetes.io/target-type: ip
spec:
  ingressClassName: alb
  rules:
    - http:
        paths:
        - path: /
          pathType: Prefix
          backend:
            service:
              name: service-2048
              port:
                number: 80

배포 확인

위 yaml 파일을 배포하고 확인해 보도록 하자.

// 디플로이먼트 & 인그레스 배포
kubectl apply -f ingress1.yaml

// 정보 확인
kubectl get pod -n game-2048 -o wide

kubectl get targetgroupbindings -n game-2048

// Ingress 확인
kubectl describe ingress -n game-2048 ingress-2048

다음과 같이 파드 2개가 배포되고, ClusterIP 서비스에 연결된 상태로 Ingress가 이를 라우팅하고 있는 형태이다.

AWS콘솔에서 배포 확인

실제로 Ingress에 의해서 ALB가 생성된 것을 확인할 수 있다.

리스너 및 규칙을 확인해보자.
/ 로 시작하는 경우, 파드IP로 라우팅 되도록 지정된 것을 확인할 수 있다.

ALB의 DNS 주소로 접속하면 다음과 같이 배포된 파드(2048게임)으로 접속할 수 있다.

파드 수량 조절

// 파드 5대로 조정
kubectl scale deployment -n game-2048 deployment-2048 --replicas 3

파드 수량을 조절하면 실제 대상 그룹 또한 늘어나는 것을 NLB와 동일하게 확인할 수 있다.


Reference📎 | CloudNet@와 함께하는 Amazon EKS 기본 강의

profile
붉은 배 오색 딱다구리 개발자 🦃Cloud & DevOps

0개의 댓글