# 05. etcd 복구 절차 ## 복구 시나리오 분류 | 상황 | 방법 | |------|------| | 단일 노드 장애 (데이터 intact) | etcd 재시작으로 자동 동기화 | | 단일 노드 장애 (데이터 손상) | 멤버 제거 → 재추가 | | 과반수 장애 (데이터 intact) | 모든 노드 재시작 | | 전체 장애 / 데이터 손상 | 스냅샷으로 복구 | --- ## 복구 1: 단일 노드 자동 재동기화 etcd 데이터가 살아있고 단순히 프로세스가 죽은 경우입니다. ```bash # ctrl3 재시작 ssh k8s-ctrl3 "sudo systemctl start etcd" # Raft 로그 동기화 확인 (수 초 ~ 수십 초) ssh k8s-ctrl3 "sudo journalctl -u etcd -f | grep -E 'synced|leader'" # 멤버 상태 확인 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 status -w table" ``` --- ## 복구 2: 스냅샷 백업 → 복구 ### 스냅샷 생성 (정상 상태에서) ```bash ssh k8s-ctrl1 "sudo ETCDCTL_API=3 etcdctl \ --endpoints=https://127.0.0.1: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 \ snapshot save /tmp/etcd-snapshot-$(date +%Y%m%d-%H%M%S).db" # 스냅샷 검증 ssh k8s-ctrl1 "sudo ETCDCTL_API=3 etcdctl snapshot status /tmp/etcd-snapshot-*.db -w table" ``` ### 전체 클러스터 스냅샷 복구 절차 > 이 절차는 etcd 데이터가 완전히 유실된 극단적 상황에서 사용합니다. > 모든 노드에서 동시에 진행해야 합니다. #### Step 1: 모든 etcd + kube-apiserver 정지 ```bash for node in k8s-ctrl1 k8s-ctrl2 k8s-ctrl3; do ssh $node "sudo systemctl stop etcd kube-apiserver" done ``` #### Step 2: 기존 etcd 데이터 백업 (혹시 모를 상황 대비) ```bash for node in k8s-ctrl1 k8s-ctrl2 k8s-ctrl3; do ssh $node "sudo mv /var/lib/etcd /var/lib/etcd.bak.$(date +%s)" done ``` #### Step 3: 각 노드에 스냅샷 복사 후 복구 ```bash SNAPSHOT="/tmp/etcd-snapshot-20240101-120000.db" # ctrl1 복구 ssh k8s-ctrl1 "sudo ETCDCTL_API=3 etcdctl snapshot restore ${SNAPSHOT} \ --name=k8s-ctrl1 \ --initial-cluster=k8s-ctrl1=https://203.0.113.11:2380,k8s-ctrl2=https://203.0.113.12:2380,k8s-ctrl3=https://203.0.113.13:2380 \ --initial-advertise-peer-urls=https://203.0.113.11:2380 \ --data-dir=/var/lib/etcd" # ctrl2 복구 ssh k8s-ctrl2 "sudo ETCDCTL_API=3 etcdctl snapshot restore ${SNAPSHOT} \ --name=k8s-ctrl2 \ --initial-cluster=k8s-ctrl1=https://203.0.113.11:2380,k8s-ctrl2=https://203.0.113.12:2380,k8s-ctrl3=https://203.0.113.13:2380 \ --initial-advertise-peer-urls=https://203.0.113.12:2380 \ --data-dir=/var/lib/etcd" # ctrl3 복구 ssh k8s-ctrl3 "sudo ETCDCTL_API=3 etcdctl snapshot restore ${SNAPSHOT} \ --name=k8s-ctrl3 \ --initial-cluster=k8s-ctrl1=https://203.0.113.11:2380,k8s-ctrl2=https://203.0.113.12:2380,k8s-ctrl3=https://203.0.113.13:2380 \ --initial-advertise-peer-urls=https://203.0.113.13:2380 \ --data-dir=/var/lib/etcd" ``` #### Step 4: etcd 재시작 ```bash for node in k8s-ctrl1 k8s-ctrl2 k8s-ctrl3; do ssh $node "sudo systemctl start etcd" done # 클러스터 상태 확인 sleep 10 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" ``` #### Step 5: kube-apiserver 재시작 ```bash for node in k8s-ctrl1 k8s-ctrl2 k8s-ctrl3; do ssh $node "sudo systemctl start kube-apiserver" done kubectl get nodes ``` --- ## 복구 3: virsh 스냅샷으로 VM 롤백 (빠른 리셋) 실험이 잘못됐을 때 VM 레벨에서 롤백하는 방법입니다. ```bash # 실험 전 스냅샷 생성 (항상 먼저 찍어두기) for i in 1 2 3; do virsh snapshot-create-as k8s-ctrl${i} \ "pre-experiment-$(date +%Y%m%d)" \ "실험 전 안전 스냅샷" done # 스냅샷 목록 확인 virsh snapshot-list k8s-ctrl1 # 스냅샷으로 롤백 (VM 실행 중에도 가능) for i in 1 2 3; do virsh snapshot-revert k8s-ctrl${i} "pre-experiment-20240101" done # 롤백 후 VM 시작 for i in 1 2 3; do virsh start k8s-ctrl${i} done ``` --- ## 복구 후 K8s 상태 검증 체크리스트 ```bash # 1. 노드 Ready 상태 확인 kubectl get nodes # 2. 시스템 파드 정상 여부 kubectl get pods -n kube-system # 3. etcd 멤버 동기화 확인 ssh k8s-ctrl1 "etcdctl member list -w table" ssh k8s-ctrl1 "etcdctl endpoint status -w table" # 4. 간단한 워크로드 배포 테스트 kubectl create deployment verify-nginx --image=nginx --replicas=3 kubectl get pods -l app=verify-nginx kubectl delete deployment verify-nginx # 5. PVC 테스트 (있는 경우) kubectl get pv,pvc -A ```