1. 장애 개요
운영 중인 Kubernetes 클러스터에서 Harbor의 복제본(Replica)을 확장하려던 단순 작업이, StatefulSet의 제약 조건과 kubelet 설정 충돌로 인해 클러스터 전체의 제어 불능(Brain Split) 상태로 확산된 사고입니다. 본 문서는 장애의 발생 과정, 원인 분석, 그리고 OS 레벨의 초기화를 통한 복구 절차를 기술합니다.
2. 장애 발생 메커니즘 (Timeline)
Phase 1: Trigger (초기 오류)
- 작업:
helm upgrade를 통해 Harbor의 주요 컴포넌트(core,jobservice,registry)를 2-Replica로 확장 시도. - 실패:
Harbor-trivy가StatefulSet으로 배포되어 있어, 복제본 외의 스펙 변경이 불가능한 Immutability 제약 조건에 걸려 업그레이드 실패.
Phase 2: Escalation (문제 확산)
- 대응:
helm uninstall후 재설치를 감행했으나,Ingress컨트롤러와PVC간의 연결이 꼬이면서 외부 접속 불가 발생. - 리소스 증설: 파드 스케줄링 실패를 해결하고자 워커 노드 메모리를 6GB로 증설 후 재부팅했으나,
kubelet이NotReady상태에 빠지며 노드 통신 두절.
Phase 3: Disaster (클러스터 붕괴)
- 치명적 실수: 노드 복구를 위해
kubeadm reset -f를 실행하는 과정에서, Core Component(etcd,coredns,flannel)가 동시에 중단됨. - 결과: 클러스터의 '두뇌(API Server)'와 '혈관(CNI)'이 모두 끊기며, 파드들이 서로를 찾지 못하는 Deadlock 상태 진입.
3. 원인 분석 (Root Cause Analysis)
1) 아키텍처 이해 부족 (StatefulSet vs Deployment)
StatefulSet은 각 파드가 고유한 식별자와 볼륨을 가지므로,Deployment처럼 단순하게 복제본을 늘리거나 설정을 변경할 수 없음. 이 특성을 간과하고 강제 업그레이드를 시도한 것이 초기 원인.
2) Core Component의 상호 의존성 간과
etcd(상태 저장),CoreDNS(서비스 디스커버리),Flannel(네트워크 오버레이)은 서로 강하게 결합되어 있음.- 하나라도 비정상일 때 무리하게
reset을 수행하면, 남은 컴포넌트들이 좀비 프로세스(CrashLoopBackOff)가 되어 복구 불가능한 상태에 빠짐.
3) 오염된 노드 환경 (Dirty State)
kubeadm reset을 해도/etc/cni/net.d,/var/lib/kubelet등에 이전 설정 파일이 잔존하여, 재조인 시 설정 충돌(Config Conflict)을 유발함.
4. 복구 절차 (Disaster Recovery)
일반적인 방법으로 복구가 불가능하다고 판단, 노드 초기화(Factory Reset) 수준의 복구를 수행함.
Step 1: 잔존 데이터 완전 소거 (Clean-up)
단순 reset으로는 해결되지 않아, CNI 설정과 kubelet 데이터를 수동으로 삭제하여 '순정' 상태로 되돌림.
sudo kubeadm reset -f
sudo systemctl stop kubelet
# CNI 및 Kubelet 잔존 데이터 강제 삭제
sudo rm -rf /etc/cni/net.d
sudo rm -rf /var/lib/cni/
sudo rm -rf /var/lib/kubelet/*
sudo rm -rf /etc/kubernetes
sudo systemctl restart containerd
Step 2: 클러스터 재구축 (Re-join)
마스터 노드에서 새로운 토큰을 발급받아 워커 노드를 다시 조인시킴.
# Master
kubeadm token create --print-join-command
# Worker
sudo kubeadm join <Master-IP>:6443 --token <Token> ...
Step 3: 스토리지 레이어 복구
기존 PVC와 PV가 오염되었으므로, 로컬 패스 프로비저너의 실제 데이터 경로(/opt/local-path-provisioner/*)까지 정리 후 Harbor 재설치 수행.
5. 교훈 및 자산화 (Lessons Learned)
- StatefulSet 관리 원칙: 스케일링 시
pvc템플릿 수정 불가 등 제약 사항을 사전에 검토해야 함. - Disaster Recovery 절차 수립: 운영 중인 클러스터에서
reset은 최후의 수단이며, 수행 시 CNI 및 볼륨 데이터의 잔존 여부를 반드시 체크해야 함을 매뉴얼화함. - 의존성 파악:
CoreDNS가 죽으면 내부 서비스 도메인 리졸빙이 안 되어 다른 파드도 연쇄적으로 죽는다는 것을 경험적으로 체득함.
'인프라' 카테고리의 다른 글
| [Jenkins] Jenkins 빌드 머신 설정 하기 (0) | 2025.06.14 |
|---|---|
| [Jenkins] Helm으로 Jenkins 설치하기 (0) | 2025.06.13 |
| [Proxmox VE] QEMU Guest Agent 설치 및 활성화 (0) | 2025.06.09 |
| [K8s] Proxmox VE 위에 K8S 설정하기 (0) | 2025.06.01 |
| [K8S] 쿠버네티스 이해 하기 (0) | 2025.05.27 |