AWS Load Balancer Controller

신동수·2024년 3월 18일

K8S

목록 보기
3/19

AWS Loadbalencer Controller?

쿠버네티스가 외부의 트래픽을 받기 위해 Ingress 리소스를 생성할 경우 자동으로 AWS Load Balancer Controller가 트리거하여 ingress.yaml 템플릿에 명시된대로 로드밸런서를 생성해주는 컨트롤러이다.
즉, Cluster에 Ingress 자원이 생성될 때 ELB 및 필요한 자원이 생성되도록 Trigger하는 컨트롤러이다.
Ingress 자원들은 ELB를 구성하여 HTTP,HTTPS, TCP 트래픽을 클러스터 내 Pod로 라우팅하게 된다.

AWS Load Balancer Controller
위 Github 에서 내용 확인할 수 있다.
AWS Load Balancer Controller 추가 기능 설치
또한 위 링크에서는 설치 관련된 내용도 함께 확인할 수 있다.

IRSA (Identity Role as a Servic account)?

AWS 는 IAM ( Identity And Access Management ) 를 이용해서 RBAC를 구현하였는데 이를 통해서 역할을 통해서 접근을 제한할 수 있게 된다. EKS 에서는 Service Account에 annotation을 통해서 IAM의 Role을 부여하고 이를 통해서 해당 Service Account를 사용하는 Service는 해당 권한을 갖을 수 있게 되는 것이다. 이개념이 IRSA이다.
Annotation을 통해서 role을 부여할 때 OIDC ( OpenID Connect) issuer URL 이 사용되게 된다. 따라서 EKS 에서 IRSA 라는 개념을 적용하여 사용하기 위한 도구로 OIDC identity provider를 만들어 주어야한다.

OIDC (OpenID Connect)?

OIDC 는 간단한 인증 레이어로 OAuth2.0 프로토콜을 기반으로 하여 만들어졌다. Oauth2.0을 기반으로 만들어 졌다보니 동작하는 원리는 Oauth2.0의 인증과정과 흡사하다.
그렇다면 OAuth2.0 에서 더 나아가 OIDC를 사용하는 이유는 무엇일까?
OAuth2.0은 단순 인가(Authorization) 이 목적이었다면 OIDC는 인가와 인증(Authentication)을 같이 하기 위한 목적이 있다.
OAuth2.0을 통해서 받은 AccessToken에는 사용자의 신원정보는 없고 이를 통한 접근권한만 갖게된다. 따라서 AccessToken만으로는 누구인지 식별을 할 수가 없는 것이다. 따라서 이 AccessToken을 가지고 Resource Server에 요청을 하여서 얻어와야 하는데 그러면 2번의 작업을 해야하는 불리함이 생기게 된다.
OIDC는 AccessToken과 ID Token이 발행되는데 이 ID Token이 신원정보를 갖고 있는 토큰이 된다.

OAuth 2.0

OAuth 2.0(Open Authorization 2.0, OAuth2)은 인증을 위한 개방형 표준 프로토콜.

이 프로토콜에서는 Third-Party 프로그램에게 리소스 소유자를 대신하여 리소스 서버에서 제공하는 자원에 대한 접근 권한을 위임하는 방식을 제공한다. 구글, 페이스북, 카카오, 네이버 등에서 제공하는 간편 로그인 기능도 OAuth2 프로토콜 기반의 사용자 인증 기능을 제공하고 있다.

추가 링크 : OAuth 2.0

인그레스 컨트롤러


인그레스(Ingress) 는 주로 클러스터 외부에서 쿠버네티스 내부로 접근할 때, 요청들을 어떻게 처리할지 정의해놓은 규칙이자 리소스 오브젝트이다.
외부의 요청이 내부로 접근하기 위한 관문의 역할을 하며, 외부 요청에 대한 로드 밸런싱, TLS/SSL 인증서 처리, HTTP 경로에 대한 라우팅 등을 설정할 수 있다.

쿠버네티스에서 앱을 서비스할 수 있도록 Port 노출, 부하 분산 기능을 가진 Service 와 Ingress 를 제공하며 각자의 역할이 있다.

  • Service : 요청 Pod 에 전달 (L4, NLB)
    - ClusterIP : 클러스터 내부 접근 허용
    - NodePort : 클러스터 외부 접근 허용, 호스트IP:PORT 방식의 접근
    - LoadBalancer : 클러스터 외부 접근 허용, 로드밸런서DNS:PORT 방식의 접근 (기본적으로 CLB)
  • Ingress : HTTP, HTTPS 요청을 규칙(Rule)에 따라 Service 에 전달 (L7, ALB)

EKS 에서 AWS Loadbalencer Controller 를 통해 ELB 생성을 해야한다면 조건이 있다.

  • 다른 가용 영역에 존재하는 2개 이상의 Subnet 이 존재해야한다.
  • 서브넷 Tag 조건 [참고]EKS Subnet 요구사항
  • Private Subnet
    • key : kubernetes.io/role/internal-elb value : 1
    • key : kubernetes.io/cluster/<Cluster_Name> value : shared (EKS 1.18 까지만 있어야 하며, 1.19 버전부터는 필요없음)
  • Public Subnet
    • key : kubernetes.io/role/elb value : 1
    • key : kubernetes.io/cluster/<Cluster_Name> value : shared (EKS 1.18 까지만 있어야 하며, 1.19 버전부터는 필요없음)

AWS Loadbalencer Controller 생성

k8s 마스터 노드 호출의 위한 Bastion 설정

# Bastion에서 진행하였고, OS 는 AmazonLinux2, System 은 amd64 로 진행하였다.

# AccessKey 설정
$ aws configure
# Cluster 사용을 위한 사용자 업데이트
$ aws eks update-kubeconfig --name <ClusterName> --region ap-northeast-2
Added new context arn:aws:eks:ap-northeast-2:<Account>:cluster/eks-eks to /home/ec2-user/.kube/config

# eksctl 다운로드
$ uname -s
$ curl --silent --location "https://github.com/weaveworks/eksctl/releases/latest/download/eksctl_$(uname -s)_amd64.tar.gz" | tar xz -C /tmp
$ sudo mv /tmp/eksctl /usr/local/bin
$ eksctl version

# kubectl 다운로드
$ curl -LO https://dl.k8s.io/release/v1.29.2/bin/linux/amd64/kubectl
$ chmod +x kubectl
$ sudo mv kubectl /usr/local/bin
$ kubectl version --version

# 아래 내용과 같이 확인이 된다면 AWS CLI 와 EKS Update 항목 실행
$ kubectl get nodes
error: exec plugin: invalid apiVersion "client.authentication.k8s.io/v1alpha1"

# AWS CLI Version2 다운로드
$ curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
$ unzip awscliv2.zip
$ sudo ./aws/install --bin-dir /usr/local/bin --install-dir /usr/local/aws-cli --update
$ sudo mv /usr/local/bin/aws /usr/bin
$ aws --version

# EKS Updatae
$ aws eks update-kubeconfig --name <ClusterName> --region ap-northeast-2

# OIDC 자격 증명 공급자 인증
$ aws eks describe-cluster --name <ClusterName> --query "cluster.identity.oidc.issuer" --output text
https://oidc.eks.ap-northeast-2.amazonaws.com/id/BC12345667890ABCDEFGHIJKL1234567
$ eksctl utils associate-iam-oidc-provider --cluster <ClusterName> --approve
# 확인
$ aws iam list-open-id-connect-providers
{
    "OpenIDConnectProviderList": [
        {
            "Arn": "arn:aws:iam::605983240948:oidc-provider/oidc.eks.ap-northeast-2.amazonaws.com/id/BC12345667890ABCDEFGHIJKL1234567"
        }
    ]
}


AWS IAM -> 자격 증명 공급자 공급자 리스트에서 확인할 수 있다.

AWS LoadBalancer Controller 생성

AWS Load Balancer Controller 추가 기능 설치
EKS-Workshop
위 2개의 문서와 워크샵 내용을 기반으로 작성 하였다.

# Bastion에서 설정

# IAM Policy Json 파일 다운로드
$ curl -O https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/v2.5.4/docs/install/iam_policy.json
# Policy 생성
$ aws iam create-policy --policy-name AWSLoadBalancerControllerIAMPolicy  --policy-document file://iam_policy.json
# ServiceAccount Role 생성
$ eksctl create iamserviceaccount --cluster <ClusterName> --namespace kube-system --name aws-load-balancer-controller --attach-policy-arn=arn:aws:iam::<Account>:policy/AWSLoadBalancerControllerIAMPolicy --override-existing-serviceaccounts --approve
# ServiceAccount 가 생성 확인
$ kubectl get sa aws-load-balancer-controller -n kube-system -o yaml

# 인증서 구성을 웹훅에 삽입할 수 있도록 쿠버네티스 클러스터 내에서 TLS인증서를 자동으로 관리하는 cert-manager 를 설치
$ kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.12.0/cert-manager.yaml
# Load Balancer 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
# **아래 캡처 확인 후 yaml 내용 수정**
# kubectl 로 수정한 v2_5_4_full.yaml 파일을 배포
$ 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
# Cluster 에 배포
$ kubectl apply -f v2_5_4_ingclass.yaml
ingressclassparams.elbv2.k8s.aws/alb created
ingressclass.networking.k8s.io/alb created
# 컨트롤러 확인
$ kubectl get deployment  aws-load-balancer-controller -n kube-system
NAME                           READY   UP-TO-DATE   AVAILABLE   AGE
aws-load-balancer-controller   1/1     1            1           101s


ServiceAccount를 생성했으므로 다운로드 된 v2_5_4_full.yaml 파일을 열어 해당 sa 선언 섹션을 주석 (595 줄부터 603 줄 까지 주석)


863 줄에서 cluster-name 의 your-cluster-name 부분을 자신의 클러스터명으로 수정한다.


최종적으로 컨트롤러가 설치가 완료되었다.

배포 테스트

# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.14.2
        ports:
        - containerPort: 8

# service.yaml
apiVersion: v1
kind: Service
metadata:
  name: nginx-service
spec:
  type: NodePort
  selector:
    app: nginx
  ports:
  - port: 80

# ingress.yaml
apiVersion: v1
kind: Service
metadata:
  name: nginx-service
spec:
  type: NodePort
  selector:
    app: nginx
  ports:
  - port: 80
[ec2-user@ip-10-10-1-219 nginx]$ cat ingress.yaml 
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: nginx-ingress
  annotations:
    kubernetes.io/ingress.class: alb
    alb.ingress.kubernetes.io/scheme: internet-facing
    alb.ingress.kubernetes.io/load-balancer-name: nginx-load-balancer-test
    alb.ingress.kubernetes.io/target-type: 'instance'
spec:
  rules:
    - http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: nginx-service
                port:
                  number: 80
# deployment.yaml 배포
$ kubectl apply -f deployment.yaml

# service.yaml 배포
$ kubectl apply -f service.yaml

# ingress.yaml 배포
$ kubectl apply -f ingress.yaml

# 확인
kubectl get all
NAME                                    READY   STATUS    RESTARTS   AGE
pod/nginx-deployment-86dcfdf4c6-7n7l6   1/1     Running   0          4m38s
pod/nginx-deployment-86dcfdf4c6-j28vk   1/1     Running   0          4m38s

NAME                    TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
service/kubernetes      ClusterIP   172.16.0.1      <none>        443/TCP        175m
service/nginx-service   NodePort    172.16.235.92   <none>        80:32109/TCP   4m33s

NAME                               READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/nginx-deployment   2/2     2            2           4m38s

NAME                                          DESIRED   CURRENT   READY   AGE
replicaset.apps/nginx-deployment-86dcfdf4c6   2         2         2       4m38s

# Ingress 확인
kubectl get ingress
NAME            CLASS    HOSTS   ADDRESS                                                                PORTS   AGE
nginx-ingress   <none>   *       nginx-load-balancer-test-1118613452.ap-northeast-2.elb.amazonaws.com   80      3m18s




위와 같이 Nginx 접속을 위한 ALB, Target Group 등 설정이 된 것을 확인할 수 있었다. 또한 프로비저닝이 완료가 된다면 ALB DNS 로 접속을 하여 서비스 확인을 하도록 하겠다.


프로비저닝이 끝나고 해당 DNS 주소로 접속을 해보니 Nginx 서비스에 정상 접근이 되는 것을 확인할 수 있었다.

profile
조금씩 성장하는 DevOps 엔지니어가 되겠습니다. 😄

0개의 댓글