EKS에 Helm으로 AWS Load Balancer Controller 설치하기

brillog·2024년 1월 13일
0

Kubernetes

목록 보기
10/11

AWS Load Balancer Controller 추가 기능 설치를 참고하여 작성하였습니다.

Prerequisites

EKS 클러스터에는 OpenID Connect (OIDC) 발급자 URL이 연결되어 있습니다. 서비스 계정에 IAM 역할을 사용하려면 클러스터의 OIDC 발급자 URL에 IAM OIDC 제공업체가 있어야 합니다.

OIDC provider Associate

Kubernetes Service Account에 IAM Role을 부여하기 위해서는 IAM OIDC Provider가 활성화되어 있어야 합니다. 여기서 말하는 '활성화'는 EKS 클러스터와 IAM OIDC Provider의 association을 의미합니다.

OIDC provider 생성

IAM OIDC Provider는 기본적으로 활성화되어 있지 않기 때문에 (default: not enabled) 하기 명령어를 이용하여 OIDC provider를 생성합니다.

$ eksctl utils associate-iam-oidc-provider --cluster=<EKS_CLUSTER_NAME> --approve

생성된 IAM OIDC provider 확인

위 명령어로 생성되는 Provider 명은 oidc.eks.ap-northeast-2.amazonaws.com/id/<CLUSTER_ID>이며 생성된 IAM OIDC provider는 IAM 콘솔의 Identity providers 항목에서 확인할 수 있습니다.

IAM OIDC provider

IAM Role 생성

위와 같이 IAM OIDC provider가 생성된 것을 확인했다면 이제 AWS Load Balancer Controller가 사용할 IAM Role을 생성해 보겠습니다.

IAM Policy 생성

IAM Policy는 다음과 같으며 하기 링크를 통해 다운로드가 가능합니다.

  • '미국 동부(us-east)' or '미국 서부(us-west)' AWS 리전
    $ curl -O https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/v2.5.4/docs/install/iam_policy_us-gov.json
  • 기타 모든 AWS 리전
    $ curl -O https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/v2.5.4/docs/install/iam_policy.json

저는 서울 리전(ap-northeast-2)을 사용하고 있으므로 '기타 모든 AWS 리전' Policy를 다운받아 IAM Policy를 생성하였습니다.

# 기타 모든 AWS 리전

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "iam:CreateServiceLinkedRole"
            ],
            "Resource": "*",
            "Condition": {
                "StringEquals": {
                    "iam:AWSServiceName": "elasticloadbalancing.amazonaws.com"
                }
            }
        },
        {
            "Effect": "Allow",
            "Action": [
                "ec2:DescribeAccountAttributes",
                "ec2:DescribeAddresses",
                "ec2:DescribeAvailabilityZones",
                "ec2:DescribeInternetGateways",
                ...
 ...

IAM Role 생성

IAM Role을 생성하여 위에서 생성한 IAM Policy를 붙입니다. 그 다음 생성한 IAM Role의 Trust relationship을 수정합니다.

하기 예시에서 ACCOUNT_ID, REGION_CODE, CLUSTER_ID를 변경하면 됩니다.
(클러스터가 '미국 동부(us-east)' or '미국 서부(us-west)' 리전에 있는 경우는 arn:aws:arn:aws-us-gov:로 바꿔야 합니다.)

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Federated": "arn:aws:iam::<ACCOUNT_ID>:oidc-provider/oidc.eks.<REGION_CODE>.amazonaws.com/id/<CLUSTER_ID>"
            },
            "Action": "sts:AssumeRoleWithWebIdentity",
            "Condition": {
                "StringEquals": {
                    "oidc.eks.<REGION_CODE>.amazonaws.com/id/<CLUSTER_ID>:aud": "sts.amazonaws.com",
                    "oidc.eks.<REGION_CODE>.amazonaws.com/id/<CLUSTER_ID>:sub": "system:serviceaccount:kube-system:aws-load-balancer-controller"
                }
            }
        }
    ]
}

ServiceAccount 생성

생성한 IAM Role을 annotation으로 사용하는 ServiceAccount를 kube-system 네임스페이스에 배포합니다.

# aws-load-balancer-controller-service-account.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  labels:
    app.kubernetes.io/component: controller
    app.kubernetes.io/name: aws-load-balancer-controller
  name: aws-load-balancer-controller
  namespace: kube-system
  annotations:
    eks.amazonaws.com/role-arn: arn:aws:iam::<ACCOUNT_ID>:role/<위에서_생성한_IAM_ROLE_NAME>
# ServiceAccount 배포
$ kubectl apply -f aws-load-balancer-controller-service-account.yaml
# 생성 확인
kubectl get serviceaccount -n kube-system
NAME                                 SECRETS   AGE
attachdetach-controller              0         145d
aws-cloud-provider                   0         145d
aws-load-balancer-controller         0         18s  # 생성됨
...

AWS Load Balancer Controller 설치

helm으로 설치

이제 사전 준비가 완료되었으니 helm을 사용하여 AWS Load balancer controller를 설치해 보겠습니다.

  1. helm V3 이상을 사용하여야 합니다.

    $ helm version
    version.BuildInfo{Version:"v3.8.2", GitCommit:"6e3701edea09e5d55a8ca2aae03a68917630e91b", GitTreeState:"clean", GoVersion:"go1.17.5"}
  2. eks-charts 리포지토리를 추가합니다.

    $ helm repo add eks https://aws.github.io/eks-charts
    "eks" has been added to your repositories
    
    $ helm repo list
    NAME    URL                             
    eks     https://aws.github.io/eks-charts
  3. 최신 차트가 적용되도록 local repository를 업데이트합니다.

    $ helm repo update eks
    Hang tight while we grab the latest from your chart repositories...
    ...Successfully got an update from the "eks" chart repository
    Update Complete. ⎈Happy Helming!
  4. 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=<위에서_생성한_ServiceAccount_NAME>
  5. kube-system 네임스페이스 설치된 리소스들을 확인합니다.

    $ k get all -n kube-system
    NAME                                                READY   STATUS    RESTARTS   AGE
    pod/aws-load-balancer-controller-58df668c77-5k4gj   0/1     Pending   0          2m17s
    pod/aws-load-balancer-controller-58df668c77-6nk9h   0/1     Pending   0          2m17s
    ...
    
    NAME                                        TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)         AGE
    service/aws-load-balancer-webhook-service   ClusterIP   172.20.195.78   <none>        443/TCP         2m17s
    ...
    
    NAME                                           READY   UP-TO-DATE   AVAILABLE   AGE
    deployment.apps/aws-load-balancer-controller   0/2     2            0           2m17s
    ...
    
    NAME                                                      DESIRED   CURRENT   READY   AGE
    replicaset.apps/aws-load-balancer-controller-58df668c77   2         2         0       2m17s
    ...

ingress 동작 확인 테스트

nginx 생성

apiVersion: v1
kind: Pod
metadata:
  labels:
    app: nginx
  name: nginx
spec:
  containers:
    - image: nginx:latest
      name: nginx
      ports:
      - containerPort: 80

---
apiVersion: v1
kind: Service
metadata:
  name: service-nginx
  annotations:
    alb.ingress.kubernetes.io/healthcheck-path: "/"
spec:
  selector:
     app: nginx
  type: NodePort
  ports:
  - port: 80
    protocol: TCP
    targetPort: 80

mario 생성

apiVersion: v1
kind: Pod
metadata:
  labels:
    app: mario
  name: mario
spec:
  containers:
  - image: pengbai/docker-supermario
    name: mario
    ports:
    - containerPort: 8080

---
apiVersion: v1
kind: Service
metadata:
  name: service-mario
  annotations:
    alb.ingress.kubernetes.io/healthcheck-path: "/"
spec:
  selector:
     app: mario
  type: NodePort
  ports:
  - port: 80
    protocol: TCP
    targetPort: 8080

ingress 생성

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-test
  annotations:
    kubernetes.io/ingress.class: alb
    alb.ingress.kubernetes.io/scheme: internet-facing
    alb.ingress.kubernetes.io/target-type: instance
    alb.ingress.kubernetes.io/load-balancer-name: <생성할_LB_NAME>
    alb.ingress.kubernetes.io/subnets: <SUBNET_ID_1>,<SUBNET_ID_2>
    alb.ingress.kubernetes.io/certificate-arn: arn:aws:acm:<REGION-CODE>:<ACCOUNT_ID>:certificate/<CERTIFICATE_ID>
    alb.ingress.kubernetes.io/listen-ports: '[{"HTTP": 80}, {"HTTPS": 443}]'
    alb.ingress.kubernetes.io/ssl-redirect: '443'
spec:
  rules:
    - host: nginx.mytestdomain.com
      http:
        paths:
          - pathType: Prefix
            path: /
            backend:
              service:
                name: service-nginx
                port:
                  number: 80
    - host: mario.mytestdomain.com
      http:
        paths:
          - pathType: Prefix
            path: /
            backend:
              service:
                name: service-mario
                port:
                  number: 80

콘솔에서 ingress(ALB) 생성 확인

Ingress

IngressRule

도메인 설정

  • nginx.mytestdomain.com > ingress ALB의 DNS name
  • mario.mytestdomain.com > ingress ALB의 DNS name

Route53

서비스 접속 확인

nginx

mario


Reference

개인적으로 공부하며 작성한 글로, 내용에 오류가 있을 수 있습니다.

profile
Cloud & DevOps ♡

0개의 댓글