- Published on
EKS에서 Pod가 IP 못받고 Pending일 때(CNI) 진단
- Authors
- Name
- 스타차일드
- https://x.com/ETFBITX
서론
EKS에서 Pod를 배포했는데 Pending 상태가 오래 지속되거나, ContainerCreating에서 멈춘 채로 Pod IP가 비어 있는 상황을 종종 만납니다. 이때 많은 경우 원인은 애플리케이션이 아니라 AWS VPC CNI(aws-node) 입니다. EKS 기본 네트워킹은 “노드(EC2)에 붙은 ENI의 Secondary IP를 Pod에 할당”하는 구조라서, ENI/IP가 고갈되거나 CNI가 IP를 붙이지 못하는 상태가 되면 Pod는 스케줄되더라도 네트워크 단계에서 멈춥니다.
이 글은 “Pod가 IP를 못 받고 Pending/ContainerCreating에서 멈출 때”를 대상으로, kubectl describe 이벤트 → aws-node 로그 → 노드 ENI/IP 용량 → CNI 설정/버전 → 운영 중 완화책 순서로 빠르게 진단하는 체크리스트를 제공합니다.
> 참고: Pod가 ContainerCreating에 멈춘 이슈는 CNI/CSI/권한 등 다양한 원인이 섞일 수 있습니다. 범용 진단은 EKS Pod가 ContainerCreating에 멈출 때 10분 진단도 함께 보세요.
증상 패턴: “스케줄은 됐는데 IP가 없다”
대표적인 관찰 포인트는 아래와 같습니다.
kubectl get pod -o wide에서IP컬럼이 비어 있음kubectl describe pod이벤트에 CNI 관련 메시지- 노드에서는
aws-node(DaemonSet) 컨테이너 로그에 IP 할당 실패 흔적
먼저 Pod 상태와 이벤트부터 확인합니다.
kubectl get pod -n <ns> -o wide
kubectl describe pod -n <ns> <pod-name>
이때 자주 보이는 이벤트 예시는 다음 계열입니다.
FailedCreatePodSandBoxfailed to set up sandbox container/CNI failed to assign an IP addressrpc error: code = Unknown desc = failed to setup network for sandbox
이 메시지가 보이면 “스케줄링 문제”보다는 CNI가 Pod 네트워크를 만들지 못하는 문제로 보는 게 맞습니다.
1단계: aws-node(=VPC CNI) 상태 확인
EKS 기본 CNI는 kube-system 네임스페이스의 aws-node DaemonSet입니다. 우선 DaemonSet과 Pod가 정상인지 확인합니다.
kubectl -n kube-system get ds aws-node
kubectl -n kube-system get pod -l k8s-app=aws-node -o wide
여기서 특정 노드에만 aws-node가 재시작을 반복하거나 CrashLoopBackOff라면, 해당 노드는 신규 Pod에 IP를 붙이지 못할 가능성이 큽니다.
aws-node 로그에서 “IP 할당 실패” 찾기
문제가 발생한 노드의 aws-node Pod를 골라 로그를 봅니다.
# 문제 Pod가 스케줄된 노드 확인
kubectl get pod -n <ns> <pod-name> -o jsonpath='{.spec.nodeName}'
# 해당 노드에서 동작 중인 aws-node Pod 찾기
kubectl -n kube-system get pod -l k8s-app=aws-node -o wide | grep <node-name>
# 로그 확인
kubectl -n kube-system logs <aws-node-pod> -c aws-node --since=30m
로그에서 아래 키워드가 나오면 거의 확정적으로 “ENI/IP 자원 부족 또는 CNI 설정 문제”입니다.
failed to assign an IP address to containerIPAMD관련 에러(=IP Address Management Daemon)Insufficient free addresses/no available IP addressesfailed to allocate IP/failed to attach ENI
2단계: 노드 ENI/IP 용량(=Pod 수용량) 확인
VPC CNI는 노드 인스턴스 타입별로 붙일 수 있는 ENI 개수와 ENI당 Secondary IP 개수 제한이 있습니다. 결국 “노드가 수용 가능한 Pod 수”는 인스턴스 타입에 의해 하드 제한을 받습니다.
빠른 신호: 노드에 Pod가 빽빽하게 찼는지
kubectl get node <node-name> -o jsonpath='{.status.allocatable.pods}'
kubectl get pod -A --field-selector spec.nodeName=<node-name> | wc -l
allocatable.pods 근처까지 Pod가 찼다면, IP 고갈 가능성이 큽니다. 다만 allocatable.pods는 kubelet maxPods 설정과도 연관이 있으므로, 실제 IP 여유는 aws-node/ENI 상태로 재확인해야 합니다.
EC2에서 ENI/IP 실제 사용량 확인(권장)
AWS CLI로 노드(EC2)의 ENI와 Secondary IP 사용 현황을 확인합니다.
# 노드의 인스턴스 ID 찾기(노드 이름이 Private DNS인 경우가 많음)
aws ec2 describe-instances \
--filters "Name=private-dns-name,Values=<node-name>" \
--query 'Reservations[].Instances[].InstanceId' \
--output text
# ENI와 IP 확인
aws ec2 describe-network-interfaces \
--filters "Name=attachment.instance-id,Values=<instance-id>" \
--query 'NetworkInterfaces[].{ENI:NetworkInterfaceId,IPs:PrivateIpAddresses[].PrivateIpAddress,Count:length(PrivateIpAddresses)}'
여기서 ENI별 IP가 꽉 차 있거나, 추가 ENI attach가 실패하는 상황이면 Pod IP 할당이 막힙니다.
서브넷 IP 고갈도 함께 확인
노드 자체 ENI/IP가 늘어날 여지가 있어도, 서브넷에 남은 IP가 없으면 추가 Secondary IP를 못 붙입니다.
aws ec2 describe-subnets \
--subnet-ids <subnet-id> \
--query 'Subnets[].{SubnetId:SubnetId,AvailableIpAddressCount:AvailableIpAddressCount,CidrBlock:CidrBlock}'
AvailableIpAddressCount가 낮다면(특히 수십 개 미만), 스케일아웃/새 Pod 생성 시점에 Pending이 폭발할 수 있습니다.
3단계: CNI 설정값(WARM_IP_TARGET/MINIMUM_IP_TARGET)로 “미리 확보” 전략 점검
VPC CNI는 “필요할 때마다 IP를 붙이는” 방식 외에, 미리 IP를 확보해 두는(warm pool) 설정을 제공합니다. 트래픽 급증/오토스케일 상황에서 Pod 생성이 느리거나 Pending이 늘어나는 경우, warm pool 튜닝이 효과적입니다.
설정은 aws-node DaemonSet의 환경변수로 들어갑니다.
kubectl -n kube-system get ds aws-node -o jsonpath='{.spec.template.spec.containers[0].env}' | jq
자주 쓰는 값:
WARM_IP_TARGET: 노드가 “여유 IP”를 몇 개 유지할지MINIMUM_IP_TARGET: 최소로 확보할 IP 수(버전에 따라 동작 차이 존재)WARM_ENI_TARGET: 여유 ENI를 유지(환경에 따라 유효)
예: 노드당 여유 IP 5개를 유지하도록 설정(예시)
kubectl -n kube-system patch ds aws-node \
--type='json' \
-p='[
{"op":"add","path":"/spec/template/spec/containers/0/env/-","value":{"name":"WARM_IP_TARGET","value":"5"}}
]'
주의할 점:
- warm pool은 “속도”를 개선하지만, 근본적으로 서브넷/인스턴스 IP 한계를 늘리지는 못합니다.
- 너무 크게 잡으면 IP를 과도하게 선점하여 다른 노드/서비스에 악영향을 줄 수 있습니다.
4단계: Prefix Delegation(/28) 사용 여부(대규모 Pod 밀도 개선)
최근 VPC CNI는 Prefix Delegation(PD) 을 지원합니다. Secondary IP를 하나씩 붙이는 대신, ENI에 /28 프리픽스를 위임받아 Pod IP를 더 효율적으로 운영할 수 있습니다(환경에 따라 Pod 밀도와 확장성이 좋아짐).
PD 사용은 CNI 설정과 버전, 그리고 노드/서브넷 설계와 함께 봐야 하므로 “무조건 켠다”보다는 아래 상황에 검토 가치가 큽니다.
- 노드당 Pod가 많아 IP가 자주 고갈됨
- 스케일아웃 때 IP attach 지연이 잦음
- 서브넷을 크게 가져가기 어렵고 IP 효율이 중요함
현재 클러스터의 CNI 버전 확인:
kubectl -n kube-system describe ds aws-node | sed -n '/Image:/p'
운영 중인 버전이 너무 낮다면 업그레이드가 1순위가 되기도 합니다(특히 EKS Add-on으로 관리하는 경우).
5단계: 보안그룹/네트워크 경로 문제로 CNI가 AWS API를 못 치는 경우
IP 할당은 노드에서 AWS API를 호출해 ENI/IP를 붙이는 작업이 포함됩니다. 따라서 다음이 막히면 aws-node가 정상이어도 IP 할당이 실패할 수 있습니다.
- 노드가 인터넷/NAT 없이 외부로 나가며, VPC Endpoint도 없음
ec2:AssignPrivateIpAddresses,ec2:AttachNetworkInterface등 권한이 부족- 노드의 보안그룹/네트워크 ACL이 비정상(특히 엔드포인트/메타데이터 경로)
EKS에서 흔한 권한 이슈는 컨트롤러/애드온에서 자주 터지지만, CNI도 예외는 아닙니다. 만약 “권한 문제”가 의심되면, 다른 403 계열 트러블슈팅 패턴도 함께 참고하면 도움이 됩니다. 예를 들어 EKS에서 AWS Load Balancer Controller 403 해결법은 IRSA/권한 점검 흐름을 이해하는 데 유용합니다.
6단계: 빠른 완화책(장애 대응)과 근본 해결책(재발 방지)
장애 시 빠른 완화책
- 문제 노드에서 Pod 재스케줄
- 특정 노드만 IP 할당이 막혔다면, 해당 노드를
cordon후drain하여 Pod를 다른 노드로 옮깁니다.
kubectl cordon <node-name>
kubectl drain <node-name> --ignore-daemonsets --delete-emptydir-data
- 노드그룹 스케일아웃
- 전체적으로 IP가 부족하면 노드 수를 늘려 “ENI/IP 풀”을 늘리는 게 즉효입니다.
- 서브넷 IP 여유 확보
- 서브넷이 작으면 어떤 튜닝도 한계가 있습니다. 즉시 가능한 조치가 제한적이지만, 여유 있는 서브넷을 추가해 노드그룹을 분산하는 방식이 필요합니다.
근본 해결책(설계/운영)
- 서브넷 CIDR 재설계: EKS 워크로드가 늘어날수록 /24는 생각보다 빠르게 고갈됩니다.
- 인스턴스 타입/노드 전략: Pod 밀도가 높다면 ENI/IP 한도가 넉넉한 타입을 고려합니다.
- CNI warm pool 튜닝: 급격한 스케일링에서 Pending을 줄입니다.
- Prefix Delegation 검토: 대규모 환경에서 IP 운영 효율을 개선합니다.
- 관측(모니터링) 추가: 서브넷 Available IP, aws-node 재시작, IPAMD 오류를 알람으로 올립니다.
재현 가능한 “10분 점검 루틴” 요약
아래 순서대로 보면 대부분 10분 내에 원인 범위를 좁힐 수 있습니다.
kubectl describe pod에서FailedCreatePodSandBox/CNI 이벤트 확인- 문제 노드의
aws-node로그에서 IPAMD/assign 실패 메시지 확인 - 노드 ENI/IP 사용량과 서브넷
AvailableIpAddressCount확인 WARM_IP_TARGET등 CNI 설정값 점검(스케일링 지연 완화)- 권한/네트워크 경로(AWS API 접근) 문제 여부 확인
추가로, “Pod는 Running인데 트래픽이 0” 같은 네트워크 계층의 다른 증상과 구분도 중요합니다. 그 경우는 EKS Pod는 뜨는데 트래픽 0 - NetPol·SG·CNI 10분 진단 쪽 체크리스트가 더 맞습니다.
마무리
EKS에서 Pod가 IP를 못 받아 Pending/ContainerCreating에 걸릴 때는, 쿠버네티스 스케줄러 자체보다 VPC CNI의 IP 할당 경로(ENI/Secondary IP/서브넷 가용 IP/CNI 설정/권한) 를 먼저 의심하는 게 시간 절약입니다. 특히 “서브넷 IP 고갈”과 “인스턴스 타입의 ENI/IP 한계”는 튜닝으로 해결되지 않는 구조적 제약이므로, 조기 모니터링과 네트워크 설계가 재발 방지의 핵심입니다.
원하시면 현재 사용 중인 인스턴스 타입, 노드당 Pod 수, 서브넷 CIDR/가용 IP, aws-node 로그 일부를 기준으로 “어떤 원인이 가장 유력한지”와 “WARM_IP_TARGET/PD를 어떻게 잡을지”까지 구체적으로 계산해 드릴게요.