Among Us - Yellow Crewmate AWS EKS에서 ALB를 Ingress Controller로 사용해보자

DevOps/Kubernetes

AWS EKS에서 ALB를 Ingress Controller로 사용해보자

감쟈! 2021. 10. 17. 20:10

쿠버네티스 클러스터 외부에서 내부로 통신하기 위해서는 NodePort, LoadBalancer 또는 Ingress를 사용하는 방법이 있다. 이번 게시물에서는 EKS 클러스터에서 Ingress Controller로 ALB를 사용하고 간단한 애플리케이션을 배포하여 테스트하는 과정에 대해서 이야기할 것이다.

 

우선, 본문에 들어가기에 앞서 외부와 통신하는 3가지 방법의 차이점에 대해서 적어보고자 한다.

 

NodePort

NodePort는 노드의 IP와 30000-32767 사이의 포트를 노출시켜 외부와 통신하는 방법이다.

 

이 방식은 1) 하나의 서비스당 하나의 포트만 할당할 수 있다는 점, 2) 포트가 제한적이라는 점, 3) IP가 바뀌면 접속 주소가 바뀐다는 점들을 고려하여 실제 서비스에서는 이 방식으로 서비스를 노출시키는 것을 추천하지 않는다.

 

그럼 이걸 언제 쓰느냐?? 

쉽고 간단한 설정으로 인해서 테스트 용으로 사용하거나 임시로 사용하기에 적합하다고 생각한다.

 

 

LoadBalancer

LoadBalancer 를 이용하여 외부와 통신할 수 있게될 뿐더러, 부하분산 기능까지 가능하기 때문에 가장 일반적인 통신 방법이다.

 

이 방식은 ExternalIP 라는 하나의 IP를 제공하여 외부와 통신하게 된다. LoadBalancer는 Service 타입 자체만으로는 사용할 수 없기 때문에 외부의 LoadBalancer를 사용해야 한다. MetalLB나, AWS의 NLB, 또는 다른 퍼블릭 클라우드에서 제공하는 LoadBalancer를 사용할 수 있다.

 

Ingress

Ingress는 위의 두 방식과는 다르게 Service의 종류는 아니고 Ingress 그 자체가 하나의 Kind로 작동한다.

 

위의 그림과 같이 Ingress는Ingress Controller를 사용하여 도메인별로 나누어 서로 다른 Service로 트래픽을 라우팅하는것이 가능하다. Ingress는 외부와의 통신을 가능하게 해주고, LoadBalancer 기능, 도메인 기반의 라우팅, SSL 인증서 처리를 할 수 있게 정의해두는 역할이고, 실제로 그것을 가능하게 해주는 것은 Ingress Controller의 역할이다.

 

퍼블릭 클라우드를 사용하여 쿠버네티스 클러스터를 구축했다면 클라우드에서 제공하는 ALB를 사용하여 쉽게 Ingress를 사용할 수 있다. 클라우드를 사용하지 않는다면 Kubernetes에서 제공하는 nginx-ingress를 사용하는 방법이 있다.

 

이번글에서 진행할 과정은 AWS의 EKS를 사용하여 클러스터를 구축하고 ALB를 Ingress Controller로 사용하는 방법을 진행할 예정이다.

 


1. 준비사항

1. EKS 클러스터가 미리 구축되어 있어야 한다.

2. kubectl 이 설치되어 있어야 한다.

3. eksctl이 설치되어 있어야 한다.

4. aws cli 이 설치되어 있어야 한다.

5. iam role과 policy 생성 권한이 있어야 한다.

 

 

 

2. IAM ServiceAccount 

 

1. 먼저 클러스터에서 API Server 또는 외부 서비스에 인증하는데에 사용되는 Service Account에 IAM role을 적용하기 위해서 생성한 클러스터에는 IAM OIDC provider가 필요하다.

eksctl utils associate-iam-oidc-provider \
    --region ap-northeast-2 \ # Your Region
    --cluster eks\ # Your Cluster Name
    --approve

 

2. 다음은 IAM에 적용할 Policy를 생성하는 과정이다.

aws iam create-policy \
    --policy-name AWSLoadBalancerControllerIAMPolicy \
    --policy-document https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/main/docs/install/iam_policy.json

 

 

3. 위에서 생성한 Policy를 적용한 iamserviceaccount를 생성해준다.

여기까지 serviceaccount가 제대로 생성되었다면 EKS클러스터에서 ALB를 Ingress Controller로 사용하기 위한 준비는 끝이다.

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

 

 

 

2. Ingress Controller

 

1. Ingress Controller를 설치하기 전에 Cert-manager를 설치하자.

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

kubectl apply --validate=false -f https://github.com/jetstack/cert-manager/releases/download/v1.4.1/cert-manager.yaml

 

2. 다음으로 ALB가 사용할 서브넷을 Tags를 이용하여 미리 지정해주어야 한다. 

서브넷이 public 인지, private 인지 생각하며 알맞는 Tags를 달아주자. 

kubernetes.io/cluster/<cluster-name> = shared 
kubernetes.io/role/internal-elb = 1 # internal
kubernetes.io/role/elb = 1  # internet-facing

 

 

3. 다음으로 Ingress Controller를 배포하기 위한 yaml파일을 다운받는다.

wget https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/v2.2.1/docs/install/v2_2_1_full.yaml

 

4. 다운받은 yaml파일을 배포하기 전에 파일을 다음과 같이 수정해주어야 한다.

Deployment 부분의 args에서 아래와 같이 추가해주자.

 

    spec:
      containers:
      - args:
        - --cluster-name=eks # Your cluster name
        - --ingress-class=alb   # ingress에 사용할 loadbalancer 정의 
        - --aws-vpc-id=vpc-0c78bbfadc749caab  # Your VPC ID
        - --aws-region=ap-northeast-2   # Your Region
        image: amazon/aws-alb-ingress-controller:v2.2.1

 

 

 

5. yaml파일 수정 후 배포해주고 제대로 생성되었는지 확인해주자. 

$ kubectl apply -f v2_2_1_full.yaml



$ kubectl get deploy -n kube-system
NAME                           READY   UP-TO-DATE   AVAILABLE   AGE
aws-load-balancer-controller   1/1     1            1           109m
coredns                        2/2     2            2           142m

 

6. Ingress Controller가 제대로 작동하고 있는지 확인하기 위해서 Pod의 log도 살펴보자

$ kubectl get po -n kube-system
NAME                                            READY   STATUS    RESTARTS   AGE
aws-load-balancer-controller-77c6ff8fcc-htffr   1/1     Running   0          111m
aws-node-bqscj                                  1/1     Running   0          135m
aws-node-rndrm                                  1/1     Running   0          135m
coredns-6dbb778559-6cdg9                        1/1     Running   0          144m
coredns-6dbb778559-xmwpc                        1/1     Running   0          144m
kube-proxy-mlfmp                                1/1     Running   0          135m
kube-proxy-tbncj                                1/1     Running   0          135m


$ kubectl logs -n kube-system aws-load-balancer-controller-77c6ff8fcc-htffr

 

 

3. Test Application Deploy

 

다음으로 Ingress를 적용하기 위한 간단한 Nginx Application을 배포해보도록 하자.

# nginx-deploy.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
spec:
  selector:
    matchLabels:
      run: nginx
  replicas: 2
  template:
    metadata:
      labels:
        run: nginx
    spec:
      containers:
      - name: nginx
        image: nginx
        ports:
        - containerPort: 80

nginx 서비스를 노출시킬 service도 생성하자. 

# nginx-svc.yaml

apiVersion: v1
kind: Service
metadata:
  name: nginx
  labels:
    run: nginx
spec:
  ports:
  - port: 80
    protocol: TCP
  selector:
    run: nginx

 

다음은 Ingress를 정의하는 내용이다.

ingress는 아래와 같이 annotations을 사용하여 리소스를 정의한다. 

 

https://kubernetes-sigs.github.io/aws-load-balancer-controller/v2.2/guide/ingress/annotations/  

위의 링크에서 사용가능한 annotations들을 확인할 수 있다.

 

# nginx-ingress.yaml

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: "ingress"
  annotations:
    kubernetes.io/ingress.class: alb
    alb.ingress.kubernetes.io/target-type: ip
    alb.ingress.kubernetes.io/scheme: internet-facing
spec:
  rules:
   - http:
      paths:
        - path: /*
          backend:
            serviceName: "nginx"
            servicePort: 80

 

여기서 Ingress가 제대로 생성이 되었다면 AWS 콘솔에서 ALB가 자동으로 생성된 것을 확인할 수 있다.

생성된 ALB와 타겟그룹을 확인해보자

 

(자동으로 생성된 ALB)

 

 

(ALB에 사용되는 타겟그룹) - 타겟그룹에 사용되는 2개의 워커노드 모두 healthy인것 확인하기.

 

 

여기까지가 ALB Ingress Controller를 설정하는 과정이다. 실제로 Ingress를 통해서 로드밸런싱이 되는지 이전에 배포했던 nginx를 통해서 확인해주자.

 

4. Ingress Loadbalancing test

 

위에서 배포했던 nginx를 통해서 ingress가 제대로 로드밸런싱 기능을 해주고 있는지 확인해보자.

$ kubectl get po
NAME                        READY   STATUS    RESTARTS   AGE
my-nginx-5b56ccd65f-vqq94   1/1     Running   0          143m
my-nginx-5b56ccd65f-x6989   1/1     Running   0          143m

 

동작중인 pod 컨테이너에 접속하여 웹페이지에 표시될 내용을 index.html에 적어주도록하자

 

$ kubectl exec my-nginx-5b56ccd65f-vqq94 -it -- /bin/bash

$ root@my-nginx-5b56ccd65f-vqq94:/# find -name index.html 2>/dev/null
./usr/share/nginx/html/index.html

$ root@my-nginx-5b56ccd65f-vqq94:/# echo nginx1 > ./usr/share/nginx/html/index.html

 

그리고 Ingress Controller로 사용중인 ALB의 DNS Name을 URL에 입력하면 nginx가 배포된 모습을 볼 수 있고, 제대로 로드밸런싱까지 해주고 있는것을 확인할 수 있다.