쿠버네티스 클러스터에서 파드가 생성되지 않고, 계속해서 새로운 파드의 생성과 삭제를 반복하는 문제가 발생했습니다. 처음에는 단순한 리소스 부족으로 판단했지만, 실제로는 HPA(Horizontal Pod Autoscaler)와 etcd 간의 악순환이 원인이었습니다.
✏️ 이 글에서는 해당 장애의 원인과 트러블슈팅 과정을 기록합니다.
파드 스케줄링 실패
kubectl describe pod user-service-797cd76868-dbrph -n dev-user-service
출력 결과
Warning FailedScheduling 84s default-scheduler 0/5 nodes are available:
1 Insufficient memory, 1 node(s) had untolerated taint {node-role.kubernetes.io/control-plane: },
3 Insufficient cpu. preemption: 0/5 nodes are available:
1 Preemption is not helpful for scheduling, 4 No preemption victims found for incoming pod.
초기 판단
일부 노드는 메모리와 CPU가 부족하고, 컨트롤 플레인 노드는 테인트 설정으로 인해 스케줄링 대상에서 제외되었습니다. 해당 문제는 일반적인 리소스 부족 현상으로 보였습니다.
1) 노드별 리소스 확인
kubectl top nodes
출력 결과
NAME CPU(cores) CPU% MEMORY(bytes) MEMORY%
host-10-10-16-248 1448m 72% 2741Mi 71%
host-10-10-17-210 1752m 87% 2723Mi 71%
host-10-10-17-228 838m 41% 4069Mi 51%
host-10-10-17-253 346m 17% 4801Mi 61%
host-10-10-19-191 1457m 72% 4724Mi 60%
분석
컨트롤플레인 노드(host-10-10-17-210)의 CPU 사용률이 87%로 매우 높았습니다.
2) dev-user-service 파드 리소스 확인
kubectl top pods -n dev-user-service
출력 결과
NAME CPU(cores) MEMORY(bytes)
user-service-797cd76868-5xfqx 133m 110Mi
user-service-797cd76868-dbrph 8m 334Mi
user-service-797cd76868-hmddh 300m 284Mi
user-service-797cd76868-msr85 302m 291Mi
분석
일부 파드가 300m 이상의 CPU를 사용하며 비교적 높은 부하를 보이고 있었습니다. 전체적으로 워커 노드의 리소스는 여유가 있었지만, 스케줄링 실패가 반복된 주요 원인은 컨트롤 플레인 노드의 과도한 부하일 가능성이 높다고 판단했습니다.
모니터링 시스템이 많은 리소스를 쓰고 있어, 관련 컴포넌트들을 일시적으로 중지했습니다.
# 모니터링 스택 스케일 다운
kubectl get deployments -n dev-monitoring -o name | xargs -I {} kubectl scale {} --replicas=0 -n dev-monitoring
kubectl get statefulsets -n dev-monitoring -o name | xargs -I {} kubectl scale {} --replicas=0 -n dev-monitoring
# Falco 보안 모니터링 컴포넌트 중지
kubectl scale deployment -n falco-security --all --replicas=0
kubectl delete daemonset -n falco-security --all
리소스 사용량 확인
kubectl top nodes
출력 결과
NAME CPU(cores) CPU% MEMORY(bytes) MEMORY%
host-10-10-16-248 718m 35% 1655Mi 43%
host-10-10-17-210 1611m 80% 2636Mi 69%
host-10-10-17-228 1273m 63% 3874Mi 49%
host-10-10-17-253 282m 14% 4427Mi 56%
host-10-10-19-191 1086m 54% 4356Mi 55%
분석
모니터링 스택 제거 이후, 대부분의 워커 노드에서는 CPU 및 메모리 사용률이 눈에 띄게 감소했습니다. 하지만 컨트롤 플레인 노드(host-10-10-17-210)는 여전히 80% 이상의 CPU 사용률을 유지하고 있어, 근본적인 문제가 해결되지 않았음을 알 수 있었습니다.
리소스를 정리했음에도 불구하고 파드 스케줄링 문제는 계속되었습니다.
kubectl top nodes
출력 결과
NAME CPU(cores) CPU% MEMORY(bytes) MEMORY%
host-10-10-16-149 1641m 82% 1264Mi 33%
host-10-10-16-248 1541m 77% 1463Mi 38%
host-10-10-17-210 1823m 91% 2648Mi 69%
host-10-10-17-228 1578m 78% 3326Mi 42%
host-10-10-17-253 430m 21% 3672Mi 46%
host-10-10-19-191 910m 45% 3911Mi 49%
⚠️ 컨트롤 플레인 CPU 91% 도달
노드를 추가해도 근본적인 해결이 되지 않았고, 오히려 전체 클러스터의 대부분의 파드가 생성되지 않는 현상까지 발생했습니다.
1) API 서버 응답 확인
kubectl get nodes --v=6
출력 결과
I0609 14:46:07.575430 3110342 round_trippers.go:553] GET https://10.10.17.210:6443/api/v1/nodes?limit=500 200 OK in 17 milliseconds
분석
API 서버는 요청에 정상적으로 응답하고 있었으며, 응답 속도도 큰 문제가 없어 보였습니다.
2) 컨트롤 플레인 컴포넌트 상태 확인
kubectl get pods -n kube-system | grep -E "(api|controller|scheduler|etcd)"
출력 결과
etcd-host-10-10-17-210 1/1 Running 0 9d
kube-apiserver-host-10-10-17-210 1/1 Running 1 (6d7h ago) 9d
kube-controller-manager-host-10-10-17-210 1/1 Running 18 (13h ago) 9d
kube-scheduler-host-10-10-17-210 1/1 Running 17 (13h ago) 9d
분석
kube-controller-manager와 kube-scheduler가 각각 18회, 17회 재시작된 것이 확인되었습니다.
3) etcd 성능 확인
kubectl logs -n kube-system etcd-host-10-10-17-210 --tail=20
출력 결과
{"level":"warn","ts":"2025-06-09T14:45:03.529176Z","caller":"v3rpc/interceptor.go:197","msg":"request stats","start time":"2025-06-09T14:45:02.873387Z","time spent":"655.538204ms","remote":"127.0.0.1:57964","response type":"/etcdserverpb.KV/Txn"}
{"level":"warn","ts":"2025-06-09T14:45:19.523664Z","caller":"v3rpc/interceptor.go:197","msg":"request stats","start time":"2025-06-09T14:45:18.734664Z","time spent":"788.756718ms","remote":"127.0.0.1:36246","response type":"/etcdserverpb.KV/Txn"}
{"level":"warn","ts":"2025-06-09T14:45:53.506663Z","caller":"v3rpc/interceptor.go:197","msg":"request stats","start time":"2025-06-09T14:45:52.816751Z","time spent":"689.842973ms","remote":"127.0.0.1:36246","response type":"/etcdserverpb.KV/Txn"}
분석
정상적인 etcd 응답 시간은 100ms 이하가 이상적이지만, 현재는 요청마다 600~800ms의 지연이 발생하고 있었습니다.
etcd는 쿠버네티스의 중앙 데이터 저장소로, 클러스터 내 모든 오브젝트의 상태 정보(Pod, Service, ConfigMap 등)를 저장합니다. API 서버는 etcd를 통해 클러스터 상태를 조회하고 변경하기 때문에, etcd가 느려지면 컨트롤플레인을 포함한 전체 시스템의 응답성에 영향을 미치게 됩니다.
etcd 로그를 자세히 분석해보니, twp-service와 관련된 이벤트가 비정상적으로 폭증하고 있었고, 이것이 etcd 성능 저하의 직접적인 원인임을 발견했습니다.
1) 문제 서비스 식별
etcd 로그에는 아래와 같은 패턴이 반복적으로 나타났습니다.
"request content":"compare:<target:MOD key:\"/registry/events/dev-twp-service/twp-service-5649d66c74.18476710f9922751\""
"request content":"compare:<target:MOD key:\"/registry/services/endpoints/dev-twp-service/twp-service\""
"request content":"compare:<target:MOD key:\"/registry/endpointslices/dev-twp-service/twp-service-w6t2l\""
분석
twp-service가 지속적으로 etcd에 이벤트를 생성하고 있었고, 이로 인해 etcd가 과부하에 빠지고 있었습니다.
2) twp-service 상태 확인
kubectl get pods -n dev-twp-service
출력 결과
NAME READY STATUS RESTARTS AGE
dev-redis-lock-85f48688cc-zj62c 1/1 Running 0 5m11s
twp-service-5649d66c74-42fdp 1/1 Running 0 88s
twp-service-5649d66c74-4glxc 1/1 Running 0 5m11s
twp-service-5649d66c74-bwqkf 1/1 Running 0 89s
twp-service-5649d66c74-ztkfn 1/1 Running 0 5m11s
분석
파드 상태는 모두 Running이었지만, AGE를 보면 짧은 간격으로 반복 생성되고 있는 상황임을 확인할 수 있었습니다.
3) 이벤트 히스토리 확인
kubectl get events -n dev-twp-service --sort-by='.lastTimestamp' | tail -10
출력 결과
94s Normal SuccessfulDelete replicaset/twp-service-5649d66c74 Deleted pod: twp-service-5649d66c74-bl4px
92s Normal SuccessfulRescale horizontalpodautoscaler/twp-service-hpa New size: 4; reason: cpu resource utilization (percentage of request) above target
92s Normal ScalingReplicaSet deployment/twp-service Scaled up replica set twp-service-5649d66c74 to 4 from 2
89s Normal SuccessfulCreate replicaset/twp-service-5649d66c74 Created pod: twp-service-5649d66c74-42fdp
분석
이벤트 로그를 보면, 2~3초 간격으로 파드 삭제, HPA 스케일 업, 파드 생성 이벤트가 반복되고 있음을 확인할 수 있습니다.
즉, twp-service는 CPU 사용률이 HPA의 기준을 초과하면서 스케일 업 → 파드 생성 → 부하 집중 → 다시 스케일 업이라는 순환 구조에 빠져 있었고, 이로 인해 etcd에는 초당 수차례의 트랜잭션 요청이 쏟아지는 상황이 발생하고 있었습니다.
1) 초기 상황
클러스터 전반에 리소스 부족이 발생한 상태였습니다.
2) HPA 트리거 발생
twp-service의 CPU 사용률이 HPA의 target을 초과
→ HPA: CPU 사용률이 여전히 높다고 판단하고 스케일 업을 시도
3) 악순환 시작
하지만 실제로는 다음과 같은 메커니즘이 작동하고 있었습니다.
결국, 스케줄링 결정은 정상적으로 이루어졌지만 etcd의 반영 속도가 느려 HPA가 계속해서 중복 트리거되는 무한 루프에 빠졌습니다.
4) etcd 과부하
5) 전체 시스템 마비
HPA 확인 및 제거
kubectl get hpa -A
출력 결과
NAMESPACE NAME TARGETS MINPODS MAXPODS REPLICAS
dev-twp-service twp-service-hpa 85%/70% 2 10 4
dev-user-service user-service-hpa 45%/70% 2 8 3
분석
twp-service가 지속적으로 target(70%)을 초과하며 스케일 업을 반복 중이었고, 이로 인해 위의 악순환이 발생한 것이었습니다.
# HPA 제거
kubectl delete hpa twp-service-hpa -n dev-twp-service
kubectl delete hpa user-service-hpa -n dev-user-service
HPA를 제거한 뒤, 다시 노드 리소스 상태를 확인했습니다.
kubectl top nodes
출력 결과
NAME CPU(cores) CPU% MEMORY(bytes) MEMORY%
host-10-10-16-149 892m 44% 1156Mi 30%
host-10-10-16-248 1102m 55% 1344Mi 35%
host-10-10-17-210 1243m 62% 2145Mi 56%
host-10-10-17-228 1089m 54% 2987Mi 38%
host-10-10-17-253 278m 13% 3201Mi 41%
host-10-10-19-191 756m 37% 3456Mi 44%
🎉 컨트롤플레인 노드(host-10-10-17-210)의 CPU 사용률이 91% → 62%로 안정화되었고, 전체 클러스터의 부하도 눈에 띄게 감소했습니다.
etcd 로그 확인
kubectl logs -n kube-system etcd-host-10-10-17-210 --tail=10
“request took too long” 경고 메시지가 더 이상 나타나지 않으며, etcd 응답도 정상으로 회복된 것을 확인했습니다.
HPA는 편리한 자동 확장 도구지만, 클러스터 전체 리소스 상황을 고려하지 않은 설정은 오히려 장애를 유발할 수 있습니다. 특히, etcd와 같은 핵심 컴포넌트에 부하를 집중시키면, 클러스터 전체가 느려지거나 마비되는 결과를 초래할 수 있습니다.
이번 장애의 핵심은 워커 노드에는 리소스가 있었지만, etcd 병목으로 인해 스케줄링 프로세스 전체가 느려져서 HPA가 이를 인지하지 못하고 계속 스케일 업을 시도한 것이었습니다.
HPA 개선 방안
😶 이번 장애를 통해 쿠버네티스의 복잡한 상호작용과 etcd 성능의 중요성을 다시 한 번 깨달았습니다.