homelab89 Docs Logs Legacy Files ☰ TOC 🌓
guidek8s 2026-06-29etcdraftquorumfailure-testing

04. etcd 장애 실험 시나리오

etcd Raft 쿼럼 기본 원리

3-node etcd 클러스터:
  - 쿼럼(과반수) = 2
  - 1개 장애: 쿼럼 유지 (2/3 살아있음) → 클러스터 정상 운영
  - 2개 장애: 쿼럼 붕괴 (1/3만 살아있음) → 클러스터 읽기 전용 / 쓰기 불가
  - 3개 장애: 완전 다운

  장애 허용 공식: floor((n-1)/2)
  3노드: floor((3-1)/2) = 1개까지 허용

실험 전 준비

export KUBECONFIG=~/.kube/k8s-etcd-lab.conf

# 실험 전 etcd 상태 베이스라인 기록
kubectl get nodes
kubectl get pods -n kube-system

# etcd 헬스체크 (ctrl1에서)
ssh k8s-ctrl1 "sudo ETCDCTL_API=3 etcdctl \
  --endpoints=https://203.0.113.11:2379,https://203.0.113.12:2379,https://203.0.113.13:2379 \
  --cacert=/etc/ssl/etcd/ssl/ca.pem \
  --cert=/etc/ssl/etcd/ssl/member-k8s-ctrl1.pem \
  --key=/etc/ssl/etcd/ssl/member-k8s-ctrl1-key.pem \
  endpoint health -w table"

시나리오 1: 단일 노드 장애 (쿼럼 유지)

목표: etcd 노드 1개 정지 후 클러스터 운영 영향 확인

장애 주입

# ctrl3의 etcd 서비스 정지
ssh k8s-ctrl3 "sudo systemctl stop etcd"

# 또는 virsh로 VM 자체를 강제 종료 (더 극단적)
virsh destroy k8s-ctrl3

관찰 포인트

# 1. etcd 클러스터 상태 - ctrl1에서 확인
ssh k8s-ctrl1 "sudo ETCDCTL_API=3 etcdctl \
  --endpoints=https://203.0.113.11:2379,https://203.0.113.12:2379 \
  --cacert=/etc/ssl/etcd/ssl/ca.pem \
  --cert=/etc/ssl/etcd/ssl/member-k8s-ctrl1.pem \
  --key=/etc/ssl/etcd/ssl/member-k8s-ctrl1-key.pem \
  endpoint health"
# → ctrl3은 unreachable, ctrl1+ctrl2는 healthy

# 2. K8s 클러스터 - 여전히 정상 동작해야 함
kubectl get nodes
kubectl create deployment test-nginx --image=nginx
kubectl get pods

# 3. API Server 로그에서 etcd 연결 오류 확인
ssh k8s-ctrl1 "sudo journalctl -u kube-apiserver -n 50 | grep etcd"

복구

# etcd 서비스 재시작
ssh k8s-ctrl3 "sudo systemctl start etcd"
# 또는 VM 재시작
virsh start k8s-ctrl3

# 멤버 재합류 확인 (자동 재합류됨)
ssh k8s-ctrl1 "sudo ETCDCTL_API=3 etcdctl \
  --endpoints=https://203.0.113.11:2379 \
  --cacert=/etc/ssl/etcd/ssl/ca.pem \
  --cert=/etc/ssl/etcd/ssl/member-k8s-ctrl1.pem \
  --key=/etc/ssl/etcd/ssl/member-k8s-ctrl1-key.pem \
  member list"

시나리오 2: 과반수 장애 (쿼럼 붕괴)

목표: etcd 노드 2개 정지 후 K8s 클러스터가 어떻게 반응하는지 관찰

주의: 이 상태에서는 kubectl 명령이 타임아웃됩니다.

장애 주입

# ctrl2, ctrl3 동시 정지
virsh destroy k8s-ctrl2
virsh destroy k8s-ctrl3

관찰 포인트

# 1. kubectl 응답 불가 확인
kubectl get nodes --request-timeout=10s
# → 타임아웃 또는 etcd connection refused

# 2. API Server 에러 로그
ssh k8s-ctrl1 "sudo journalctl -u kube-apiserver -f"
# → "etcdserver: request timed out"

# 3. etcd 자체 상태 (ctrl1에서)
ssh k8s-ctrl1 "sudo systemctl status etcd"
# → active이지만 리더 없음, no quorum

# 4. etcd 내부 로그로 Raft 메시지 확인
ssh k8s-ctrl1 "sudo journalctl -u etcd -n 100 | grep -E 'raft|leader|quorum'"

# 5. 기존에 실행 중인 파드는 유지됨 확인 (etcd 없어도 kubelet은 동작)
ssh k8s-ctrl1 "sudo crictl ps"

복구

virsh start k8s-ctrl2
virsh start k8s-ctrl3
# etcd 자동 Raft 재동기화 후 쿼럼 복구됨

# 쿼럼 복구 확인
ssh k8s-ctrl1 "sudo ETCDCTL_API=3 etcdctl \
  --endpoints=https://203.0.113.11:2379 \
  --cacert=/etc/ssl/etcd/ssl/ca.pem \
  --cert=/etc/ssl/etcd/ssl/member-k8s-ctrl1.pem \
  --key=/etc/ssl/etcd/ssl/member-k8s-ctrl1-key.pem \
  endpoint health"

kubectl get nodes

시나리오 3: etcd 데이터 디렉토리 손상

목표: 특정 노드의 etcd 데이터가 손상됐을 때 멤버 제거 후 재추가

# ctrl3의 etcd 정지 후 데이터 삭제 (손상 시뮬레이션)
ssh k8s-ctrl3 "sudo systemctl stop etcd"
ssh k8s-ctrl3 "sudo rm -rf /var/lib/etcd/member"

# ctrl1에서 ctrl3 멤버 제거
ssh k8s-ctrl1 "sudo ETCDCTL_API=3 etcdctl \
  --endpoints=https://203.0.113.11:2379 \
  --cacert=/etc/ssl/etcd/ssl/ca.pem \
  --cert=/etc/ssl/etcd/ssl/member-k8s-ctrl1.pem \
  --key=/etc/ssl/etcd/ssl/member-k8s-ctrl1-key.pem \
  member remove <ctrl3-member-id>"

# ctrl3을 새 멤버로 추가
ssh k8s-ctrl1 "sudo ETCDCTL_API=3 etcdctl \
  --endpoints=https://203.0.113.11:2379 \
  --cacert=/etc/ssl/etcd/ssl/ca.pem \
  --cert=/etc/ssl/etcd/ssl/member-k8s-ctrl1.pem \
  --key=/etc/ssl/etcd/ssl/member-k8s-ctrl1-key.pem \
  member add k8s-ctrl3 --peer-urls=https://203.0.113.13:2380"

# ctrl3에서 etcd를 새 멤버로 재시작 (initial-cluster-state=existing)
# → experiments/04-restore-from-snapshot.sh 참조

관찰 도구 정리

도구 용도
etcdctl endpoint health 각 멤버 헬스
etcdctl endpoint status 리더·commit index 확인
etcdctl member list 멤버 목록
journalctl -u etcd -f etcd Raft 로그 실시간
journalctl -u kube-apiserver API Server etcd 연결 상태
kubectl get events -A 클러스터 레벨 이벤트
crictl ps kubelet 로컬 컨테이너 (etcd 없어도 동작)

etcd 주요 메트릭 (Prometheus)

# etcd 메트릭 엔드포인트
curl -sk https://203.0.113.11:2381/metrics | grep -E "etcd_server_leader|etcd_server_proposals"

# 주요 메트릭
# etcd_server_leader_changes_seen_total    → 리더 변경 횟수
# etcd_server_proposals_failed_total       → 쿼럼 실패 횟수
# etcd_server_has_leader                   → 리더 존재 여부 (0/1)
# etcd_disk_wal_fsync_duration_seconds     → 디스크 성능

Files