4주차 - CLB, ALB 그리고 aws-load-balancer-controller

월간-CS | 쿠버네티스 비기너 클래스
이민석's avatar
Aug 12, 2024
4주차 - CLB, ALB 그리고 aws-load-balancer-controller

지금까지

아래 과정을 수행하였습니다.

  1. 1주차 - Docker & EKS 기초

  2. 2주차 - 다양한 유형의 앱 배포하기

  3. 3주차 - Pod 그리고 RDS 연결

이번 주차에는

AWS ELB*가 무엇이고 어떤 타입이 있는지 알아봅니다.

ELB* : Elastic Load Balancer

AWS ELB Types

Elastic Load Balancing 기능에 따르면,
ELB에는 ALB, NLB, GLB, CLB 유형이 있고 각 유형 별로 세부적인 차이점이 있습니다.
(자세한 내용은 본 스터디의 범위를 벗어나므로 제외합니다.)

사전 준비 및 지식

  1. Private Subnet에 EKS NodeGruop 생성하기

  2. Service(Type: LoadBalancer)로 NLB 생성하기

Private Subnet에 EKS NodeGroup 생성하기

  1. EKS NodeGroup 생성하기

    eksctl create nodegroup --cluster=<CL_NAME>\
                            --region=us-east-1 \
                            --name=eksdemo1-ng-private1 \ 
                            --node-type=t3.medium \
                            --node-min=2 \
                            --node-max=4 \
                            --node-volume-size=20 \
                            --ssh-access \
                            --ssh-public-key=<KEYNAME> \
                            --managed \
                            --asg-access \
                            --external-dns-access \
                            --full-ecr-access \
                            --appmesh-access \
                            --alb-ingress-access \
                            --node-private-networking
  2. EKS NodeGroup 조회하기

    kubectl get nodes -o wide

Service(Type: LoadBalancer)로 NLB 생성하기

K8s Objects중에 Service를 사용하여,
AWS Elastic Load Balancer - Network Load Balancer를 생성할 수 있습니다.

apiVersion: v1
kind: Service
metadata:
  name: usermgmt-restapp-service
  labels:
    app: usermgmt-restapp
  annotations:
    service.beta.kubernetes.io/aws-load-balancer-type: nlb 
spec:
  type: LoadBalancer
  selector:
    app: usermgmt-app
  ports:
    - port: 8095
      targetPort: 8095
      nodePort: 31231

ALB 생성하기

과거에는 AWS ALB Ingress Controller였지만,
현재는 AWS Load Balancer Controller로 불리며, 이 AWS Load Balancer Controller의 작동 원리는 다음과 같습니다.

이름 그대로 과거에는 AWS ALB만 배포가 가능했지만,
현재는 ALB 와 NLB를 모두 배포할 수 있습니다.

  • AWS ALB Ingress Controller

    • AWS Application Load Balancer Only

    • Dosen’t support latest Ingress API Version(apiVersion: networking.k8s.io/v1) from Kubernetes Version 1.22 onwards

    • No Development releases, Son it will be deprecated.

  • AWS Load Balancer Controller

    • AWS Application and Network Load Balancer

    • K8s Ingress Object → AWS ALB

    • K8s Service Object → AWS NLB

    • Support latest and greatest from Ingress perspective

실제로 작동하는 방식은 다음과 같습니다.

OIDC Provider 생성하기

ServiceAccount에 권한을 할당하기 위해 EKS OIDC Provider를 생성해주세요.

eksctl utils associate-iam-oidc-provider \
   --region region-code \
   --cluster <cluster_name> \
   --approve

이후 아래 명령어를 통해서 EKS Cluster에서 IAM ServiceAccount가 있는지 확인할 수 있습니다.

eksctl get iamserviceaccount --cluster=<Cluster_Name>

단, 특정한 EKS Cluster에 대한 로컬 구성이 없다면 해당 명령어가 작동하지 않을 것입니다. 이 경우 아래 명령어를 통해서 ~/.kube/config을 고칠 수 있습니다.

aws eks --region <region> update-kubeconfig --name <cluster_name>

이후 아래 명령어를 통해서 설정 파일을 확인할 수 있습니다.

cat ~/.kube/config

IAM Policy & Role 생성하기 [Ref]

  1. AWS CLIv2로 IAM Policy 다운로드

    curl -o iam_policy_latest.json https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/main/docs/install/iam_policy.json
  2. AWS CLIv2로 IAM Policy 생성하기

    aws iam create-policy \
      --policy-name AWSLoadBalancerControllerIAMPolicy \
      --policy-document file://iam_policy_latest.json
  3. Kubectl로 K8s ServiceAccount 확인하기

    kubectl get sa -n kube-system
    kubectl get sa aws-load-balancer-controller -n kube-system
  4. Eksctl로 IAM ServiceAccount 생성하기

    eksctl create iamserviceaccount       \
      --cluster=<cluster>                 \
      --namespace=kube-system             \
      --name=aws-load-balancer-controller \
      --attach-policy-arn=<AWS CLIv2로 IAM Policy 생성하기의 ARN> \
      --override-existing-serviceaccounts \
      --approve
  5. Eksctl로 IAM ServiceAccount 확인하기

    eksctl get iamserviceaccount --cluster=<cluster>

Helm으로 AWS LoadBalancer Controller 설치하기

  1. AWS Load Balancer Controller 릴리즈하기

    helm install aws-load-balancer-controller eks/aws-load-balancer-contoller \
      -n kube-system \
      --set clusterName=<cluster> \
      --set serviceAccount.create=false \
      --set serviceAccount.name=aws-load-balancer \
      --set region=<region> \
      --set vpcId=<vpc_id> \
      --set image.repository=<regional_official_account_id>.dkr.ecr.<region>.amazonaws.com/amazon/aws-load-balancer-controller

강의에서는 나오지 않았지만 아래와 같은 방법도 가능합니다.

  1. values.yaml 파일 생성하기

    clusterName: <cluster>
    serviceAccount:
      create: false
      name: aws-load-balancer
    
    region: <region>
    vpcId: <vpc_id>
    image:
      repository: <regional_official_account_id>.dkr.ecr.<region>.amazonaws.com/amazon/aws-load-balancer-controller
  2. AWS Load Balancer Controller 릴리즈하기

    helm install aws-load-balancer-controller eks/aws-load-balancer-controller \
      --values values.yaml

물론 아래와 같이 2가지 방법으로 Helm Chart를 테스트할 수 있습니다.

  1. --dry-run 모드 사용하여 테스트 (kubeconfig 필요)

    helm install aws-load-balancer-controller \
       eks/aws-load-balancer-controller \
       --values values.yaml \
       --dry-run
  2. template으로 Helm Syntax 검사 (kubeconfig 불필요)

    helm template aws-load-balancer-controller \
       eks/aws-load-balancer-controller        \
       --values values.yaml > output.yaml

    마지막 라인에 붙은 > output.yaml 을 제거하면,
    터미널에서 출력값을 바로 볼 수 있습니다.

AWS LoadBalancer Controller Deployment 확인하기

아래 명령어를 통해서 aws-loadbalancer-controller를 확인해보세요.

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

주요하게 봐야할 부분은 다음과 같습니다.

  1. ServiceAccount가 등록되어 있음 : aws-load-balancer-controller

  2. Volumes에 cert가 등록되어 있음 : aws-load-balancer-tls

AWS LBC WebHook

AWS Load Balancer Controller에서는
WebHook Service(ClusterIP)로 들어오는 443 요청이
WebHook Server(9443)으로 포워딩 됩니다.

해당 WebHook Server는 deployment/aws-load-balancer-controller에 해당합니다.

kubectl -n kube-system get svc aws-load-balancer-webhook-service -o yaml
kubectl -n kube-system get deployment aws-load-balancer-controller -o yaml

번외로 Metric Server(8000)도 존재합니다.

AWS Load Balancer Controller Log 확인

디버깅 및 다양한 목적으로 AWS Load Balancer Controller Log를 확인하기 위해서 다음 명령어를 사용할 수 있습니다.

  1. aws-load-balancer-controller의 pods 조회

    kubectl -n kube-system get pods
  2. 해당 pods의 로그 조회

    kubectl -n kube-system logs -f aws-load-balancer-controller-5d9d9d7466-8wjgw

추가적으로 다음과 같은 내부 구성들을 더 자세하게 확인할 수도 있습니다.

kubectl -n kube-system get secrets -o yaml
kubectl -n kube-system get secret <secret_name> -o yaml
kubectl -n kube-system get secret aws-load-balancer-controller-token-5w8th -o yaml | base64 .

kubectl -n kube-system get deploy aws-load-balancer-controller -o yaml

kubectl -n kube-system get pods
kubectl -n kube-system get pod <pod_name> -o yaml
kubectl -n kube-system get pod aws-load-balancer-controller-65b4f64d6c
kubectl -n kube-system

Verify AWS Load Balancer Controller Logs

Verify AWS Load Balancer Controller k8s Service Account

Verify TLS Certs for AWS Load Balancer Controller - Internals

K8s IngressClass란?

만약 EKS Cluster안에 여러개의 Ingress Controller가 있다고 생각해보겠습니다.

  1. AWS EKS ALB Ingress Controller

  2. NGINX Ingress Controller

  3. AKS Application Gateway Ingress Controller

이렇게 여러 개의 Ingress Controller가 있을 때,
어떤 Ingress Controller를 사용할지를 어떻게 결정할 수 있을까요? 이때 사용하는 것이 IngressClass입니다.

apiVersion: networking.k8s.io/v1
kind: IngressClass
metadata:
  name: my-aws-ingress-class
  annotations:
    ingressclass.kubernetes.io/is-default-class: "true"

spec:
  controller: ingress.k8s.aws/alb

K8s IngressResource란?

그리고 이 IngressClass를 참조하여 IngressResource가 생성 됩니다.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-nginxapp1
  labels:
    app: app1-nginx
  annotations:
    alb.ingress.kubernetes.io/load-balancer-name/app1ingress
    alb.ingress.kubernetes.io/scheme: internet-facing

spec:
  ingressClassName: my-aws-ingress-class
  defaultBackend:
    service:
      name: app1-nginx-nodeprt-service
      port:
        number: 80

앞서 IngressClass에서 is-default-class: true를 설정하지 않은 경우에는 IngressResource에서 .spec.ingressClassName을 지정해야합니다.

If IngressClass is not defined as is-default-class: true then in IngressResource we need to define the .spec.ingressClassName in IngressResource.

K8s Ingress Manifest Key Items 소개

  1. Ingress Annotations : AW ELB 설정에 반영

  2. Ingress ClassName : 어떤 IngressClass를 선택할 것인지

  3. Ingress Spec : Ingress Routing Rules, Default Backend

사실 중요한 내용들은 AWS Load Balancer Controller 공식 문서에 대부분 포함되어 있습니다. 트러블 슈팅은 kubernetes-sigs/aws-load-balancer-controller Issues를 참고하는 것이 좋습니다.

결론

전체적으로 aws-load-balancer-controller를 이용해서 AWS ALB와 함께 어플리케이션을 배포하는 방법을 배웠습니다.

  1. aws-load-balancer-controller : Helm Chart로 배포

    1. Service : WebHook 443 요청 받아서 9443으로 포워딩..

    2. Deployment, ReplicaSet, Pods : 요청 처리..!

    3. ServiceAccount : Deployment에 IAM Role을 사용할 수 있도록 함. OIDC Provider 방식으로 생성하여 할당되어 있음. 일반적인 sts:assumRole과 전혀 다름.

  2. IngressClass : Plugin과 연결 = aws-load-balancer-controller와 연결

  3. Ingress : IngressClass를 어떤 것을 쓸지 결정하며 실제로 AWS ALB를 생성하고 라우팅을 Service에 진행

  4. Service : Managed NodeGroup의 대상 Node에 Inbound Traffic을 열고 요청을 개별 Pods들에게 흩뿌림

  5. Deployment : ReplicaSet으로 앱 관리, 블루그린…

  6. ReplicaSet : Pods 수량 조절

  7. Pods : 앱

Share article

Unchaptered