인프라

[K8S] 클러스터 붕괴 원인 분석 및 복구 과정

하루이2222 2025. 6. 13. 02:40

1. 장애 개요

운영 중인 Kubernetes 클러스터에서 Harbor의 복제본(Replica)을 확장하려던 단순 작업이, StatefulSet의 제약 조건과 kubelet 설정 충돌로 인해 클러스터 전체의 제어 불능(Brain Split) 상태로 확산된 사고입니다. 본 문서는 장애의 발생 과정, 원인 분석, 그리고 OS 레벨의 초기화를 통한 복구 절차를 기술합니다.


2. 장애 발생 메커니즘 (Timeline)

Phase 1: Trigger (초기 오류)

  • 작업: helm upgrade를 통해 Harbor의 주요 컴포넌트(core, jobservice, registry)를 2-Replica로 확장 시도.
  • 실패: Harbor-trivyStatefulSet으로 배포되어 있어, 복제본 외의 스펙 변경이 불가능한 Immutability 제약 조건에 걸려 업그레이드 실패.

Phase 2: Escalation (문제 확산)

  • 대응: helm uninstall 후 재설치를 감행했으나, Ingress 컨트롤러와 PVC 간의 연결이 꼬이면서 외부 접속 불가 발생.
  • 리소스 증설: 파드 스케줄링 실패를 해결하고자 워커 노드 메모리를 6GB로 증설 후 재부팅했으나, kubeletNotReady 상태에 빠지며 노드 통신 두절.

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: 스토리지 레이어 복구
기존 PVCPV가 오염되었으므로, 로컬 패스 프로비저너의 실제 데이터 경로(/opt/local-path-provisioner/*)까지 정리 후 Harbor 재설치 수행.


5. 교훈 및 자산화 (Lessons Learned)

  • StatefulSet 관리 원칙: 스케일링 시 pvc 템플릿 수정 불가 등 제약 사항을 사전에 검토해야 함.
  • Disaster Recovery 절차 수립: 운영 중인 클러스터에서 reset은 최후의 수단이며, 수행 시 CNI 및 볼륨 데이터의 잔존 여부를 반드시 체크해야 함을 매뉴얼화함.
  • 의존성 파악: CoreDNS가 죽으면 내부 서비스 도메인 리졸빙이 안 되어 다른 파드도 연쇄적으로 죽는다는 것을 경험적으로 체득함.