Published on

Azure AKS 노드 NotReady - CNI IP 고갈 해결

Authors

AKS 운영 중 갑자기 일부 노드가 NotReady 로 바뀌고, 새 파드가 스케줄되지 않거나 기존 파드가 재시작을 반복하는 상황을 겪을 수 있습니다. 이때 노드 리소스(CPU, 메모리)는 충분해 보이는데도 장애가 발생한다면, CNI 네트워크 IP 고갈(IP exhaustion) 을 가장 먼저 의심해야 합니다.

특히 Azure CNI 계열은 파드가 VNet IP를 직접 소비하기 때문에(설정에 따라) 서브넷의 가용 IP가 바닥나면 노드가 파드를 더 이상 붙이지 못하고, 결과적으로 kubelet 및 네트워크 플러그인이 오류를 내면서 NotReady 로 전이되는 케이스가 실제로 자주 발생합니다.

이 글에서는

  • 증상 패턴과 빠른 판별법
  • Azure CNI(전통)와 Azure CNI Overlay, Kubenet의 차이
  • 즉시 복구(단기)와 구조 개선(중장기) 체크리스트
  • 재발 방지 모니터링 포인트

를 실전 관점에서 정리합니다.


1) 증상: NotReady인데 CPU/메모리는 멀쩡하다

CNI IP 고갈은 대체로 아래 증상으로 시작합니다.

  • 특정 노드에서만 파드 생성이 실패하거나 ContainerCreating 에 오래 머뭄
  • 이벤트에 FailedCreatePodSandBox , CNI failed to allocate IP 류 메시지 등장
  • 노드 상태가 NotReady 로 전환되거나 NetworkUnavailable 이 간헐적으로 표시
  • 오토스케일링이 켜져 있어도 파드가 계속 Pending(노드가 늘어도 서브넷이 작으면 해결 안 됨)

먼저 “노드가 죽었다” 라기보다 “노드가 네트워크 주소를 더 못 받는다” 로 접근하는 게 핵심입니다.


2) 10분 내 1차 진단: 이벤트와 CNI 로그로 확인

2.1 노드/파드 이벤트 확인

아래 명령으로 실패 이벤트를 빠르게 확인합니다.

kubectl get nodes -o wide
kubectl describe node <node-name>

kubectl get pods -A -o wide | grep -E "Pending|ContainerCreating"
kubectl describe pod -n <ns> <pod>

kubectl describe pod 의 Events 섹션에서 다음 키워드가 보이면 IP 고갈 가능성이 큽니다.

  • FailedCreatePodSandBox
  • failed to set up sandbox container
  • CNI failed to allocate IP
  • no available addresses

MDX 빌드 에러 방지를 위해 노드 이름과 네임스페이스 등 꺾쇠 표기는 모두 인라인 코드로 감쌌습니다.

2.2 Azure CNI 로그 확인(노드에서)

AKS 노드에 접속할 수 있다면(또는 kubectl debug node 를 활용한다면) Azure CNI 로그를 확인합니다.

# 노드에서
sudo journalctl -u kubelet -n 200 --no-pager

# Azure CNI 구성에 따라 경로가 다를 수 있음
sudo ls -al /var/log/azure-vnet*
sudo tail -n 200 /var/log/azure-vnet.log

로그에서 IP 할당 실패/풀 고갈을 의미하는 문구가 반복되면 원인이 거의 확정됩니다.


3) 원인 이해: Azure CNI에서 왜 IP가 빨리 고갈되나

AKS 네트워킹은 크게 다음 선택지로 나뉩니다.

  • Azure CNI(전통, VNet 통합): 파드가 VNet(서브넷) IP를 직접 소비하는 모델(구성/버전에 따라 동작 차이가 있으나, 운영 체감상 “서브넷 IP가 곧 파드 수 상한” 으로 이어지기 쉬움)
  • Azure CNI Overlay: 파드는 오버레이 대역을 사용하고, 노드만 VNet IP를 사용(서브넷 IP 압박이 크게 줄어듦)
  • Kubenet: 파드는 별도 CIDR, 노드만 VNet IP 사용(NAT 기반)

문제가 커지는 전형적인 조건은 아래와 같습니다.

  • 서브넷이 작다(예: /24 수준) + 노드가 많거나 파드 밀도가 높다
  • 오토스케일로 노드가 빠르게 늘었다(노드 자체도 IP를 소비)
  • 파드 churn(짧은 배치 잡, 잦은 롤링 업데이트)으로 IP가 빠르게 할당/해제 반복
  • 네트워크 정책/보안 요구로 Azure CNI를 선택했는데, 초기 IP 플래닝을 작게 잡았다

4) 즉시 복구(단기): “서비스를 살리는” 우선순위

아래는 장애 대응 관점에서 우선순위가 높은 순서입니다.

4.1 서브넷 가용 IP 확인 및 확장

가장 근본적이고 즉각적인 해결은 서브넷을 더 크게 만드는 것입니다. 다만 Azure에서 서브넷 프리픽스 변경은 제약이 있을 수 있어, 새 서브넷을 만들고 노드풀을 옮기는 방식이 현실적일 때가 많습니다.

  • Azure Portal 또는 CLI로 서브넷의 사용 가능한 IP를 확인
  • 여유가 없다면 더 큰 주소 공간을 가진 새 서브넷 준비

CLI 예시:

az network vnet subnet show \
  --resource-group <rg> \
  --vnet-name <vnet> \
  --name <subnet> \
  --query "{prefix:addressPrefix, ipConfigs:length(ipConfigurations)}"

ipConfigurations 는 리소스에 따라 해석이 달라 “정확한 가용 IP” 를 그대로 보여주진 않지만, 운영 중에는 서브넷 크기 자체(/23, /22 등)가 충분한지부터 재검토하는 게 중요합니다.

4.2 새 노드풀을 더 큰 서브넷에 만들고 워크로드 이동

서브넷 프리픽스를 직접 늘리기 어렵다면, 새 서브넷 + 새 노드풀 로 우회하는 것이 일반적입니다.

az aks nodepool add \
  --resource-group <rg> \
  --cluster-name <aks> \
  --name <newpool> \
  --vnet-subnet-id <subnet-resource-id> \
  --node-count 3

그 다음 기존 노드풀을 cordon 하고 drain 해서 파드를 새 노드풀로 이동시킵니다.

kubectl cordon <old-node>
kubectl drain <old-node> --ignore-daemonsets --delete-emptydir-data --grace-period=60

주의: drain 은 PDB, 우선순위, 스팟 노드 정책 등과 충돌할 수 있습니다. 대규모 드레인 전략은 아래 글의 “퇴거 루프” 관점도 함께 참고하면 좋습니다.

(클라우드는 다르지만, 쿠버네티스 레벨에서 퇴거가 막히는 패턴은 유사합니다.)

4.3 임시로 파드 밀도 낮추기

구조 변경 전에 급한 불을 끄려면 “파드 수를 줄여 IP를 회수” 해야 합니다.

  • 불필요한 배치/크론잡 중지
  • 과도하게 복제된 디플로이먼트 스케일 다운
  • 장애 중인 HPA가 폭증시키는지 확인
kubectl scale deploy -n <ns> <deploy> --replicas=2
kubectl get hpa -A

4.4 노드 재이미징/재부팅은 최후 수단

IP 고갈은 “주소가 없다” 가 본질이라, 노드 재시작은 일시적으로 좋아 보일 수 있어도 재발합니다. 오히려 churn을 늘려 IP 할당/해제 경합을 키울 수 있으니, 서브넷/네트워크 설계 변경 없이 재시작만 반복하는 대응은 피하는 편 이 좋습니다.


5) 중장기 해결: Azure CNI Overlay 또는 네트워크 재설계

5.1 Azure CNI Overlay로 전환 고려

서브넷 IP를 파드가 직접 잡아먹는 구조가 문제라면, Overlay 모델로 전환 하는 것이 가장 큰 체질 개선입니다.

  • 장점: 서브넷 IP 압박이 크게 감소, 노드 스케일에도 여유
  • 고려사항: 기존 워크로드의 네트워크 정책, 라우팅, 온프레미스 연동, 방화벽/UDR 설계 점검 필요

전환은 보통 “클러스터 재구성” 또는 “새 클러스터로 마이그레이션” 으로 접근하는 경우가 많습니다. 운영 중 클러스터에서 네트워크 모델을 바꾸는 것은 리스크가 커서, 블루/그린 방식이 안전합니다.

5.2 (Azure CNI 전통 사용 시) IP 플래닝 공식으로 상한 계산

운영에서 중요한 건 “현재 파드 수” 가 아니라 “최대 파드 수” 입니다.

  • 노드 수 최대치
  • 노드당 최대 파드 수(maxPods)
  • 시스템 데몬셋이 차지하는 파드
  • 여유 버퍼(롤링 업데이트 시 순간적으로 파드가 늘어나는 구간)

이를 기반으로 서브넷을 /22 이상 등으로 넉넉히 잡는 것이 일반적입니다(환경에 따라 다름).

AKS에서 노드풀 maxPods 확인 예시:

az aks nodepool show \
  --resource-group <rg> \
  --cluster-name <aks> \
  --name <pool> \
  --query "maxPods"

5.3 노드풀 분리로 IP burst를 격리

워크로드 성격에 따라 노드풀을 나누면 IP 고갈의 “전파” 를 줄일 수 있습니다.

  • 배치/크론잡 전용 노드풀(짧은 수명 파드가 많아 IP churn 큼)
  • 장기 서비스 전용 노드풀
  • 시스템 전용 노드풀(CoreDNS, ingress, 모니터링)

이렇게 분리하면 배치 폭주가 전체 서비스 노드풀의 IP를 잠식하는 상황을 완화할 수 있습니다.


6) 재발 방지: 관측(모니터링) 포인트 5가지

  1. 서브넷 가용 IP 알람
  • Azure Monitor로 서브넷 IP 사용률을 추적하고 임계치 알림 설정
  1. 노드 상태 변화 알람
  • NotReady 전환을 즉시 감지
  1. 파드 생성 실패 이벤트 수집
  • 이벤트에 FailedCreatePodSandBox 가 급증하면 네트워크 이슈 가능성 큼
  1. CNI 관련 로그 수집
  • 노드 로컬 로그만 보면 장애 시점에 접근이 어려움
  1. 배포 전략 점검
  • 롤링 업데이트에서 maxSurge 가 과도하면 순간 파드 수가 폭증해 IP를 빨리 소모

배포로 인한 순간 트래픽/오류가 함께 터지는 경우도 많습니다. 네트워크 이슈와 직접 관련은 없더라도, 장애 시 “겉으로 보이는 증상” 을 키우는 요인이 될 수 있어 아래 글의 체크리스트도 참고할 만합니다.


7) 실전 체크리스트: 장애 대응 순서(요약)

7.1 지금 당장(15분)

  • kubectl describe pod 이벤트에서 CNI failed to allocate IP 확인
  • 서브넷 크기와 가용 IP 확인
  • 불필요한 파드/잡 스케일 다운으로 IP 회수

7.2 1시간 내(복구 안정화)

  • 새 서브넷 준비가 가능하면, 새 노드풀 생성 후 워크로드 이동
  • 드레인 시 PDB/우선순위로 막히는지 점검

7.3 1주 내(재발 방지)

  • Azure CNI Overlay 또는 Kubenet 등 네트워크 모델 재검토
  • 노드풀 분리 및 maxPods 재설계
  • 서브넷 IP, CNI 이벤트/로그 기반 알람 구축

8) 마무리

AKS의 NotReady 는 원인이 다양하지만, CNI IP 고갈은 “리소스는 남아 있는데 클러스터가 멈추는” 전형적인 함정 입니다. 포인트는 두 가지입니다.

  • 진단은 이벤트에서 빠르게: FailedCreatePodSandBox 와 IP 할당 실패 로그
  • 해결은 주소 설계로: 서브넷 확장, 노드풀 이동, Overlay 전환 같은 구조적 개선

운영 환경에서 한 번이라도 IP 고갈을 겪었다면, 다음 장애는 “더 큰 트래픽” 이 아니라 “더 많은 파드” 에서 시작될 가능성이 큽니다. 서브넷과 노드풀 설계를 한 단계 넉넉하게 가져가고, 알람을 IP 관점으로 붙이는 것만으로도 재발 확률을 크게 낮출 수 있습니다.