- Published on
EKS 노드 NotReady일 때 CNI·IP 고갈 진단
- Authors
- Name
- 스타차일드
- https://x.com/ETFBITX
EKS에서 노드가 NotReady로 바뀌면 대부분은 kubelet 자체 문제라기보다, 노드가 Pod 네트워크를 구성하지 못하는 상황에서 연쇄적으로 발생합니다. 특히 AWS VPC CNI를 쓰는 기본 구성에서는 다음 두 축이 압도적으로 자주 원인입니다.
- CNI 플러그인 상태 이상:
aws-node데몬셋이 죽었거나, iptables 규칙/ENI attach가 꼬였거나, IMDS·권한 문제로 CNI가 IP를 할당하지 못함 - IP 고갈: 서브넷의 사용 가능한 IP가 부족하거나, 노드에 붙일 수 있는 ENI·secondary IP 한도가 꽉 차서 새 Pod가 IP를 못 받음
이 글은 “노드가 NotReady”라는 결과에서 출발해, CNI 문제인지 IP 고갈인지를 빠르게 갈라내고, 바로 적용 가능한 복구 및 재발 방지 설정까지 정리합니다.
관련해서 readiness 관점에서 헷갈리는 케이스는 아래 글도 함께 참고하면 좋습니다.
1) 먼저 증상 분기: NotReady가 의미하는 것
노드가 NotReady일 때 가장 먼저 확인할 것은 노드 조건(Conditions) 과 최근 이벤트(Events) 입니다.
kubectl get nodes -o wide
kubectl describe node <node-name>
kubectl describe node에서 특히 다음을 봅니다.
Conditions에서Ready=False사유NetworkUnavailable=True여부KubeletNotReady메시지에network plugin is not ready같은 문구Allocated resources가 아니라Events에 반복되는 네트워크/샌드박스 생성 실패
대표적인 신호는 아래와 같습니다.
A. CNI 쪽이 유력한 신호
NetworkUnavailable가True- 이벤트에
CNI failed to set up pod network또는failed to assign an IP address to container비슷한 문구 aws-node파드가 해당 노드에서CrashLoopBackOff또는ImagePullBackOff
B. IP 고갈이 유력한 신호
- 새 파드가
Pending에서 안 뜨고FailedCreatePodSandBox이벤트 - 메시지에
Insufficient pods또는 IP 할당 실패 관련 문구 - 특정 서브넷에 노드가 몰린 뒤부터 갑자기 발생
이제부터는 클러스터 내부에서 확인할 것과 AWS 네트워크 자원에서 확인할 것을 순서대로 진행합니다.
2) 클러스터 내부에서 CNI 상태 1차 확인
2-1. aws-node 데몬셋이 정상 배포됐는지
kubectl -n kube-system get ds aws-node
kubectl -n kube-system get pods -l k8s-app=aws-node -o wide
여기서 체크 포인트는 다음입니다.
DESIRED와READY가 동일한지- 문제가 있는 노드에
aws-node가 실제로 뜨는지 aws-node가 뜨더라도Running인지, 재시작이 과도한지
특정 노드에서만 문제가 나면 해당 노드의 aws-node 로그를 봅니다.
kubectl -n kube-system logs -l k8s-app=aws-node --tail=200
kubectl -n kube-system logs <aws-node-pod> -c aws-node --tail=300
로그에서 자주 보이는 키워드는 아래입니다.
AssignPodIPv4Address실패failed to allocate또는ipamd관련 에러- IMDS 접근 실패(예: 토큰/홉 제한) 또는 EC2 API 호출 권한 부족
2-2. 노드 이벤트에서 샌드박스 생성 실패 확인
kubectl get events -A --sort-by=.lastTimestamp | tail -n 80
자주 나오는 형태는 다음과 같습니다.
FailedCreatePodSandBoxFailed to create pod sandbox: rpc error이후 CNI 관련 메시지
이 단계에서 aws-node가 아예 죽어 있으면 CNI 장애가 우선입니다. 반대로 aws-node는 정상인데 계속 IP 할당 실패가 나오면 IP 고갈 가능성이 급상승합니다.
3) IP 고갈인지 빠르게 판별하는 핵심: 서브넷 IP와 노드 Pod 한도
AWS VPC CNI 환경에서 “IP 고갈”은 보통 두 가지 중 하나입니다.
- 서브넷 Free IP 부족: 서브넷 자체에 남은 IP가 거의 없음
- 노드가 가질 수 있는 Pod 수 한도 도달: 인스턴스 타입별 ENI 수와 ENI당 secondary IP 수 제한
3-1. 서브넷 가용 IP 확인(AWS CLI)
노드가 속한 서브넷을 확인한 뒤, 해당 서브넷의 AvailableIpAddressCount를 봅니다.
aws ec2 describe-instances \
--instance-ids <instance-id> \
--query 'Reservations[0].Instances[0].SubnetId' \
--output text
aws ec2 describe-subnets \
--subnet-ids <subnet-id> \
--query 'Subnets[0].AvailableIpAddressCount' \
--output text
운영 경험상 다음이면 위험 신호입니다.
AvailableIpAddressCount가 두 자릿수 이하- 오토스케일로 노드가 늘어나는 시간대에 급격히 감소
3-2. 노드의 Pod 최대치 확인
Kubernetes는 노드마다 최대 Pod 수 제한을 가질 수 있고, EKS는 보통 인스턴스 타입 기반으로 제한이 잡힙니다.
kubectl describe node <node-name> | sed -n '1,120p'
출력 중 Capacity 또는 Allocatable의 pods 값을 봅니다. 이 값이 낮고, 실제 파드 수가 근접해 있다면 IP 할당 실패가 발생할 수 있습니다.
현재 노드에 떠 있는 파드 수는 아래로 확인합니다.
kubectl get pods -A -o wide --field-selector spec.nodeName=<node-name> | wc -l
pods 한도 근처인데 신규 파드가 계속 스케줄되면 CNI는 정상이어도 IP를 못 주는 상태가 됩니다.
4) 흔한 원인 1: ENI·secondary IP 한도 도달
AWS VPC CNI는 노드에 ENI를 붙이고, ENI에 secondary IP를 여러 개 붙여서 Pod IP로 사용합니다. 따라서 인스턴스 타입별 한도에 도달하면 신규 Pod가 IP를 못 받습니다.
인스턴스의 현재 네트워크 인터페이스 상태를 확인합니다.
aws ec2 describe-instances \
--instance-ids <instance-id> \
--query 'Reservations[0].Instances[0].NetworkInterfaces[*].{Id:NetworkInterfaceId,PrivateIps:PrivateIpAddresses}'
여기서 ENI 수가 이미 많고, 각 ENI의 secondary IP가 가득 차 있다면 “노드 단위 IP 고갈”입니다.
즉시 대응
- 파드를 다른 노드로 분산(스케줄링 제약 완화)
- 노드 증설 시 서브넷 분산(다중 서브넷)
- 인스턴스 타입을 ENI/IP 여유가 큰 타입으로 변경
5) 흔한 원인 2: 서브넷 자체 IP 고갈
서브넷 IP 고갈은 “클러스터 전체가 동시에 이상해지는” 양상으로 나타납니다. 특히 신규 노드가 뜨지 않거나, 뜨더라도 파드가 못 붙습니다.
즉시 대응
- 더 큰 CIDR의 서브넷으로 확장(새 서브넷 추가 후 노드그룹이 사용하도록)
- 노드그룹을 다른 서브넷으로 분산
- 불필요하게 IP를 점유하는 리소스 정리(테스트 노드, 오래된 ENI, 남은 로드밸런서 등)
서브넷 설계 문제는 다른 클라우드에서도 유사하게 터집니다. IP 대역 충돌과 설계 관점은 아래 글도 참고할 만합니다.
6) 흔한 원인 3: aws-node는 떠 있는데 CNI가 IP를 못 주는 케이스
IP가 남아 있는데도 IP 할당이 실패한다면 보통 다음을 의심합니다.
aws-node권한 문제(IRSA 또는 노드 IAM Role 정책 누락)- IMDS 접근 문제(예: IMDSv2 강제, hop limit)
iptables또는 커널 네트워크 설정 꼬임- CNI 버전 이슈 또는 업그레이드 중 불일치
6-1. aws-node가 사용하는 권한 점검
EKS에서 AWS VPC CNI는 EC2 API로 ENI/IP를 붙이므로 권한이 필요합니다. aws-node가 IRSA를 쓰는지, 아니면 노드 IAM Role에 정책이 붙어 있는지 확인해야 합니다.
kubectl -n kube-system get sa aws-node -o yaml
kubectl -n kube-system describe pod <aws-node-pod>
서비스어카운트 어노테이션에 role ARN이 없는데 IRSA를 기대하고 있었다면, 권한이 노드 role로만 가서 실패할 수 있습니다.
6-2. IMDS 접근 문제 확인
CNI가 인스턴스 메타데이터(IMDS)에서 정보를 읽는 과정이 막히면 장애가 납니다. 노드에서 IMDS가 접근 가능한지 확인합니다.
kubectl debug node/<node-name> -it --image=public.ecr.aws/amazonlinux/amazonlinux:2 -- bash
# 디버그 컨테이너 내부
curl -s -m 2 http://169.254.169.254/latest/meta-data/instance-id || echo fail
여기서 실패하면 보안 설정이나 IMDSv2 정책을 의심해야 합니다.
7) 운영에서 바로 먹히는 재발 방지 설정
7-1. WARM_IP_TARGET 또는 MINIMUM_IP_TARGET로 버퍼 확보
AWS VPC CNI는 미리 IP를 확보해 두는 전략이 있습니다. 트래픽 급증 시 파드가 빠르게 늘어나면 “할당 지연”이 장애처럼 보일 수 있으니 버퍼를 둡니다.
아래는 aws-node 데몬셋 환경변수 예시입니다.
kubectl -n kube-system set env ds/aws-node \
WARM_IP_TARGET=5 \
MINIMUM_IP_TARGET=10
WARM_IP_TARGET: 노드가 여유로 들고 있을 secondary IP 개수MINIMUM_IP_TARGET: 최소 확보할 IP 총량(상황에 따라 더 직관적)
값은 인스턴스 타입과 파드 증가 패턴에 따라 튜닝해야 하며, 너무 크게 잡으면 서브넷 IP를 빨리 소모합니다.
7-2. 서브넷 분산과 노드그룹 설계
- 한 AZ, 한 서브넷에 노드가 몰리지 않게 노드그룹 서브넷을 여러 개로 구성
- 워크로드 성격별로 노드그룹을 분리해 “IP 많이 먹는 워크로드”가 전체를 고갈시키지 않게 격리
7-3. 모니터링 포인트(알람 추천)
- 서브넷
AvailableIpAddressCount임계치 알람 kube-system의aws-node재시작 횟수 알람- 클러스터 이벤트에서
FailedCreatePodSandBox급증 감지
8) 10분 트러블슈팅 체크리스트
아래 순서대로 하면 원인 분리가 빠릅니다.
kubectl describe node <node-name>에서NetworkUnavailable및 이벤트 확인kubectl -n kube-system get pods -l k8s-app=aws-node -o wide로 문제 노드의aws-node상태 확인kubectl -n kube-system logs <aws-node-pod> -c aws-node에서 IP 할당 실패/권한/IMDS 키워드 확인- AWS CLI로 서브넷
AvailableIpAddressCount확인 - 노드
Allocatable pods와 현재 파드 수 비교 - 인스턴스 ENI 및 secondary IP가 한도에 닿았는지 확인
- 단기 복구(노드 교체, 서브넷 분산, 파드 분산) 후 재발 방지(
WARM_IP_TARGET등) 적용
9) 마무리: NotReady는 결과, 원인은 “IP를 못 주는 네트워크”인 경우가 많다
EKS 노드 NotReady는 표면적으로는 노드 상태 문제처럼 보이지만, 실제로는 CNI가 Pod 네트워크를 구성하지 못하는 상태로 귀결되는 경우가 많습니다. 그중에서도 AWS VPC CNI 환경에서는 “서브넷 IP 고갈”과 “노드 ENI·secondary IP 한도”가 가장 흔한 병목입니다.
장애 대응에서는 aws-node 상태와 서브넷 가용 IP를 동시에 확인해 원인을 빠르게 분리하고, 운영에서는 서브넷 설계·분산과 IP 버퍼링 설정으로 재발을 막는 것이 핵심입니다.