Search
moon
sun

Pod EIP Controller

참고

기존 Pod가 외부 인터넷과 통신하는 방법

1.
Worker Node가 Public Subnet에 위치 할 경우 Pod는 외부 인터넷 통신 시 Worker Node의 Public/EIP를 기반으로 외부 인터넷과 통신
2.
Worker Node가 Private Subnet에 위치 할 경우 NAT G/W을 통해 NAT GW의 공인 IP로 NAT되어 통신

AWS Pod EIP Controller란?

AWS Pod EIP Controller는 Annotation을 통해 Elastic IP를 자동으로 할당 및 해제하는 기능을 제공

Pod에 대한 인터넷 Outbound 액세스 이해

•
Pod의 통신 대상이 VPC에 연결된 CIDR 블록 내에 있지 않은 경우 기본적으로 Pod가 실행 중인 노드의 ENI의 IP 주소로 변환
•
즉 실행 중인 노드가 Public Subnet에 위치하여 있고, 해당 노드가 퍼블릭 또는 EIP 주소를 할당 받은 경우에 인터넷과 통신이 가능하지만, Pod는 노드의 Public IP로 SNAT 되어 통신
•
노드의 기본 ENI로의 SNAT을 해제하기 위해서는 아래 옵션으로 해제
kubectl set env daemonset -n kube-system aws-node AWS_VPC_K8S_CNI_EXTERNALSNAT=true
Shell
복사

Pod 기반 White-List 처리를 위한 방안

•
AWS Pod EIP Controller를 통해 Pod의 Public EIP를 부여
•
AWS_VPC_K8S_CNI_EXTERNALSNAT=true을 통해 Node 기반 SNAT을 해제
•
외부 파트너사 API가 "이 IP만 허용해줄게"라고 화이트리스트를 걸어주는 상황에서, Pod마다 서로 다른 IP로 식별되어야 하는 경우
•
NAT GW를 쓰면 Pod A, B, C가 전부 같은 IP로 나가기 때문에 애초에 "Pod별 화이트리스트"라는 요구사항 자체가 성립이 안 됨. 이게 EIP Controller를 별도로 만든 이유
[Pod A: 10.0.1.10] ─┐ [Pod B: 10.0.1.11] ─┼─→ NAT Gateway (공인 IP 1개) ─→ 인터넷 [Pod C: 10.0.1.12] ─┘
Markdown
복사
Cluster Manifest
export ACCOUNT_ID=$(aws sts get-caller-identity --output text --query Account) export AWS_REGION=<AWS_REGION>
Shell
복사
aws ecr create-repository --repository-name aws-pod-eip-controller
Shell
복사
aws ecr get-login-password --region ${AWS_REGION} \ | docker login --username AWS --password-stdin ${ACCOUNT_ID}.dkr.ecr.${AWS_REGION}.amazonaws.com
Shell
복사
git clone https://github.com/aws-samples/aws-pod-eip-controller.git cd aws-pod-eip-controller
Shell
복사
docker buildx build \ --tag ${ACCOUNT_ID}.dkr.ecr.${AWS_REGION}.amazonaws.com/aws-pod-eip-controller:latest \ --platform linux/amd64,linux/arm64 \ --push .
Shell
복사
cat << EOF > iam-policy.json { "Version": "2012-10-17", "Statement": [ { "Sid": "VisualEditor0", "Effect": "Allow", "Action": [ "ec2:AllocateAddress", "ec2:AssociateAddress", "ec2:CreateTags", "ec2:ReleaseAddress", "ec2:DisassociateAddress", "ec2:DeleteTags", "ec2:DescribeAddresses", "ec2:DescribeNetworkInterfaces" ], "Resource": "*" } ] } EOF
Shell
복사
aws iam create-policy \ --policy-name AWSPodEIPControllerIAMPolicy \ --policy-document file://iam-policy.json
Shell
복사
eksctl create iamserviceaccount \ --cluster=eip-controller-demo \ --namespace=kube-system \ --name=aws-pod-eip-controller \ --attach-policy-arn=arn:aws:iam::${ACCOUNT_ID}:policy/AWSPodEIPControllerIAMPolicy \ --override-existing-serviceaccounts \ --region ${AWS_REGION} \ --approve
Shell
복사
helm install aws-pod-eip-controller ./charts/aws-pod-eip-controller \ --namespace kube-system \ --set image=${ACCOUNT_ID}.dkr.ecr.${AWS_REGION}.amazonaws.com/aws-pod-eip-controller:latest \ --set clusterName=eip-controller-demo \ --set serviceAccountName=aws-pod-eip-controller \ --wait
Shell
복사
apiVersion: apps/v1 kind: Deployment metadata: name: busybox namespace: default spec: replicas: 2 selector: matchLabels: app: busybox-eip template: metadata: labels: app: busybox-eip annotations: aws-samples.github.com/aws-pod-eip-controller-type: auto spec: nodeSelector: alpha.eksctl.io/nodegroup-name: public-node-group containers: - name: busybox image: busybox command: - sleep - "3600" imagePullPolicy: IfNotPresent
YAML
복사
kubectl get pod | grep busybox
Shell
복사
kubectl get pods -o=custom-columns=NAME:.metadata.name,STATUS:.status.phase,PODIP:.status.podIP,EIP:.metadata.labels.aws-pod-eip-controller-public-ip -w
Shell
복사
테스트 1 - SNAT가 활성화 되어 있을 경우
•
busybox Pod에 접속하여 외부 API를 통해 Source IP를 조회하게 되면 결과적으로 Pod의 EIP가 아닌, Node의 Public IP가 반환 되는 것을 확인 할 수 있다.
kubectl exec -it <POD_NAME> -- /bin/sh wget -qO- http://api.ipify.org
Shell
복사
테스트 2 - SNAT가 비활성화 되어 있을 경우
•
busybox Pod에 접속하여 외부 API를 통해 Source IP를 조회하게 되면 결과적으로 Pod에 부여된 EIP가 조회되는 사항을 확인 할 수 있다.
kubectl exec -it <POD_NAME> -- /bin/sh wget -qO- http://api.ipify.org
Shell
복사