- Published on
Kubernetes CNI IP 부족으로 Pod Pending 해결 가이드
- Authors
- Name
- 스타차일드
- https://x.com/ETFBITX
서버가 멀쩡해 보이는데도 새로 뜨는 Pod가 Pending에서 멈추는 상황은 운영에서 자주 만나는 장애 유형입니다. 특히 클러스터가 일정 규모를 넘거나 노드/파드 스케일링이 잦은 환경에서는 CNI의 Pod IP 할당 풀이 고갈(IP exhaustion) 되면서 스케줄러는 배치하려고 하는데 실제 네트워크가 따라주지 못해 멈추는 일이 발생합니다.
이 글에서는 “CNI IP 부족”이 실제로 어떤 이벤트/로그로 나타나는지, 어떤 지표로 빠르게 확정 진단하는지, 그리고 즉시 완화(quick mitigation) 와 근본 해결(설계 변경) 을 단계별로 정리합니다. (예시는 EKS의 aws-vpc-cni를 중심으로 설명하지만, Calico/Cilium에서도 진단 흐름은 유사합니다.)
관련해서 노드가 NotReady로 떨어질 때 CNI/보안그룹/IRSA까지 함께 점검해야 하는 경우도 많습니다. 필요하면 이 글도 함께 참고하세요: Terraform apply 후 EKS 노드 NotReady - CNI·IRSA·보안그룹 점검
1) 증상: Pod는 Pending, 이벤트는 IP 할당 실패
1-1. Pod 상태 확인
kubectl get pod -A -o wide | grep Pending
kubectl describe pod -n <ns> <pod>
describe의 Events에서 다음과 유사한 메시지가 보이면 IP 부족 가능성이 큽니다.
FailedCreatePodSandBoxfailed to set up sandbox container/CNI failed to allocate IP- (EKS aws-vpc-cni)
failed to assign an IP address to container
1-2. kubelet / CNI 로그에서 확인
노드에서 kubelet 로그 또는 CNI 데몬 로그를 확인합니다.
# 노드 접속 후
sudo journalctl -u kubelet -n 200 --no-pager
EKS의 경우 aws-node(aws-vpc-cni) DaemonSet 로그가 핵심입니다.
kubectl -n kube-system get pods -l k8s-app=aws-node -o wide
kubectl -n kube-system logs <aws-node-pod> -c aws-node --tail=200
대표적인 키워드:
IPAM/ipamdAssignPodIPAddress실패datastore has no available IP addresses류
2) 원인 구조: “노드당 Pod IP 풀”이 먼저 고갈된다
CNI IP 부족은 크게 두 층에서 발생합니다.
- 노드 레벨 고갈: 특정 노드가 보유한 Pod IP(secondary IP)가 부족해서 그 노드로 스케줄되는 Pod가 Pending
- 서브넷 레벨 고갈: 노드가 IP를 더 붙이려고 해도 VPC 서브넷에 남은 IP가 없어 전체적으로 할당 불가
EKS aws-vpc-cni 기준으로는 노드의 ENI(Elastic Network Interface)와 secondary IP가 Pod IP로 사용되기 때문에,
- 인스턴스 타입별 ENI 개수/ENI당 IP 제한
WARM_IP_TARGET,MINIMUM_IP_TARGET같은 사전 확보 설정- (최근 권장) Prefix delegation(/28) 사용 여부
에 따라 “노드당 수용 가능한 Pod 수”가 크게 달라집니다.
3) 빠른 확정 진단 체크리스트
3-1. Pending Pod가 특정 노드에만 몰리는가?
스케줄링은 되었는데 CNI에서 막히는 경우, describe pod에서 Node:가 찍히거나 Scheduled 이벤트는 성공한 상태일 수 있습니다.
kubectl describe pod -n <ns> <pod> | sed -n '/Events:/,$p'
Successfully assigned ... to ip-...이후FailedCreatePodSandBox가 나오면 노드 레벨 IP 부족 가능성이 큽니다.
3-2. 노드의 Pod 수 vs 인스턴스 타입 한계
kubectl get nodes
kubectl describe node <node> | egrep -i 'Pods:|Non-terminated Pods:|Allocatable|Capacity'
여기서 Capacity/Allocatable의 pods 값이 낮게 잡혀 있거나, 실제 파드 수가 한계에 근접하면 IP/ENI 제한에 걸릴 확률이 높습니다.
3-3. 서브넷 IP 잔량 확인(AWS)
서브넷 IP가 바닥나면 어떤 노드도 IP를 더 못 붙입니다.
aws ec2 describe-subnets --subnet-ids <subnet-1> <subnet-2> \
--query 'Subnets[].{SubnetId:SubnetId,AvailableIpAddressCount:AvailableIpAddressCount,CidrBlock:CidrBlock}' \
--output table
AvailableIpAddressCount가 매우 낮으면 서브넷 레벨 고갈이 원인입니다.
4) 즉시 완화(Quick Mitigation): 서비스 살리기
장애 상황에서는 “근본 해결”보다 지금 Pending을 풀어 트래픽을 받게 만드는 것이 우선입니다.
4-1. (노드 레벨) 노드 수를 늘려 IP 풀을 분산
클러스터 오토스케일러/노드그룹 스케일 아웃이 가장 빠르게 먹히는 경우가 많습니다.
- 노드가 늘면 노드별로 ENI/secondary IP 풀도 늘어나므로 Pending이 해소될 수 있습니다.
- 단, 서브넷 자체가 고갈이면 노드를 늘려도 소용이 없습니다.
4-2. (노드 레벨) 문제 노드 Drain 후 교체
특정 노드의 CNI가 꼬이거나 IP가 회수되지 않는(유령 IP) 상황이 겹치면 drain이 빠른 처방이 됩니다.
kubectl drain <node> --ignore-daemonsets --delete-emptydir-data
# 노드 교체(ASG/EKS managed nodegroup에서 terminate)
4-3. (서브넷 레벨) 불필요한 Pod/Job 정리
짧게 끝나야 할 Job/배치가 누적되어 IP를 잡아먹는 경우가 있습니다.
kubectl get job -A
kubectl delete job -n <ns> <job>
kubectl get pod -A --field-selector=status.phase=Succeeded
kubectl delete pod -A --field-selector=status.phase=Succeeded
4-4. (EKS) WARM_IP_TARGET 상향으로 “미리 IP 확보”
이미 서브넷 여유가 있고, 단지 노드가 IP를 늦게 확보해서 순간적으로 Pending이 생긴다면 WARM_IP_TARGET/MINIMUM_IP_TARGET 튜닝이 효과적입니다.
kubectl -n kube-system set env daemonset aws-node \
WARM_IP_TARGET=10 MINIMUM_IP_TARGET=10
kubectl -n kube-system rollout status ds/aws-node
- 너무 크게 잡으면 노드들이 IP를 과도하게 선점하여 서브넷 고갈을 앞당길 수 있습니다.
- 트래픽 패턴(스파이크)과 노드 수를 고려해 점진적으로 조정하세요.
5) 근본 해결: IP 설계/할당 방식을 바꿔야 재발이 줄어든다
5-1. 서브넷 CIDR 확장 또는 신규 서브넷 추가
서브넷 고갈이면 답은 명확합니다.
- 더 큰 CIDR로 재설계(기존 서브넷 확장은 제약이 많음)
- 신규 서브넷을 추가하고 노드그룹이 해당 서브넷을 사용하도록 변경
EKS에서는 노드그룹(또는 ASG)이 붙는 서브넷 목록을 늘려 IP 풀 자체를 확장하는 방식이 일반적입니다.
점검 포인트:
- NAT Gateway/라우팅/보안그룹/NACL
- 멀티 AZ 분산
- 프라이빗/퍼블릭 서브넷 역할 분리
5-2. (EKS 권장) Prefix Delegation(/28)로 노드당 Pod 수 확대
aws-vpc-cni는 Prefix Delegation을 켜면 ENI에 개별 secondary IP를 하나씩 붙이는 대신 /28 프리픽스(16 IP) 단위로 할당받아 Pod IP를 더 효율적으로 운영할 수 있습니다.
설정은 환경/버전에 따라 다르지만, 일반적으로 ENABLE_PREFIX_DELEGATION=true를 사용합니다.
kubectl -n kube-system set env daemonset aws-node \
ENABLE_PREFIX_DELEGATION=true
kubectl -n kube-system rollout status ds/aws-node
주의사항:
- CNI 버전이 해당 기능을 안정적으로 지원하는지 확인
- 인스턴스 타입/ENI 제한과 결합해 실제 증가 폭이 달라짐
- Prefix를 쓰면 “노드가 서브넷에서 가져가는 IP 덩어리”가 커지므로 서브넷 설계가 더 중요해집니다.
5-3. 인스턴스 타입 변경: ENI/IP 한계가 낮은 타입 피하기
같은 노드 수여도 인스턴스 타입에 따라 Pod 수용량이 크게 갈립니다.
- 작은 타입: ENI 수/ENI당 IP가 적어 Pod IP가 빨리 고갈
- 큰 타입: 더 많은 ENI/IP로 Pod 밀도가 증가
실제로는 애플리케이션 리소스(CPU/메모리)보다 네트워크(IP) 가 먼저 병목이 되는 케이스가 많습니다.
5-4. 노드당 Pod 상한(--max-pods)과 CNI 설정의 정합성
노드가 이론상 IP를 더 붙일 수 있어도, kubelet의 --max-pods가 낮게 잡혀 있으면 과도한 스케줄링은 막히지만(그나마 안전), 반대로 --max-pods가 너무 높으면 스케줄러는 넣는데 CNI가 못 받쳐서 Pending 이 증가할 수 있습니다.
- EKS AMI는 인스턴스 타입에 맞춰
maxPods를 계산해 주는 편이지만, - 커스텀 AMI/부트스트랩 옵션을 쓰면 불일치가 생길 수 있습니다.
5-5. (대안) 오버레이 CNI/Secondary Network 고려
VPC-native 방식이 IP를 너무 많이 소비한다면, 오버레이 네트워크(예: Calico overlay, Cilium overlay)로 전환하거나, 대규모 멀티테넌트 환경에서는 Secondary CIDR/추가 네트워크 인터페이스 설계도 검토합니다.
다만 이는 운영/보안/성능 특성이 달라지므로 PoC 후 단계적으로 진행하는 것이 안전합니다.
6) 재발 방지: 관측(Observability)과 운영 규칙
6-1. 서브넷 IP 잔량 알람
가장 먼저 해야 할 것은 서브넷 AvailableIpAddressCount 알람입니다.
- CloudWatch(또는 외부 모니터링)로 임계치 경보
- 예: 20% 이하 또는 절대값 256 이하 등, 환경에 맞게 설정
6-2. 노드 단위 IP 여유 모니터링
EKS라면 aws-node/ipamd 메트릭을 수집해 “노드별 남은 IP”를 시각화하세요.
- 노드별 warm IP가 0에 수렴하는 패턴
- 스케일 이벤트 직후 Pending 급증
6-3. 배치/크론잡의 Pod 누수 방지
Job이 끝났는데 Pod가 남아 IP를 점유하는 상황을 막기 위해 TTL을 적극 활용합니다.
apiVersion: batch/v1
kind: Job
metadata:
name: sample-job
spec:
ttlSecondsAfterFinished: 3600
template:
spec:
restartPolicy: Never
containers:
- name: worker
image: busybox
command: ["sh", "-c", "echo hello; sleep 5"]
7) 트러블슈팅 예시 시나리오(실전 흐름)
kubectl get pod -A | grep Pendingkubectl describe pod ...에서FailedCreatePodSandBox+ CNI IP 할당 실패 확인aws ec2 describe-subnets ...로 서브넷 IP 잔량 확인- 잔량 충분: 노드 레벨 문제(ENI/IP 한계, warm IP 부족, CNI 꼬임)
- 잔량 부족: 서브넷/대역 설계 문제(확장/추가 필요)
- 즉시 완화: 노드 스케일 아웃 또는 drain/교체
- 근본 해결: 서브넷 확장/추가 + Prefix Delegation + 인스턴스 타입/
max-pods정합성 재검토
8) 마무리
Pod Pending은 원인이 다양하지만, CNI IP 부족은 “증상은 단순한데 원인은 설계(대역/인스턴스/할당 방식)에 걸쳐 있는” 대표적인 문제입니다. 장애 대응에서는 노드 확장/드레인으로 일단 불을 끄고, 이후에는 서브넷 IP 잔량 알람과 Prefix Delegation 같은 구조적 개선으로 재발을 줄이는 것이 정석입니다.
노드가 NotReady까지 동반하거나, CNI/보안그룹/IRSA 이슈가 섞여 원인이 복합적으로 보인다면 아래 글의 점검 순서가 도움이 됩니다.