NotReady 상태의 노드
배경
Corporation XYZ의 DevOps 팀은 새로운 노드 그룹을 배포했고, 애플리케이션 팀은 retail-app 외부에 새로운 애플리케이션을 배포했습니다. 여기에는 Deployment(prod-app)와 이를 지원하는 DaemonSet(prod-ds)이 포함됩니다.
이러한 애플리케이션을 배포한 후, 모니터링 팀은 노드가 NotReady 상태로 전환되고 있다고 보고했습니다. 근본 원인이 즉시 명확하지 않으며, 당직 DevOps 엔지니어로서 노드가 응답하지 않는 이유를 조사하고 정상 작동을 복원하기 위한 솔루션을 구현해야 합니다.
Step 1: 노드 상태 확인
먼저 노드의 상태를 확인하여 현재 상태를 확인해 보겠습니다:
NAME STATUS ROLES AGE VERSION
ip-10-42-180-244.us-west-2.compute.internal NotReady <none> 15m v1.27.1-eks-2f008fe
Step 2: 노드 이름 내보내기
Step 3: 시스템 Pod 상태 확인
시스템 수준의 문제를 식별하기 위해 영향을 받는 노드의 kube-system Pod 상태를 살펴보겠습니다:
이 명령은 영향을 받는 노드에서 실행 중인 모든 kube-system Pod를 보여주며, 이러한 Pod로 인한 노드의 잠재적 문제를 식별하는 데 도움이 됩니다. 모든 Pod가 실행 중 상태임을 확인해야 합니다.
Step 4: 노드 Conditions 검토
NotReady 상태의 원인을 이해하기 위해 노드의 describe 출력을 살펴보겠습니다.
Taints: node.kubernetes.io/unreachable:NoExecute
node.kubernetes.io/unreachable:NoSchedule
Unschedulable: false
Conditions:
Type Status LastHeartbeatTime LastTransitionTime Reason Message
---- ------ ----------------- ------------------ ------ -------
MemoryPressure Unknown Wed, 12 Feb 2025 15:20:21 +0000 Wed, 12 Feb 2025 15:21:04 +0000 NodeStatusUnknown Kubelet stopped posting node status.
DiskPressure Unknown Wed, 12 Feb 2025 15:20:21 +0000 Wed, 12 Feb 2025 15:21:04 +0000 NodeStatusUnknown Kubelet stopped posting node status.
PIDPressure Unknown Wed, 12 Feb 2025 15:20:21 +0000 Wed, 12 Feb 2025 15:21:04 +0000 NodeStatusUnknown Kubelet stopped posting node status.
Ready Unknown Wed, 12 Feb 2025 15:20:21 +0000 Wed, 12 Feb 2025 15:21:04 +0000 NodeStatusUnknown Kubelet stopped posting node status.
Addresses:
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Starting 3m18s kube-proxy
Normal Starting 3m31s kubelet Starting kubelet.
Warning InvalidDiskCapacity 3m31s kubelet invalid capacity 0 on image filesystem
Normal NodeHasSufficientMemory 3m31s (x2 over 3m31s) kubelet Node ip-10-42-180-244.us-west-2.compute.internal status is now: NodeHasSufficientMemory
Normal NodeHasNoDiskPressure 3m31s (x2 over 3m31s) kubelet Node ip-10-42-180-244.us-west-2.compute.internal status is now: NodeHasNoDiskPressure
Normal NodeHasSufficientPID 3m31s (x2 over 3m31s) kubelet Node ip-10-42-180-244.us-west-2.compute.internal status is now: NodeHasSufficientPID
Normal NodeAllocatableEnforced 3m31s kubelet Updated Node Allocatable limit across pods
Normal RegisteredNode 3m27s node-controller Node ip-10-42-180-244.us-west-2.compute.internal event: Registered Node ip-10-42-180-244.us-west-2.compute.internal in Controller
Normal Synced 3m27s cloud-node-controller Node synced successfully
Normal ControllerVersionNotice 3m12s vpc-resource-controller The node is managed by VPC resource controller version v1.6.3
Normal NodeReady 3m10s kubelet Node ip-10-42-180-244.us-west-2.compute.internal status is now: NodeReady
Normal NodeTrunkInitiated 3m8s vpc-resource-controller The node has trunk interface initialized successfully
Warning SystemOOM 94s kubelet System OOM encountered, victim process: python, pid: 4763
Normal NodeNotReady 52s node-controller Node ip-10-42-180-244.us-west-2.compute.internal status is now: NodeNotReady
여기서 노드의 kubelet이 Unknown 상태에 있으며 연결할 수 없음을 알 수 있습니다. 이 상태에 대한 자세한 내용은 Kubernetes 문서에서 확인할 수 있습니다.
노드에는 다음과 같은 Taint가 있습니다:
- node.kubernetes.io/unreachable:NoExecute: 이 Taint를 허용하지 않는 Pod는 제거됨을 나타냅니다
- node.kubernetes.io/unreachable:NoSchedule: 새로운 Pod가 스케줄링되는 것을 방지합니다
노드 Conditions는 kubelet이 상태 업데이트 게시를 중단했음을 보여주며, 이는 일반적으로 심각한 리소스 제약이나 시스템 불안정을 나타낼 수 있습니다.
Step 5: CloudWatch Metrics 조사
Metrics Server가 데이터를 제공하지 않으므로 CloudWatch를 사용하여 EC2 인스턴스 메트릭을 확인해 보겠습니다:
편의를 위해 new_nodegroup_3의 워커 노드 인스턴스 ID가 환경 변수 $INSTANCE_ID로 저장되어 있습니다.
{"MetricDataResults": [
{"Id": "cpu",
"Label": "CPUUtilization",
"Timestamps": [
"2025-0X-XXT16:25:00+00:00",
"2025-0X-XXT16:20:00+00:00",
"2025-0X-XXT16:15:00+00:00",
"2025-0X-XXT16:10:00+00:00"
],
"Values": [
99.87333333333333,
99.89633636636336,
99.86166666666668,
62.67880324995537
],
"StatusCode": "Complete"
}
],
"Messages": []
}
CloudWatch 메트릭은 다음을 보여줍니다:
- CPU 사용률이 지속적으로 99% 이상
- 시간이 지남에 따라 리소스 사용량이 크게 증가
- 리소스 고갈의 명확한 징후
Step 6: 영향 완화
Deployment 세부 정보를 확인하고 노드를 안정화하기 위한 즉각적인 변경을 구현해 보겠습니다:
6.1. Deployment 리소스 구성 확인
NAME CPU_REQUEST MEM_REQUEST CPU_LIMIT MEM_LIMIT
prod-app-74b97f9d85-k6c84 100m 64Mi <none> <none>
prod-app-74b97f9d85-mpcrv 100m 64Mi <none> <none>
prod-app-74b97f9d85-wdqlr 100m 64Mi <none> <none>
...
...
prod-ds-558sx 100m 128Mi <none> <none>
Deployment와 DaemonSet 모두 리소 스 제한이 구성되어 있지 않으므로 무제한 리소스 소비가 가능했습니다.
6.2. Deployment를 스케일 다운하여 리소스 과부하 중지
6.3. 노드 그룹의 노드 재시작
이 작업은 1분 조금 넘게 걸릴 수 있습니다. 스크립트는 새 노드 이름을 NODE_NAME_2로 저장합니다.
6.4. 노드 상태 확인
NAME STATUS ROLES AGE VERSION
ip-10-42-180-24.us-west-2.compute.internal Ready <none> 0h43m v1.30.8-eks-aeac579
Step 7: 장기적인 솔루션 구현
개발 팀이 애플리케이션의 메모리 누수를 식별하고 수정했습니다. 수정 사항을 구현하고 적절한 리소스 관리를 설정해 보겠습니다:
7.1. 업데이트된 애플리케이션 구성 적용
7.2. Deployment에 대한 리소스 제한 설정 (cpu: 500m, memory: 512Mi)
7.3. DaemonSet에 대한 리소스 제한 설정 (cpu: 500m, memory: 512Mi)
7.4. 롤링 업데이트 수행 및 원하는 상태로 스케일 복원
Step 8: 검증
수정 사항이 문제를 해결했는지 확인해 보겠습니다:
8.1 Pod 생성 확인
NAME READY STATUS RESTARTS AGE
prod-app-666f8f7bd5-658d6 1/1 Running 0 1m
prod-app-666f8f7bd5-6jrj4 1/1 Running 0 1m
prod-app-666f8f7bd5-9rf6m 1/1 Running 0 1m
prod-app-666f8f7bd5-pm545 1/1 Running 0 1m
prod-app-666f8f7bd5-ttkgs 1/1 Running 0 1m
prod-app-666f8f7bd5-zm8lx 1/1 Running 0 1m
prod-ds-ll4lv 1/1 Running 0 1m
8.2. Pod 제한 확인
NAME CPU_REQUEST MEM_REQUEST CPU_LIMIT MEM_LIMIT
prod-app-6d67889dc8-4hc7m 250m 256Mi 500m 512Mi
prod-app-6d67889dc8-6s8wr 250m 256Mi 500m 512Mi
prod-app-6d67889dc8-fd6kq 250m 256Mi 500m 512Mi
prod-app-6d67889dc8-gzcbn 250m 256Mi 500m 512Mi
prod-app-6d67889dc8-qvtvj 250m 256Mi 500m 512Mi
prod-app-6d67889dc8-rf478 250m 256Mi 500m 512Mi
prod-ds-srdqx 250m 256Mi 500m 512Mi
8.3 노드 CPU 리소스 확인
{"MetricDataResults": [
{"Id": "cpu",
"Label": "CPUUtilization",
"Timestamps": [
"2025-0X-XXT18:30:00+00:00",
"2025-0X-XXT18:25:00+00:00"
],
"Values": [
88.05,
58.63008430846801
],
"StatusCode": "Complete"
}
],
"Messages": []
}
CPU가 과도하게 사용되지 않는지 확인합니다.
8.4. 노드 상태 확인
NAME STATUS ROLES AGE VERSION
ip-10-42-180-24.us-west-2.compute.internal Ready <none> 1h35m v1.30.8-eks-aeac579