✍ Posted by Immersive Builder Seong
1. Service
Service 란?
쿠버네티스 서비스는 컨테이너에 접속하기 위한 엔드포인트를 제공하는 방식입니다.
파드가 삭제되고 재생성되는 경우 파드의 IP가 변경되므로
백엔드 단에서 파드에 정상적으로 연결하기 위한 고정진입점을 제공하는 역할을 합니다.
그리고 여러 파드로 트래픽을 부하분산하는 역할을 하기도 합니다.
Service 종류
ClusterIP 타입
클러스터 내부에만 접속할 수 있는 가상 IP 주소가 생성됩니다.
NodePort 타입
클러스터의 모든 노드의 지정된 포트에 대한 접속이 컨테이너로 전달됩니다.
클러스터 외부에서도 접속할 수 있습니다.
LoadBalancer 타입
AWS 로드밸런서에 대한 접속이 컨테이너로 전송됩니다.
외부 클라이언트가 로드밸런서 접속 시, 로드밸런서 → NodePort → iptables → 파드 → 컨테이너 순으로 전송되며, iptables의 분산룰을 통해 목적지 파드와 통신합니다.
2. LoadBalancer Controller
LoadBalancer Controller 란?
AWS 로드밸런서에 대한 접속이 파드의 IP로 바로 전송되는 방식입니다.
Bypass 통신(로드밸런서 → 파드 → 컨테이너)을 하므로 처리 성능이 향상됩니다.
LoadBalancer Controller는 쿠버네티스 파드의 IP 정보를 AWS 로드밸런서에 지속적으로 제공하는 역할을 합니다.
LoadBalancer Controller도 파드이므로 AWS와 쿠버네티스 간 인증을 구현해야 동작합니다.
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
# 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"
# 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
# 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 기반으로 동작하기 때문입니다.
새로 배포한 서비스에 외부 접속을 시도해봅니다.
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/
4) https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#pod-readiness-gate
'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 |