본문 바로가기
AWS/EKS

[AEWS2] 2-3. Service & AWS LoadBalancer Controller

by okms1017 2024. 3. 16.
728x90

✍ Posted by Immersive Builder  Seong
 

1. Service 

Service 란?

쿠버네티스 서비스는 컨테이너에 접속하기 위한 엔드포인트를 제공하는 방식입니다. 
파드가 삭제되고 재생성되는 경우 파드의 IP가 변경되므로 
백엔드 단에서 파드에 정상적으로 연결하기 위한 고정진입점을 제공하는 역할을 합니다. 
 
그리고 여러 파드로 트래픽을 부하분산하는 역할을 하기도 합니다. 

Service 종류 

ClusterIP 타입 
 
클러스터 내부에만 접속할 수 있는 가상 IP 주소가 생성됩니다.
 

Service - ClusterIP (CloudNet@)

NodePort 타입
 
클러스터의 모든 노드의 지정된 포트에 대한 접속이 컨테이너로 전달됩니다. 
클러스터 외부에서도 접속할 수 있습니다. 
 

Service - NodePort (CloudNet@)

LoadBalancer 타입
 
AWS 로드밸런서에 대한 접속이 컨테이너로 전송됩니다. 
외부 클라이언트가 로드밸런서 접속 시, 로드밸런서 → NodePort → iptables → 파드 → 컨테이너 순으로 전송되며, iptables의 분산룰을 통해 목적지 파드와 통신합니다.
 

Service - LoadBalancer (CloudNet@)

 


2. LoadBalancer Controller

LoadBalancer Controller 란?

AWS 로드밸런서에 대한 접속이 파드의 IP로 바로 전송되는 방식입니다. 
Bypass 통신(로드밸런서 → 파드 → 컨테이너)을 하므로 처리 성능이 향상됩니다. 
LoadBalancer Controller는 쿠버네티스 파드의 IP 정보를 AWS 로드밸런서에 지속적으로 제공하는 역할을 합니다. 
LoadBalancer Controller도 파드이므로 AWS와 쿠버네티스 간 인증을 구현해야 동작합니다. 
 

Service - LoadBalancer Controller (CloudNet@)

 

LoadBalancer Controller 배포 

 

# OIDC 정보 조회
$  aws eks describe-cluster --name $CLUSTER_NAME --query "cluster.identity.oidc.issuer" --output text
https://oidc.eks.ap-northeast-2.amazonaws.com/id/E7CBCE6208A87AE437A37D8A7BBADD03

 

Amazon EKS - OIDC

# IAM Policy - AWSLoadBalancerControllerIAMPolicy 생성
curl -O https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/v2.5.4/docs/install/iam_policy.json
aws iam create-policy --policy-name AWSLoadBalancerControllerIAMPolicy --policy-document file://iam_policy.json

# IAM Policy ARN 확인
$ aws iam get-policy --policy-arn arn:aws:iam::$ACCOUNT_ID:policy/AWSLoadBalancerControllerIAMPolicy --query 'Policy.Arn'
"arn:aws:iam::732659419746:policy/AWSLoadBalancerControllerIAMPolicy"

 

IAM Policy - AWSLoadBalancerControllerIAMPolicy

# AWS Load Balancer Controller를 위한 ServiceAccount를 생성
# IAM 역할 생성
$ eksctl create iamserviceaccount --cluster=$CLUSTER_NAME --namespace=kube-system --name=aws-load-balancer-controller --role-name AmazonEKSLoadBalancerControllerRole \
--attach-policy-arn=arn:aws:iam::$ACCOUNT_ID:policy/AWSLoadBalancerControllerIAMPolicy --override-existing-serviceaccounts --approve
```
   create IAM role for serviceaccount "kube-system/aws-load-balancer-controller",
   create serviceaccount "kube-system/aws-load-balancer-controller",
```

# IRSA 정보 확인
$ eksctl get iamserviceaccount --cluster $CLUSTER_NAME
NAMESPACE       NAME                            ROLE ARN
kube-system     aws-load-balancer-controller    arn:aws:iam::732659419746:role/AmazonEKSLoadBalancerControllerRole

# ServiceAccount 확인
$ kubectl get serviceaccounts -n kube-system aws-load-balancer-controller -o yaml | yh
apiVersion: v1
kind: ServiceAccount
metadata:
  annotations:
    eks.amazonaws.com/role-arn: arn:aws:iam::732659419746:role/AmazonEKSLoadBalancerControllerRole
  creationTimestamp: "2024-03-16T11:11:47Z"
  labels:
    app.kubernetes.io/managed-by: eksctl
  name: aws-load-balancer-controller
  namespace: kube-system
  resourceVersion: "317888"
  uid: 74ac0560-ea3e-4813-b8ca-89f7d414417b

 

Amazon CloudFormation - IAM role for serviceaccount "kube-system/aws-load-balancer-controller"
IAM Role - AmazonEKSLoadBalancerControllerRole

# Helm Chart 설치
$ helm repo add eks https://aws.github.io/eks-charts
"eks" has been added to your repositories
$ helm repo update
Hang tight while we grab the latest from your chart repositories...
...Successfully got an update from the "eks" chart repository
...Successfully got an update from the "geek-cookbook" chart repository
Update Complete. ⎈Happy Helming!⎈
$ helm repo list
NAME            URL
geek-cookbook   https://geek-cookbook.github.io/charts/
eks             https://aws.github.io/eks-charts

$ 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
NAME: aws-load-balancer-controller
LAST DEPLOYED: Sat Mar 16 20:23:16 2024
NAMESPACE: kube-system
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
AWS Load Balancer controller installed!

# 설치 확인 : aws-load-balancer-controller:v2.7.1
$ kubectl get crd
NAME                                         CREATED AT
cninodes.vpcresources.k8s.aws                2024-03-15T06:43:40Z
eniconfigs.crd.k8s.amazonaws.com             2024-03-15T06:44:44Z
ingressclassparams.elbv2.k8s.aws             2024-03-16T11:23:14Z (v)
policyendpoints.networking.k8s.aws           2024-03-15T06:43:41Z
securitygrouppolicies.vpcresources.k8s.aws   2024-03-15T06:43:40Z
targetgroupbindings.elbv2.k8s.aws            2024-03-16T11:23:14Z (v) 

$ kubectl get deployment -n kube-system aws-load-balancer-controller
NAME                           READY   UP-TO-DATE   AVAILABLE   AGE
aws-load-balancer-controller   2/2     2            2           3m13s
$ kubectl describe deploy -n kube-system aws-load-balancer-controller | grep 'Service Account'
  Service Account:  aws-load-balancer-controller

 

서비스/파드 배포 테스트 (NLB)

NLB 타입의 서비스와 파드 2개를 배포합니다.
 

$ cat echo-service-nlb.yaml 
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
---
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
    
$ kubectl apply -f echo-service-nlb.yaml

 

AWS 콘솔에서 80 포트로 리스닝 중인 네트워크 로드밸런서와 8080 포트로 바인딩되는 파드의 상태(healthy)를 확인할 수 있습니다. 또한, LoadBalancer Controller에 의해 파드의 IP(192.168.2.250, 192.168.3.59) 정보가 대시보드에 출력됩니다. 이것이 가능한 이유는 AWS VPC CNI 기반으로 동작하기 때문입니다. 
 

AWS Network LoadBalancer Info
AWS Network LoadBalancer - Listener
Target Group

새로 배포한 서비스에 외부 접속을 시도해봅니다. 
Target Group의 파드 2대에 트래픽이 골고루 분산됩니다.  
 

# echo service URL
$ kubectl get svc svc-nlb-ip-type -o jsonpath={.status.loadBalancer.ingress[0].hostname} | awk '{ print "Pod Web URL = http://"$1 }'
Pod Web URL = http://k8s-default-svcnlbip-be65ae3bfb-c4f864c633db8732.elb.ap-northeast-2.amazonaws.com

$ NLB=k8s-default-svcnlbip-be65ae3bfb-c4f864c633db8732.elb.ap-northeast-2.amazonaws.com
$ for i in {1..100}; do curl -s $NLB | grep Hostname ; done | sort | uniq -c | sort -nr
  50 Hostname: deploy-echo-7f579ff9d7-ltkz6
  50 Hostname: deploy-echo-7f579ff9d7-l8vhv

 
Target Group 파드 수를 조정하여 동작을 확인해봅니다. 
파드를 1개로 줄이면 모든 트래픽이 1개의 파드로 전송됩니다. 
다시 파드를 3개로 늘리면 트래픽이 분산되어 전송되는 모습입니다.  
 

# 파드 수: 2 → 1
$ kubectl scale deployment deploy-echo --replicas=1

## 모니터링(Health-check)
$ while true; do aws elbv2 describe-target-health --target-group-arn $TARGET_GROUP_ARN --output text; echo; done
TARGETHEALTHDESCRIPTIONS        8080
TARGET  ap-northeast-2b 192.168.2.250   8080
TARGETHEALTH    Target deregistration is in progress    Target.DeregistrationInProgress draining
TARGETHEALTHDESCRIPTIONS        8080
TARGET  ap-northeast-2c 192.168.3.59    8080
TARGETHEALTH    healthy

## 서비스 요청 Count 100 
$ for i in {1..100}; do curl -s --connect-timeout 1 $NLB | grep Hostname ; done | sort | uniq -c | sort -nr
    100 Hostname: deploy-echo-7f579ff9d7-l8vhv

# 파드 수: 1 → 3
$ kubectl scale deployment deploy-echo --replicas=3

## 모니터링(Health-check)
$ while true; do aws elbv2 describe-target-health --target-group-arn $TARGET_GROUP_ARN --output text; echo; done
TARGETHEALTHDESCRIPTIONS        8080
TARGET  ap-northeast-2b 192.168.2.28    8080
TARGETHEALTH    healthy
TARGETHEALTHDESCRIPTIONS        8080
TARGET  ap-northeast-2c 192.168.3.59    8080
TARGETHEALTH    healthy
TARGETHEALTHDESCRIPTIONS        8080
TARGET  ap-northeast-2a 192.168.1.217   8080
TARGETHEALTH    healthy

## 서비스 요청 Count 100 
$ for i in {1..100}; do curl -s --connect-timeout 1 $NLB | grep Hostname ; done | sort | uniq -c | sort -nr
     34 Hostname: deploy-echo-7f579ff9d7-54vzf
     33 Hostname: deploy-echo-7f579ff9d7-wwfkg
     33 Hostname: deploy-echo-7f579ff9d7-l8vhv

 
* Initial 상태임에도 요청을 전송하는 이유는? 
- Target Group의 파드가 준비 상태인지 확인하기 위해서 입니다. 
 

** Pod readiness gate

ALB/NLB가 ipmode로 동작하는 경우 ALB/NLB의 헬스체크가 정상일 때에만 파드로 전달하는 기능입니다. 
파드 내 컨테이너가 준비 상태인지 여부를 판단하고, 준비 상태가 아니면 해당 컨테이너로 트래픽을 보내지 않습니다. 
 
 


[출처] 
1) CloudNet@, AEWS 실습 스터디 
2) 그림으로 이해하는 가상화와 컨테이너, 5.5 
3) https://kubernetes-sigs.github.io/aws-load-balancer-controller/v2.7/deploy/pod_readiness_gate/

 

Pod Readiness Gate - AWS Load Balancer Controller

Pod readiness gate AWS Load Balancer controller supports »Pod readiness gates« to indicate that pod is registered to the ALB/NLB and healthy to receive traffic. The controller automatically injects the necessary readiness gate configuration to the pod sp

kubernetes-sigs.github.io

4) https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#pod-readiness-gate

 

Pod Lifecycle

This page describes the lifecycle of a Pod. Pods follow a defined lifecycle, starting in the Pending phase, moving through Running if at least one of its primary containers starts OK, and then through either the Succeeded or Failed phases depending on whet

kubernetes.io

 

728x90

'AWS > EKS' 카테고리의 다른 글

[AEWS2] 2-5. Network Policies with VPC CNI  (0) 2024.03.17
[AEWS2] 2-4. Ingress & External DNS  (4) 2024.03.17
[AEWS2] 2-2. 파드 생성 개수 제한하기  (1) 2024.03.16
[AEWS2] 2-1. AWS VPC CNI 소개  (0) 2024.03.16
[AEWS2] 1-2. Amazon EKS 배포  (0) 2024.03.09