Published on

EKS에서 Pod가 IP 못받고 Pending일 때(CNI) 진단

Authors

서론

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>

이때 자주 보이는 이벤트 예시는 다음 계열입니다.

  • FailedCreatePodSandBox
  • failed to set up sandbox container / CNI failed to assign an IP address
  • rpc 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 container
  • IPAMD 관련 에러(=IP Address Management Daemon)
  • Insufficient free addresses / no available IP addresses
  • failed 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단계: 빠른 완화책(장애 대응)과 근본 해결책(재발 방지)

장애 시 빠른 완화책

  1. 문제 노드에서 Pod 재스케줄
  • 특정 노드만 IP 할당이 막혔다면, 해당 노드를 cordondrain하여 Pod를 다른 노드로 옮깁니다.
kubectl cordon <node-name>
kubectl drain <node-name> --ignore-daemonsets --delete-emptydir-data
  1. 노드그룹 스케일아웃
  • 전체적으로 IP가 부족하면 노드 수를 늘려 “ENI/IP 풀”을 늘리는 게 즉효입니다.
  1. 서브넷 IP 여유 확보
  • 서브넷이 작으면 어떤 튜닝도 한계가 있습니다. 즉시 가능한 조치가 제한적이지만, 여유 있는 서브넷을 추가해 노드그룹을 분산하는 방식이 필요합니다.

근본 해결책(설계/운영)

  • 서브넷 CIDR 재설계: EKS 워크로드가 늘어날수록 /24는 생각보다 빠르게 고갈됩니다.
  • 인스턴스 타입/노드 전략: Pod 밀도가 높다면 ENI/IP 한도가 넉넉한 타입을 고려합니다.
  • CNI warm pool 튜닝: 급격한 스케일링에서 Pending을 줄입니다.
  • Prefix Delegation 검토: 대규모 환경에서 IP 운영 효율을 개선합니다.
  • 관측(모니터링) 추가: 서브넷 Available IP, aws-node 재시작, IPAMD 오류를 알람으로 올립니다.

재현 가능한 “10분 점검 루틴” 요약

아래 순서대로 보면 대부분 10분 내에 원인 범위를 좁힐 수 있습니다.

  1. kubectl describe pod에서 FailedCreatePodSandBox/CNI 이벤트 확인
  2. 문제 노드의 aws-node 로그에서 IPAMD/assign 실패 메시지 확인
  3. 노드 ENI/IP 사용량과 서브넷 AvailableIpAddressCount 확인
  4. WARM_IP_TARGET 등 CNI 설정값 점검(스케일링 지연 완화)
  5. 권한/네트워크 경로(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를 어떻게 잡을지”까지 구체적으로 계산해 드릴게요.