- Published on
EKS에서 Pod가 노드에 안붙을 때 - PodCIDR 고갈 해결
- Authors
- Name
- 스타차일드
- https://x.com/ETFBITX
서론
EKS에서 갑자기 Pod가 Pending으로 멈추고, 오토스케일링으로 노드를 늘려도 특정 노드에는 Pod가 “안 붙는” 현상이 반복될 때가 있습니다. 이벤트를 보면 Insufficient pods 또는 CNI 쪽 에러가 보이는데, CPU/메모리는 넉넉하고 디스크도 멀쩡합니다. 이때 흔한 원인 중 하나가 PodCIDR(정확히는 노드가 사용할 수 있는 Pod IP 풀) 고갈입니다.
EKS 기본 네트워킹(amazon-vpc-cni)은 Pod에 VPC IP를 직접 할당합니다. 즉, 노드가 사용할 수 있는 ENI/Secondary IP가 바닥나면 그 노드에는 더 이상 Pod IP를 줄 수 없고, 결과적으로 Pod가 스케줄링되지 않거나(혹은 스케줄링되더라도 CNI에서 IP 할당 실패로) 생성이 실패합니다.
이 글에서는 “Pod가 노드에 안 붙음”을 PodCIDR/IP 고갈 관점에서 빠르게 확인하고, 가장 흔한 해결책(서브넷 확장, Prefix Delegation, 인스턴스 타입 변경, CNI 설정 조정)을 정리합니다.
1) 증상: Pod는 Pending, 노드는 여유, 그런데 스케줄 불가
대표적인 증상 패턴은 다음 중 하나로 나타납니다.
kubectl get pods에서 특정 워크로드가 계속Pendingkubectl describe pod이벤트에 다음과 유사한 메시지0/XX nodes are available: XX Insufficient pods.failed to assign an IP address to containeradd cmd: failed to assign an IP address to container
- 노드 리소스(CPU/Memory)는 남아 있는데 Pod가 더 안 올라감
- 노드를 더 늘리면 일시적으로 풀리지만 곧 재발(서브넷 전체 IP가 부족한 경우)
여기서 Insufficient pods는 “Pod 개수 제한”처럼 보이지만, EKS/VPC CNI 환경에서는 실제로는 노드가 할당 가능한 Pod IP가 부족할 때도 동일하게 나타납니다.
2) 10분 진단: 어디가 고갈인가? (노드 단위 vs 서브넷 단위)
문제는 크게 두 갈래입니다.
- (A) 노드 단위 고갈: 특정 노드에서 ENI/Secondary IP가 부족
- (B) 서브넷 단위 고갈: 노드를 늘려도 서브넷의 남는 IP 자체가 부족
2.1 Pod 이벤트로 CNI/IP 할당 실패 확인
kubectl describe pod <pod-name> -n <ns>
이벤트에 failed to assign an IP address가 보이면 거의 확정적으로 CNI IP 할당 문제입니다.
2.2 노드에서 “pods capacity”와 실제 Pod 수 비교
kubectl get nodes -o wide
kubectl describe node <node-name> | sed -n '/Capacity:/,/Allocatable:/p'
여기서 pods: 값이 노드가 수용 가능한 Pod 최대치입니다. VPC CNI에서는 이 값이 인스턴스 타입의 ENI/IPv4 한계에 의해 결정됩니다.
2.3 aws-node(amazon-vpc-cni) 로그 확인
aws-node는 kube-system 네임스페이스의 DaemonSet입니다.
kubectl -n kube-system get pods -l k8s-app=aws-node -o wide
kubectl -n kube-system logs -l k8s-app=aws-node --tail=200
다음 키워드가 보이면 IP 부족/할당 실패를 의심하세요.
IPAM관련 에러no available IP addressesfailed to allocate IP
2.4 (서브넷 단위) VPC 서브넷 남은 IP 확인
노드를 늘려도 바로 다시 막히면, 서브넷의 free IP가 부족할 가능성이 큽니다.
aws ec2 describe-subnets \
--subnet-ids subnet-xxxx subnet-yyyy \
--query 'Subnets[].{SubnetId:SubnetId,CidrBlock:CidrBlock,AvailableIpAddressCount:AvailableIpAddressCount}' \
--output table
AvailableIpAddressCount가 낮으면(예: 수십~수백 수준) 스케일아웃 시 곧 고갈됩니다.
3) 원리 이해: “PodCIDR 고갈”이 실제로 의미하는 것
전통적인 Kubernetes(kube-controller-manager가 노드에 podCIDR를 할당하고, CNI가 그 대역에서 Pod IP를 뽑는 모델)에서는 “PodCIDR 고갈”이 정말로 노드별 CIDR 블록 고갈을 뜻합니다.
하지만 EKS의 기본 CNI(amazon-vpc-cni)는 보통 다음 구조로 이해하는 게 실전에서 더 정확합니다.
- Pod IP는 VPC 서브넷 CIDR에서 직접 할당
- 노드는 ENI(Elastic Network Interface)를 붙이고, 각 ENI에 Secondary IP를 여러 개 붙여 Pod에 배정
- 따라서 고갈 지점은
- 노드가 더 붙일 수 있는 ENI/Secondary IP 한계(인스턴스 타입 제한)
- 서브넷 전체에서 남아있는 IPv4 부족
즉, 현상은 “PodCIDR 고갈”처럼 보이지만, 실제 해결은 VPC IP 공급량을 늘리거나(IP 확장), 노드가 IP를 더 효율적으로 쓰게 하거나(Prefix Delegation), 인스턴스 타입을 바꾸는 것입니다.
4) 해결책 1: Prefix Delegation 활성화(가장 흔한 정답)
EKS VPC CNI의 Prefix Delegation(PD) 을 켜면, 노드에 개별 Secondary IP를 여러 개 붙이는 대신 /28 프리픽스 단위로 IP를 위임받아 더 많은 Pod IP를 효율적으로 관리합니다. 대규모/고밀도 배치에서 IP 부족 문제를 크게 줄일 수 있습니다.
이 주제는 케이스가 다양하고 “PD를 켰는데도 부족”한 경우도 있어, 아래 글을 함께 참고하면 좋습니다.
4.1 CNI 환경 변수 설정(예시)
aws-node DaemonSet에 다음 설정을 적용합니다(클러스터/버전에 따라 권장값은 다를 수 있음).
kubectl -n kube-system set env daemonset/aws-node \
ENABLE_PREFIX_DELEGATION=true \
WARM_PREFIX_TARGET=1
ENABLE_PREFIX_DELEGATION=true: PD 활성화WARM_PREFIX_TARGET=1: 미리 확보해둘 prefix 수(트래픽/스케일 패턴에 맞게 조정)
적용 후 롤링 업데이트를 확인합니다.
kubectl -n kube-system rollout status ds/aws-node
4.2 PD 활성화 후 검증 포인트
- 새로 뜨는 노드부터 효과가 커지는 경우가 많습니다(기존 노드는 재시작/교체 필요할 수 있음).
aws-node로그에서 prefix 관련 할당 로그가 보이는지 확인- 동일 인스턴스 타입에서 노드당 수용 가능한 Pod 수가 증가했는지 확인
5) 해결책 2: 서브넷 CIDR 확장 또는 신규 서브넷 추가
서브넷 자체의 AvailableIpAddressCount가 낮다면, PD를 켜도 근본적으로 IP 공급이 부족합니다. 이때는 네트워크 설계를 바꿔야 합니다.
현실적인 선택지는 다음입니다.
- (권장) 신규 서브넷 추가: 더 큰 CIDR의 서브넷을 추가하고, 노드그룹이 해당 서브넷을 사용하도록 구성
- VPC에 Secondary CIDR 추가 후 서브넷 확장: 기존 VPC에 보조 CIDR을 붙이고, 추가 서브넷 생성
5.1 노드그룹 서브넷 변경(예: eksctl)
# nodegroup-subnets.yaml
apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig
metadata:
name: my-eks
region: ap-northeast-2
managedNodeGroups:
- name: ng-1
instanceType: m6i.large
desiredCapacity: 3
privateNetworking: true
subnets:
- subnet-aaaa1111
- subnet-bbbb2222
적용:
eksctl create nodegroup -f nodegroup-subnets.yaml
기존 노드그룹을 교체(블루/그린)하는 방식이 안전합니다.
6) 해결책 3: 인스턴스 타입 변경(ENI/IPv4 한계 상향)
노드 단위로만 막히고 서브넷 IP는 넉넉하다면, 인스턴스 타입의 ENI/IPv4 한계가 병목일 수 있습니다. 더 많은 ENI/IPv4를 지원하는 타입으로 바꾸면 노드당 Pod 수가 늘어납니다.
실전 팁:
- “CPU/메모리 여유인데 Pod가 안 붙는” 노드는 네트워크 한계일 가능성이 큼
- 워크로드가 작은 Pod 위주라면, 노드당 Pod 밀도가 높아져 IP 한계에 빨리 도달
검증은 kubectl describe node의 Capacity.pods 변화로 확인합니다.
7) 해결책 4: WARM_* 튜닝으로 스케일 순간 장애 줄이기
IP가 “완전히 고갈”되기 전이라도, 스케일아웃 순간에 IP를 늦게 확보해서 잠깐 Pending이 몰릴 수 있습니다. 이때 WARM_IP_TARGET, WARM_ENI_TARGET, MINIMUM_IP_TARGET 같은 설정이 영향을 줍니다.
예시(환경에 맞게 조정 필요):
kubectl -n kube-system set env daemonset/aws-node \
WARM_IP_TARGET=10 \
MINIMUM_IP_TARGET=20
WARM_IP_TARGET: 미리 확보해둘 여유 IP 개수MINIMUM_IP_TARGET: 최소 유지할 IP 개수
주의: 과도하게 올리면 서브넷 IP를 더 빨리 소진할 수 있습니다. “서브넷 단위 고갈”이 의심될 때는 오히려 역효과가 날 수 있습니다.
8) 운영 관점 체크리스트(재발 방지)
8.1 모니터링 지표
- 서브넷
AvailableIpAddressCount(CloudWatch/주기적 점검) - 노드당 Pod 수(파드 밀도)
aws-node로그에서 IPAM 오류 빈도
8.2 배포/스케일 정책
- HPA/KEDA로 급격히 늘어나는 워크로드는 WARM 타깃과 함께 설계
- 작은 Pod가 많다면 인스턴스 타입/PD로 “Pod per node” 상한을 먼저 계산
8.3 함께 자주 엮이는 이슈
EKS에서 네트워크/권한 문제가 동시에 터지면 원인 분리가 어려워집니다. 예를 들어, Pod는 떴는데 AWS API 호출이 403이면 IRSA/STS 문제일 수 있습니다. 아래 글들도 같은 운영 맥락에서 자주 참고합니다.
9) 결론: “노드에 안 붙는 Pod”는 대개 IP가 먼저다
EKS에서 Pod가 노드에 안 붙을 때, CPU/메모리만 보고 있으면 시간을 많이 씁니다. 특히 이벤트에 Insufficient pods가 보이면 Pod 수 제한이 아니라 IP 풀 고갈일 가능성이 높습니다.
정리하면 우선순위는 다음이 실전에서 가장 효율적입니다.
describe pod/aws-node로그로 IP 할당 실패 여부 확인- 서브넷
AvailableIpAddressCount로 “서브넷 단위 고갈”인지 판단 - Prefix Delegation 활성화 + WARM 타깃 적정화
- 필요 시 서브넷 확장/추가, 인스턴스 타입 상향, 노드그룹 교체
이 흐름대로만 점검해도 “Pod가 Pending인데 이유를 모르겠다”에서 빠르게 벗어날 수 있습니다.