
마침내 스프링 쿨러를 설치하다.
쿠버네티스를 마스터노드 3대로 구성하고
가용성에 대비하였다고 안심하였습니다.
마치 예전에는 소화기를 비치해 두고 불 끄기를 준비하고 있던 상태라면
지금은 설비를 갖춰 불이 나면 자동으로 감지하고 스프링 쿨러를 작동할 수 있도록 자동화를 갖춘 느낌이었습니다.
3대 중 한대든 두대든 죽으면 마스터 노드가 한대라도 살아있으니
자동으로 pod를 스케쥴링하겠지.
극단적으로 2대까지 서버를 죽이진 않았지만
한대를 죽였을 때도 복구되는 걸 확인하면서 안심하였습니다.
하지만 실무에서는 달랐습니다.
생각지 못한 순간에 화재 발생
오전 8시 29분 평소와 다름없는 출근길
갑자기 다량의 알림이 쏟아졌습니다.
"node connect fail"
"node conditions not in ready state"
"pod is crash looping"
.
.
.
출근길 꽉 찬 인파 속에서 정신은 혼란스럽고 당황하여 아무것도 할 수 없었습니다.
'침착하자 곧 복구되겠지'
손에 들고 있던 태블릿으로 서비스를 점검한 지 1분, 2분이 지나도 서비스 복구가 진행되지 않았습니다.
'큰일이다, 택시를 잡아야 하나?'
장애가 발생한 지 약 5분 정도 흐른 후
다시 다수의 알림과 함께 서비스가 자동 복구 되었음을 확인했습니다.
지하철에 꼼짝없이 갇혀 식은땀을 흘리며 안도의 한숨을 내쉬웠습니다.
'그럼 그렇지'
천국과 지옥을 오가는 출근길이 더욱 길게만 느껴졌습니다.
'원인이 무엇일까? 오전에 돌아가는 정기 작업인가?'
'혹시 네트워크 순단은 아닐까?'
'어제 배포했던 서비스가 문제였나?'
수많은 원인을 떠올리면서 동시에, 복구는 왜 이리 늦었을까 의문이 생겼습니다.
사무실에 뛰어 들어가 오전 내내 메트릭 지표를 분석한 결과
특정 작업이나, 네트워크 부하등은 특이사항이 없었습니다.
원인은 다음과 같았습니다.
cluster-node-2의 네트워크가 순간적으로 단절이 되었고, 이로 인해 약 3분 정도 응답이 없었기 때문이었습니다.
Aug 22 08:28:34 cluster-node-2 ntpd[3182610]: Soliciting pool server 2620:2d:4000:1::41
Aug 22 08:28:56 cluster-node-2 rke2[2495865]: time="2025-08-22T08:28:54+09:00" level=error msg="Failed to check local etcd status for learner management: context deadline exceeded"
Aug 22 08:29:18 cluster-node-2 rke2[2495865]: time="2025-08-22T08:29:14+09:00" level=info msg="error in remotedialer server [400]: websocket: close 1006 (abnormal closure): unexpected EOF"
Aug 22 08:29:31 cluster-node-2 rke2[2495865]: time="2025-08-22T08:29:14+09:00" level=info msg="error in remotedialer server [400]: websocket: close 1006 (abnormal closure): unexpected EOF"
Aug 22 08:29:48 cluster-node-2 rke2[2495865]: time="2025-08-22T08:29:37+09:00" level=warning msg="[108] encountered error \"i/o timeout\" while writing error \"EOF\" to close remotedialer"
Aug 22 08:29:50 cluster-node-2 ntpd[3182610]: error resolving pool ntp.ubuntu.com: Temporary failure in name resolution (-3)
Aug 22 08:30:21 cluster-node-2 rke2[2495865]: time="2025-08-22T08:30:02+09:00" level=warning msg="[108] encountered error \"i/o timeout\" while writing error \"writeto tcp 127.0.0.1:34244->127.0.0.1:10250: read tcp 127.0.0.1:34244->127.0>
Aug 22 08:30:21 cluster-node-2 rke2[2495865]: time="2025-08-22T08:30:03+09:00" level=error msg="Failed to check local etcd status for learner management: context deadline exceeded"
Aug 22 08:31:02 cluster-node-2 rke2[2495865]: time="2025-08-22T08:30:48+09:00" level=error msg="Failed to check local etcd status for learner management: context deadline exceeded"
Aug 22 08:31:02 cluster-node-2 rke2[2495865]: time="2025-08-22T08:31:00+09:00" level=warning msg="[138] encountered error \"i/o timeout\" while writing error \"writeto tcp 127.0.0.1:54124->127.0.0.1:10250: read tcp 127.0.0.1:54124->127.0>
서비스 단절이 1분도 작지 않은 시간인데 5분 이후 복구 된 것은
불이 난 이후 1분 안에 스프링클러가 동작한 게 아니라 5분 정도 태운 후에 작동한 것으로 생각하니 심각하게 느껴졌습니다.
Taint based Evictions
https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/
Kubernetes v1.18 버전에 도입된 Taint based Evictions을 통해 노드의 네트워크 단절 또는 노드 상태가 not Ready 인 경우
해당 노드에 pod를 축출할 수 있는 기능을 넣었다고 합니다.
기본 값은 다음과 같습니다.
tolerations:
- effect: NoExecute
key: node.kubernetes.io/not-ready
operator: Exists
tolerationSeconds: 300
- effect: NoExecute
key: node.kubernetes.io/unreachable
operator: Exists
tolerationSeconds: 300
위의 내용은 pod 생성 시 kube-apiserver를 통해 기본 값으로 반영됩니다.
아래의 링크를 통해 default-not-ready-toleration-seconds, default-not-ready-toleration-seconds을 수정하면 이후 생성되는 pod의 기본 값을 변경할 수 있습니다.
https://kubernetes.io/docs/reference/command-line-tools-reference/kube-apiserver/
결과적으로 5분이 지나도록 쿠버네티스에서는 아무런 조치 없이 네트워크 연결이 끊어진 노드의 연결이 복구되길 기다렸고,
장애는 지속될 수밖에 없었습니다.
마치며

쿠버네티스를 통해 실무를 하면 할수록 이게 왜 이렇게 동작하는지 모르고 기본 설정에 따라 진행하는 경우가 많은 것 같습니다.
기능은 구현이 되어있지만 사용의 책임은 오롯이 사용자가 진다는 것을 통감하며 오늘도 눈물 흘리며 저의 부족함을 느끼고 반성합니다.
다음번엔 스프링 쿨러가 완벽하게 작동하길 바라며 회고를 마칩니다.
'회고' 카테고리의 다른 글
| 명명 규칙을 바꾸다 Kubernetes 내부 동작을 이해하게 된 이야기 (0) | 2026.02.22 |
|---|---|
| 쿠버네티스 워크로드 CronJob 작성시 유의할 점 - 기초가 중요한 이유 (0) | 2025.10.11 |
| DevOps가 될 수 없어서, 개발자로 입사해 직접 DevOps 환경을 구축하다. (0) | 2025.08.04 |