Published on

EKS 노드 드레인 지연 - CNI·IP 고갈 해결

Authors

서버를 롤링 업데이트하거나 노드그룹을 교체할 때 kubectl drain 이 예상보다 오래 걸리면 운영자는 보통 PDBterminationGracePeriodSeconds 를 먼저 의심합니다. 그런데 EKS에서는 드레인 자체가 막힌 것처럼 보이는 현상이 실제로는 CNI 레벨의 IP 고갈에서 시작되는 경우가 많습니다. 특히 aws-vpc-cni 를 쓰는 기본 구성에서는 노드가 파드에 VPC IP를 직접 할당하기 때문에, IP가 모자라면 파드가 새 노드로 뜨지 못하고, 그 결과 기존 노드의 파드가 안전하게 빠져나가지 못해 드레인이 지연됩니다.

이 글에서는 드레인 지연이 왜 CNI와 IP 고갈로 이어지는지, 어떤 지표와 이벤트로 확신할 수 있는지, 그리고 재발 방지까지 포함한 해결책을 순서대로 정리합니다.

관련해서 EKS에서 네트워크 또는 AWS API 경로 문제로 증상이 겹칠 수 있으니, 필요하면 EKS Pod에서 STS 502 Bad Gateway 원인·해결 도 함께 점검해보면 좋습니다.

1) 증상: 드레인이 멈춘 게 아니라, 새 파드가 못 뜨는 것

노드 드레인이 지연되는 전형적인 흐름은 다음과 같습니다.

  1. 드레인으로 기존 노드의 파드가 Evicted 되거나 Terminating 으로 전환됨
  2. 디플로이먼트나 레플리카셋이 다른 노드에 파드를 다시 띄우려 함
  3. 그런데 새 파드가 Pending 상태로 오래 머무름
  4. 기존 노드에는 여전히 종료되지 못한 파드가 남아 있고, 노드는 cordon 상태로 오래 유지됨

이때 kubectl drain 로그는 대개 PDB 또는 강제 종료 이슈처럼 보이지만, 실제 원인은 스케줄링 이후 단계인 CNI IP 할당 실패인 경우가 있습니다.

자주 보이는 이벤트 패턴

  • 파드 이벤트에 FailedCreatePodSandBox 가 반복
  • 메시지에 failed to assign an IP address to container 류 문구
  • 노드 이벤트나 aws-node 로그에서 IPAMD 관련 에러

2) 왜 IP 고갈이 드레인을 지연시키나

EKS 기본 CNI인 aws-vpc-cni 는 각 파드에 VPC의 프라이빗 IP를 붙입니다. 구현 관점에서 보면 노드의 ENI에 할당된 secondary IP 풀을 ipamd 가 관리하고, 파드가 뜰 때 그 풀에서 IP를 하나씩 소비합니다.

드레인 과정에서 중요한 포인트는 이겁니다.

  • 기존 노드에서 파드를 빼면, 그 파드는 다른 노드에 재스케줄링되어야 함
  • 재스케줄링된 노드에서 새 IP를 할당할 수 있어야 파드가 Running으로 올라옴
  • 그런데 클러스터 전체 또는 특정 AZ에서 IP가 부족하면 새 파드가 못 뜸
  • 그러면 레플리카 수가 회복되지 않아 PDB 조건을 만족하지 못하고, 결과적으로 기존 파드 종료가 지연됨

즉, 드레인 지연은 결과이고, 원인은 새 파드를 받을 수 있는 네트워크 리소스 부족인 경우가 많습니다.

3) 빠른 진단 체크리스트

아래는 현장에서 가장 빨리 확신을 주는 순서입니다.

3-1) Pending 파드 이벤트 확인

kubectl get pod -A --field-selector=status.phase=Pending
kubectl describe pod -n <namespace> <pod-name>

위 명령에서 describe 이벤트에 다음과 같은 문구가 있으면 IP 고갈 가능성이 큽니다.

  • FailedCreatePodSandBox
  • failed to setup network for sandbox
  • failed to assign an IP address

주의: 본문에서 <namespace> 같은 표기는 MDX에서 JSX로 오인될 수 있으니, 반드시 인라인 코드로 감싼 형태로만 사용하세요.

3-2) aws-node 데몬셋 로그에서 IPAMD 확인

kubectl -n kube-system get ds aws-node
kubectl -n kube-system logs -l k8s-app=aws-node --tail=200

대표적으로 다음 키워드를 찾습니다.

  • ipamd
  • InsufficientCidrBlocks
  • AssignPrivateIpAddresses 실패
  • No available IP addresses

3-3) 노드당 파드 밀도와 인스턴스 타입 한계 확인

인스턴스 타입별로 ENI 개수와 IP per ENI 한계가 있어, 노드당 붙일 수 있는 파드 수 상한이 결정됩니다.

kubectl get nodes -o wide
kubectl describe node <node-name> | sed -n '1,120p'
kubectl get pods -A -o wide | grep <node-name> | wc -l

노드에 파드가 많고, 새 파드가 특정 노드에만 몰리면 해당 노드의 IP 풀 고갈이 먼저 발생합니다.

3-4) 서브넷 여유 IP 확인

노드가 속한 서브넷 자체에 여유 IP가 없으면, 새 노드가 뜨거나 ENI에 secondary IP를 더 붙이는 단계에서 막힙니다.

aws ec2 describe-subnets \
  --subnet-ids subnet-xxx subnet-yyy \
  --query 'Subnets[].{SubnetId:SubnetId,Az:AvailabilityZone,AvailableIpAddressCount:AvailableIpAddressCount,CidrBlock:CidrBlock}' \
  --output table

AvailableIpAddressCount 가 낮다면 즉시 조치가 필요합니다.

4) 즉시 효과 있는 해결책 6가지

여기부터는 우선순위를 두고 정리합니다. 운영 환경에서는 보통 1번부터 순서대로 적용하면 됩니다.

4-1) 서브넷 확장 또는 신규 서브넷 추가

가장 근본적인 해결은 IP 풀이 더 큰 서브넷을 확보하는 것입니다.

  • 기존 서브넷 CIDR 확장이 가능한 구조라면 확장
  • 어렵다면 같은 AZ에 더 큰 신규 서브넷을 만들고 노드그룹이 그 서브넷을 사용하도록 변경

주의할 점:

  • EKS 노드그룹이 여러 서브넷을 쓰도록 구성하면 AZ 단위로 IP 압박이 분산됩니다.
  • 서브넷이 작으면 오토스케일링이 오히려 장애를 증폭시킵니다. 노드가 늘수록 IP를 더 빨리 소모하기 때문입니다.

네트워크 경로 자체 점검이 필요하면 VPC 라우트, SG, NACL도 같이 보세요. 이때는 AWS VPC 피어링 통신 불가? 라우트·SG·NACL 점검 의 체크리스트가 도움이 됩니다.

4-2) VPC CNI에 Prefix Delegation 적용

aws-vpc-cni 는 Prefix Delegation을 지원합니다. 개별 secondary IP를 하나씩 붙이는 대신 프리픽스를 위임받아 IP 할당 효율을 올려, 노드당 파드 수를 늘리고 IP 할당 API 호출을 줄이는 효과가 있습니다.

대표 설정 예시는 다음과 같습니다.

kubectl -n kube-system set env daemonset/aws-node \
  ENABLE_PREFIX_DELEGATION=true \
  WARM_PREFIX_TARGET=1

적용 후 aws-node 롤링 업데이트가 일어나며, 노드별 IP 관리 방식이 바뀝니다.

주의:

  • 인스턴스 타입, CNI 버전, VPC 설정에 따라 기대 효과가 다를 수 있습니다.
  • 적용 전후로 파드 밀도와 aws-node 로그를 비교하세요.

4-3) WARM 타겟 튜닝으로 드레인 중 스파이크 완화

드레인이나 롤링 업데이트 때는 파드가 한꺼번에 다른 노드로 이동하면서 IP 수요가 순간적으로 튑니다. 이때는 warm pool을 늘려서 완충할 수 있습니다.

kubectl -n kube-system set env daemonset/aws-node \
  WARM_IP_TARGET=10 \
  MINIMUM_IP_TARGET=5
  • WARM_IP_TARGET: 미리 확보해둘 IP 수
  • MINIMUM_IP_TARGET: 최소 보장 IP 수

값은 워크로드 특성에 따라 다르지만, 드레인 시점에 FailedCreatePodSandBox 가 폭증한다면 우선 임시로 올려서 증상을 완화할 수 있습니다.

4-4) 노드 인스턴스 타입 상향 또는 파드 밀도 낮추기

IP 고갈이 “서브넷 전체”가 아니라 “노드당 ENI 한계”에서 오는 경우가 있습니다. 예를 들어 파드가 많은데 인스턴스 타입이 ENI/IP 한계가 낮으면, 노드가 아직 CPU나 메모리는 남아도 네트워크가 먼저 포화됩니다.

대응 방법:

  • ENI 한계가 더 높은 인스턴스 타입으로 변경
  • maxPods 값을 낮춰 과밀 스케줄링 방지
  • 워크로드를 더 많은 노드로 분산

EKS 관리형 노드그룹이면 런치 템플릿과 함께 maxPods 설정을 점검하세요.

4-5) PDB와 종료 유예시간을 “원인 제거 후” 조정

PDB는 드레인 지연의 직접 원인처럼 보이지만, IP 고갈 상태에서 PDB를 완화하면 가용성을 해칠 수 있습니다. 권장 순서는 다음입니다.

  1. IP 고갈을 먼저 해소해서 새 파드가 정상적으로 뜨게 만들기
  2. 그 다음에도 드레인이 느리면 PDB, terminationGracePeriodSeconds, preStop 훅 등을 조정

즉, PDB는 마지막에 건드리는 게 안전합니다.

4-6) 관측 지표 추가: 재발을 “드레인 전에” 잡기

재발 방지를 위해서는 드레인 시점이 아니라 평상시에 경보를 올려야 합니다.

추천 관측 포인트:

  • 서브넷 AvailableIpAddressCount 를 CloudWatch로 수집 후 임계치 알람
  • aws-node 로그에서 IP 할당 실패 카운트 기반 알람
  • kube-systemaws-node 재시작 횟수 증가 감시

5) 재현 가능한 트러블슈팅 시나리오

현장에서 원인 규명할 때는 아래처럼 “증상에서 원인까지”를 한 번에 묶어 기록하면 좋습니다.

시나리오: 드레인 중 Pending 증가

  1. 드레인 시작
kubectl cordon <node-name>
kubectl drain <node-name> --ignore-daemonsets --delete-emptydir-data --grace-period=60
  1. Pending 파드 확인
kubectl get pod -A --field-selector=status.phase=Pending
  1. Pending 파드 이벤트에서 CNI 에러 확인
kubectl describe pod -n `namespace` `pod-name`
  1. aws-node 로그 확인
kubectl -n kube-system logs -l k8s-app=aws-node --tail=200 | grep -i -E 'ipamd|assign|prefix|insufficient|available'
  1. 서브넷 여유 IP 확인
aws ec2 describe-subnets \
  --filters Name=vpc-id,Values=vpc-xxx \
  --query 'Subnets[].{SubnetId:SubnetId,Az:AvailabilityZone,AvailableIpAddressCount:AvailableIpAddressCount,CidrBlock:CidrBlock}' \
  --output table

이 흐름에서 3, 4, 5 중 두 개 이상이 맞아떨어지면, 드레인 지연의 1차 원인을 IP 고갈로 결론 내려도 됩니다.

6) 운영 팁: 드레인 전략을 IP 관점에서 다시 설계하기

IP 고갈이 반복되는 환경에서는 드레인 전략 자체를 다음처럼 바꾸는 게 효과적입니다.

  • 노드그룹 교체 시 한 번에 많은 노드를 내리지 말고, maxUnavailable 을 낮춰 천천히 교체
  • 클러스터 오토스케일러가 스케일아웃할 때, 신규 노드가 들어갈 서브넷의 여유 IP를 사전 점검
  • 대규모 배포 직후 드레인을 걸지 말고, IP warm pool이 회복된 뒤 진행

특히 배포 직후에는 파드 재시작과 HPA 변동으로 IP 수요가 증가할 수 있어, 드레인과 겹치면 문제가 증폭됩니다.

7) 마무리

EKS에서 노드 드레인이 지연될 때 핵심은 “드레인이 왜 안 끝나지”가 아니라 “새 파드가 왜 못 뜨지”로 관점을 바꾸는 것입니다. aws-vpc-cni 환경에서는 이 질문이 곧 IP 고갈로 이어지고, 서브넷 설계, Prefix Delegation, warm 타겟 튜닝, 인스턴스 타입 한계까지 한 번에 점검해야 재발을 막을 수 있습니다.

만약 IP는 충분해 보이는데도 네트워크 호출이 불안정하고 파드가 간헐적으로 실패한다면, AWS 엔드포인트 경로 문제도 함께 의심해보세요. 이 경우에는 EKS Pod에서 S3 403 AccessDenied 원인 10가지 처럼 IAM과 네트워크 경계에서 발생하는 이슈가 드레인 시점에 함께 드러나기도 합니다.