Published on

EKS 노드 NotReady일 때 CNI·IP 고갈 진단

Authors

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 쪽이 유력한 신호

  • NetworkUnavailableTrue
  • 이벤트에 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

여기서 체크 포인트는 다음입니다.

  • DESIREDREADY가 동일한지
  • 문제가 있는 노드에 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

자주 나오는 형태는 다음과 같습니다.

  • FailedCreatePodSandBox
  • Failed 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 또는 Allocatablepods 값을 봅니다. 이 값이 낮고, 실제 파드 수가 근접해 있다면 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-systemaws-node 재시작 횟수 알람
  • 클러스터 이벤트에서 FailedCreatePodSandBox 급증 감지

8) 10분 트러블슈팅 체크리스트

아래 순서대로 하면 원인 분리가 빠릅니다.

  1. kubectl describe node <node-name>에서 NetworkUnavailable 및 이벤트 확인
  2. kubectl -n kube-system get pods -l k8s-app=aws-node -o wide로 문제 노드의 aws-node 상태 확인
  3. kubectl -n kube-system logs <aws-node-pod> -c aws-node에서 IP 할당 실패/권한/IMDS 키워드 확인
  4. AWS CLI로 서브넷 AvailableIpAddressCount 확인
  5. 노드 Allocatable pods와 현재 파드 수 비교
  6. 인스턴스 ENI 및 secondary IP가 한도에 닿았는지 확인
  7. 단기 복구(노드 교체, 서브넷 분산, 파드 분산) 후 재발 방지(WARM_IP_TARGET 등) 적용

9) 마무리: NotReady는 결과, 원인은 “IP를 못 주는 네트워크”인 경우가 많다

EKS 노드 NotReady는 표면적으로는 노드 상태 문제처럼 보이지만, 실제로는 CNI가 Pod 네트워크를 구성하지 못하는 상태로 귀결되는 경우가 많습니다. 그중에서도 AWS VPC CNI 환경에서는 “서브넷 IP 고갈”과 “노드 ENI·secondary IP 한도”가 가장 흔한 병목입니다.

장애 대응에서는 aws-node 상태와 서브넷 가용 IP를 동시에 확인해 원인을 빠르게 분리하고, 운영에서는 서브넷 설계·분산과 IP 버퍼링 설정으로 재발을 막는 것이 핵심입니다.