본문 바로가기
  • lakescript
스터디 이야기/AWS EKS

[AEWS] 2-3. Amazon EKS Networking - Service

by lakescript 2024. 3. 13.

사전 준비

더보기

 

위와 같이 사전 준비가 필요합니다.

저번 글에서 설명했듯이, EKS를 배포하기 위한 VPC를 생성하고, Public Subnet, Private Subnet을 생성합니다. 그 후 EKS Cluster에 접근하기 위한 bastion EC2를 미리 생성합니다.

 

Kubernetes Service란?

Kubernetes에서 Pod는 언제든지 다른 노드로 이동하거나 삭제될 수 있습니다. 즉, 상태를 유지하지 않습니다.(stateless)

이렇게 이동되거나 생성될 때마다 새로운 IP를 할당받게 됩니다. 이로 인해 Pod는 외부와 지속적으로 통신하기엔 어려움이 있습니다.

 

Kubernetes Service는 Cluster내에서 Pod들을 외부와 통신할 수 있도록 고정적인 IP를 부여하고 애플리케이션을 구동하는 여러 Pod에게 하나의 Network Endpoint를 제공하여 통신이 가능해집니다. 또한 Service는 OSI 4계층 TCP/UDP 레벨에서 동작합니다.

 

Kubernetes Service에는 ClusterIP, NodePort, LoadBalancer, ExternalName과 같은 다양한 유형이 있습니다.

 

Service의 종류

ClusterIP

 

ChatGPT가 알려주는 Kubernetes Service-ClusterIP
ClusterIP는 Kubernetes Service의 기본값으로 클러스터 내부에서 여러 파드들 간의 통신을 지원합니다. 
클러스터 내에서만 접근 가능할 수 있게 IP를 할당하며 외부에서는 접근할 수 없고 port forwarding 또는 proxy를 통해 접근
을 해야 합니다.

 

ClusterIP는 Cluster 내부에서 Service에 접속하고자 하는 용도로 사용되며, 다른 Pod에 할당되지 않은 네트워크의 IP주소를 할당합니다.

 

 

 

 

NodePort

 

ChatGPT가 알려주는 Kubernetes Service-NodePort
NodePort는 ClusterIP에서 확장된 개념으로 유형으로, 외부에서도 접근 가능하도록 합니다. Node의 IP 주소와 지정된 포트 번호를 통해 서비스에 접근할 수 있게 해 줍니다. NodePort는 30000-32767 port 범위 내에서 지정할 수 있으며, 명시적으로 지정하지 않으면 Kubernetes가 자동으로 할당합니다.

 

NodePort는 Worker Node의 Port를 열어 내부의 Pod들과 연결합니다. 서로 다른 Node간의 Pool 선택이 가능합니다. 

 

LoadBalancer

 

ChatGPT가 알려주는 Kubernetes Service-LoadBalancer
LoadBalancer는 Nodeport의 확장한 유형으로 가장 일반적으로 사용되는 서비스 유형입니다.
NodePort타입 앞단에 Cloud 공급업체(AWS, GCP, Azure등) 지원하는 Loadbalancer가 붙어서 살아있는 노드를 체크하여 트래픽을 전달 할 수 있는 장점이 있습니다  AWS의 경우 NLB 인스턴스 유형의 LoadBalancer를 사용합니다.

 

 

Loadbalancer Type은 외부 접속용 EndPoint 역할을 수행할 LoadBalancer를 생성하고, 각 Node의 NodePort를 Target으로 등록하는데, NLB를 통해 들어온 트래픽이 각 node에 있는 NodePort로 들어와 iptables를 통해 트래픽을 분배합니다. 그렇기때문에 복잡하고 비효율적인 단계와 분산룰을 거치게 됩니다.

 

 

LoadBalancer Controller

 

이 형태는 AWS Load Balancer Controller와 NLB, AWS VPC CNI가 조합된 type입니다. 즉, AWS VPC CNI를 통해 NLB가 Pod의 IP에 직접 트래픽 전달이 가능해집니다. (service, iptables rule 등을 bypass) 

 

LoadBalancer Controller는 Node의 Pod IP등 지속적으로 정보를 제공하는데(Kubernetes 구성요소인 Pod에서 AWS의 영역인 NLB에게) 동적으로 이 정보들을 전달하기 위해선 여러 설정(OIDC, IAM 등)이 필요합니다.

 

AWS LoadBalancer Controller 배포 with IRSA

그렇다면 이제 AWS LoadBalancer Controller를 IRSA를 활용하여 배포해 보겠습니다.

 

ChatGPT가 알려주는 IRSA란?
IRSA는 "IAM Roles for Service Accounts"를 의미합니다. 이는 AWS 리소스에 대한 접근을 관리하는 데 사용되는 보안 기능입니다.

 

OIDC 확인

aws eks describe-cluster --name $CLUSTER_NAME --query "cluster.identity.oidc.issuer" --output text

 

aws iam list-open-id-connect-providers | jq

 

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 역할 생성

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

 

명령어를 살펴보자면, AWS Load Balancer Controller를 위한 ServiceAccount를 생성하고 자동으로 매칭되는 IAM Role이 CloudFormation으로 생성됩니다.

 

 

 

그 후 AWS Load Balancer Controller의 kube-system 네임스페이스에 aws-load-balancer-controller라는 Kubernetes 서비스 계정을 생성하고 IAM 역할의 이름으로 Kubernetes 서비스 계정에 주석을 답니다.

 

생성된 ServiceAccount 확인

kubectl get serviceaccounts -n kube-system aws-load-balancer-controller -o yaml | yh

 

AWS LoadBalancer Controller 설치

helm repo add eks https://aws.github.io/eks-charts
helm repo update
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

 

AWS LoadBalancer Controller 설치 확인

kubectl get deployment -n kube-system aws-load-balancer-controller

생성된 IAM Role 신뢰 관계 확인

 

 

자, 이제 AWS Loadbalancer Controller 배포 및 설정은 모두 완료되었습니다! 아래의 Pod 배포를 통해 조금 더 살펴보겠습니다.

 

Service / Pod 배포 테스트 with NLB

실습용 Pod 및 NLB 생성

curl -s -O https://raw.githubusercontent.com/gasida/PKOS/main/2/echo-service-nlb.yaml
cat echo-service-nlb.yaml | yh
kubectl apply -f echo-service-nlb.yaml

 

AWS ELB(NLB) 정보 확인

aws elbv2 describe-load-balancers | jq

active 상태를 확인하자!

aws elbv2 describe-load-balancers --query 'LoadBalancers[*].State.Code' --output text

 

위 명령어로 상태만 뽑아 볼 수 있습니다.

 

Target Group 및 대상 확인

TARGET_GROUP_ARN=$(aws elbv2 describe-target-groups --load-balancer-arn $ALB_ARN | jq -r '.TargetGroups[0].TargetGroupArn')

 

배포한 ELB(NLB)에 연결된 target group을 확인 후 AWS Managed Console에서 해당 target group으로 접근하여 대상들을 살펴보겠습니다.

 

 

그 후 아래의 명령어로 pod의 IP를 확인해 보겠습니다.

kubectl get po -owide

 

ELB(NLB)는 대상 그룹의 대상(Pod)의 IP로 직접적으로 트래픽을 전송할 수 있다는 것을 확인하실 수 있습니다. 

 

어떻게 그럴까...?!?!?!

 

 

 

그 이유는 바로바로 위에서 설명한 바와 같이 AWS VPC CNI 때문입니다!!! ( 매우 매우 중요!!!)

 

LB의 본업인 부하분산은?!

for i in {1..100}; do curl -s $NLB | grep Hostname ; done | sort | uniq -c | sort -nr

 

위의 명령어는 NLB 주소로 100번 호출을 해보는 명령어입니다.

 

 

50:50, 47:53등 골고루 부하를 분산하는 것을 보실 수 있습니다.

 

 

근데, Pod가 아직 준비중이라면??

Pod가 아직 준비중이라면 부하분산을 하면 안되는 것이 일반적인 생각입니다. 그렇기에 AWS LoadBalancer Controller에서는 추가적으로 기능을 제공하는데, Pod readiness gate입니다.

즉, ALB/NLB 대상(ip mode)이 ALB/NLB의 헬스체크에 의해 정상일 경우 해당 파드로 전달할 수 있는 기능입니다. (따로 실습은 진행하지 않겠습니다.)

 


Reference

- https://kubernetes.io/docs/concepts/services-networking/service/

- https://gasidaseo.notion.site/K8S-Service-1-f095388c48a84841b09a13b582f374c8

- https://gasidaseo.notion.site/K8S-Service-2-MetalLB-e49962be02724fe6945e57ffe500e406

- https://leehosu.github.io/kubernetes-service

- https://docs.aws.amazon.com/ko_kr/eks/latest/userguide/aws-load-balancer-controller.html

- https://kubernetes-sigs.github.io/aws-load-balancer-controller/v2.7/deploy/pod_readiness_gate/