본문 바로가기

쿠버네티스

Kubernetes에서 노드 삭제 시 발생하는 서비스 지연 현상

Kubernetes 환경에서 kubectl delete node <node-name> 명령을 실행하면 단순히 노드가 제거될 뿐이라고 생각하기 쉽습니다. 하지만 실제 운영 환경에서는 이 명령 이후 일부 서비스에서 일시적인 응답 지연이나 연결 실패가 발생하는 경우가 있습니다. 이 글에서는 이러한 현상이 발생하는 원인을 체계적으로 분석하고, 사전에 할 수 있는 조치와 점검 항목까지 자세히 설명합니다.

목차

 

1. 현상 정의

 

kubectl delete node 명령을 실행한 직후, 다음과 같은 문제가 관찰될 수 있습니다:

  • 일부 서비스의 응답 지연
  • 일시적인 연결 끊김 또는 리퀘스트 실패
  • 이미 종료된 Pod로 트래픽이 전달되어 오류 발생

이러한 문제는 Pod 자체는 이미 제거되었더라도, Kubernetes 리소스의 정리 과정 또는 서비스 디스커버리 체계의 지연에 의해 발생할 수 있습니다. 특히 Endpoints 리소스의 반영 속도, CNI 플러그인의 반응성, 컨트롤 플레인의 성능 등이 중요한 변수로 작용합니다.

2. 원인 분석

(1) Service Endpoints 갱신 지연

Kubernetes의 서비스는 Endpoints 객체를 통해 연결 가능한 Pod의 목록을 관리합니다. 노드가 삭제될 경우, 해당 노드에 위치한 Pod가 종료되더라도 Endpoints 리소스에서 즉시 제거되지 않을 수 있습니다. 이때 클라이언트는 여전히 존재하지 않는 Pod의 IP로 요청을 보내게 되고, 이로 인해 연결 실패나 응답 지연이 발생할 수 있습니다.

(2) 컨트롤 플레인 반응 지연

노드 삭제 시 kube-controller-manager와 kube-apiserver가 관련 리소스를 정리하게 됩니다. 만약 API 서버에 부하가 있거나 네트워크 지연이 있는 경우, 이 정리 작업이 지연되면서 서비스 상태에도 영향을 미칩니다. 특히 수백 개 이상의 Pod가 배포된 대형 클러스터에서는 컨트롤 플레인의 처리 속도 자체가 병목이 될 수 있습니다.

(3) CNI 정리 지연

노드에서 Pod가 삭제되면 네트워크 인터페이스도 함께 제거되어야 합니다. 그러나 Cilium, Calico 같은 일부 CNI 플러그인의 처리 속도가 느릴 경우, stale한 iptables 룰이나 라우팅 설정이 남아 있어 트래픽이 잘못된 경로로 전달될 수 있습니다.

(4) CoreDNS 및 서비스 레지스트리 업데이트 지연

CoreDNS는 Kubernetes 내에서 서비스명을 IP로 해석하는 역할을 합니다. 이때 Endpoints 정보가 변경되었음에도 DNS 캐시나 TTL 값 때문에 변경 사항이 즉각 반영되지 않으면, 클라이언트가 삭제된 Pod의 IP를 참조하게 됩니다. 특히 StatefulSet 기반 서비스의 경우 이 문제가 더 빈번하게 나타납니다.

(5) 클라이언트 측 연결 캐싱

클라이언트 애플리케이션이 TCP KeepAlive, Connection Pool 또는 자체 DNS 캐시를 사용하는 경우, 삭제된 Pod IP에 대한 연결을 일정 시간 동안 유지하려고 시도합니다. 이로 인해 사용자는 이미 종료된 리소스에 요청을 보내게 되고, 이 역시 서비스 지연의 원인이 됩니다.

3. 조치 방법

(1) 노드 삭제 전에 Drain 수행

노드를 삭제하기 전에 항상 다음과 같은 drain 명령을 수행해야 합니다:

kubectl drain <node-name> --ignore-daemonsets --delete-emptydir-data

 

이 명령은 해당 노드의 Pod를 다른 노드로 이동시켜, Endpoints 정보도 안정적으로 갱신될 시간을 확보해 줍니다.

(2) 노드 상태 확인 후 Delete 수행

노드가 NotReady 상태이거나 Schedulable=False 상태인지 확인한 후 삭제하는 것이 바람직합니다. Ready 상태에서 갑작스럽게 노드를 제거하면 트래픽이 예기치 않게 단절될 가능성이 높습니다.

(3) CNI 연동 상태 확인

CNI 플러그인의 네트워크 설정이 제대로 정리되고 있는지 확인하려면 다음과 같은 명령을 사용할 수 있습니다:

kubectl logs -n kube-system <cni-pod-name>
# 또는
ip link
ip route

 

- Cilium을 사용하는 경우:

cilium endpoint list

(4) Endpoints 리소스 상태 확인

노드를 삭제한 직후, 특정 서비스의 Endpoints에 여전히 삭제된 Pod IP가 남아 있는지 확인합니다:

kubectl get endpoints <service-name> -o wide

(5) 서비스 설계 최적화

Pod가 준비되지 않은 상태에서 트래픽을 받지 않도록 readinessProbe 및 livenessProbe를 적절히 설정해야 합니다. 또한 externalTrafficPolicy나 sessionAffinity와 같은 설정은 트래픽 분산 방식에 큰 영향을 미치므로 사전에 영향 범위를 충분히 이해하고 구성해야 합니다.

4. 확인 및 진단 사항

항목 점검 내용
Service Type ClusterIP, NodePort, LoadBalancer에 따라 트래픽 처리 방식이 다름
CNI 종류 Calico, Flannel, Cilium 등 플러그인별 동작 차이 있음
CoreDNS 로그 name resolution timeout 또는 stale DNS 캐시 여부 확인
kube-proxy 상태 iptables 또는 IPVS 룰이 즉시 갱신되는지 확인
Service Endpoints TTL Endpoints가 얼마나 빠르게 갱신되는지 모니터링
클라이언트 설정 KeepAlive, Connection Pool, DNS 캐시 여부 확인

5. 결론

kubectl delete node 명령은 겉보기에는 단순한 작업이지만, 실제로는 다양한 리소스와 네트워크 설정이 복합적으로 얽혀 있는 과정입니다. Pod가 다른 노드에 안전하게 이동하고, 트래픽이 새로운 대상에 도달할 수 있도록 하려면 반드시 drain → 상태 확인 → delete의 순서를 지켜야 합니다. readinessProbe 설정을 철저히 하고, 네트워크와 서비스 구성을 사전에 검토하는 것만으로도 대부분의 서비스 지연을 방지할 수 있습니다.