쿠버네티스 운영 실무 · etcd 백업과 복구 · 실습
삭제 사고를 스냅샷으로 되돌리기
목표
실제로 오브젝트를 지운 뒤 스냅샷에서 되살려 봅니다. 복구된 데이터 디렉터리로 두 번째 etcd 를 직접 띄워 "정말 돌아왔다"를 눈으로 확인합니다.
왜 중요한가
복구 절차를 문서로만 아는 것과 한 번 해 본 것의 차이는 큽니다. 특히 snapshot restore 가 데이터를 되돌리는 명령이 아니라 새 etcd 클러스터를 만드는 명령이라는 사실은 손으로 해 봐야 몸에 남습니다. 그래서 --name, --initial-cluster, --initial-advertise-peer-urls, --initial-cluster-token 같은 신원 플래그를 요구하고, --data-dir 로 비어 있는 새 경로를 요구합니다. 기존 /var/lib/etcd 를 그대로 주는 순간 살아 있는 데이터를 건드리게 됩니다. 또 하나 중요한 것이 순서입니다. 스냅샷을 먼저 검증하고, apiserver 를 멈춰 쓰기를 끊고, 복구하고, 매니페스트의 hostPath 를 새 경로로 바꾸고, 마지막에 kubectl 로 확인합니다. 이 순서를 뒤집으면 못 쓰는 스냅샷으로 클러스터를 세우거나, 복구 중에 들어온 쓰기를 잃거나, 옛 데이터로 다시 뜨는 일이 벌어집니다. 이 랩에서는 라이브 클러스터를 멈추지 않고 별도 포트에 복구본을 띄워 같은 결론에 도달합니다.
단계
1. 네임스페이스 etcd-lab 과 그 안의 ConfigMap etcd-lab-marker(data.owner=platform)를 만드세요. 그다음 /root/etcd/restore/out/pre.json 에 사고 전 상태를 JSON 으로 기록하세요. 키는 marker_owner(값 platform), registry_keys(/registry 아래 키 개수, 20 이상), revision(현재 etcd revision, 0보다 큼) 세 개입니다.
2. 복구에 쓸 스냅샷을 /root/etcd/restore/before.db 로 뜨고(20000 바이트 이상), 검증 결과를 JSON 으로 /root/etcd/restore/out/before.json 에 저장하세요. revision 이 0보다 커야 합니다.
3. ConfigMap etcd-lab-marker 를 삭제해 사고를 재현하세요. 삭제 후 그 오브젝트를 조회한 출력을 /root/etcd/restore/out/gone.txt 에 남기세요. 파일에 NotFound 또는 not found 같은 "없다"는 응답이 들어 있어야 하고, 라이브 클러스터에는 이 ConfigMap 이 다시 생기면 안 됩니다.
4. before.db 를 /root/etcd/restore/data 로 복구하세요. 복구 후 /root/etcd/restore/data/member/snap/db 와 /root/etcd/restore/data/member/wal 이 생겨야 합니다. 복구 명령의 출력(표준 오류 포함)을 /root/etcd/restore/out/restore.txt 에 저장하세요.
5. 이번에는 신원 플래그를 모두 붙여 /root/etcd/restore/data2 로 한 번 더 복구하세요. --data-dir, --name, --initial-cluster, --initial-advertise-peer-urls, --initial-cluster-token 다섯 플래그가 모두 들어가야 하며, 이름은 restored, 피어 주소는 http://127.0.0.1:12380, 토큰은 etcd-restore-lab 로 하세요. 실제로 실행한 명령 전체를 /root/etcd/restore/out/restore-cmd.txt 에 그대로 남기세요(--data-dir 에 /var/lib/etcd 를 적으면 안 됩니다).
6. /root/etcd/restore/data2 를 데이터 디렉터리로 하는 두 번째 etcd 프로세스를 백그라운드로 띄우세요. 클라이언트 주소는 http://127.0.0.1:12379, 피어 주소는 http://127.0.0.1:12380, 이름은 restored, 초기 멤버는 restored=http://127.0.0.1:12380, 토큰은 etcd-restore-lab 입니다. 채점이 끝날 때까지 이 프로세스를 종료하지 마세요. 기동에 쓴 명령을 /root/etcd/restore/out/second-etcd.txt 에 저장하세요(파일에 12379 와 --data-dir 이 보여야 합니다).
7. 복구본에서 /registry/configmaps/etcd-lab/etcd-lab-marker 키를 읽어 값에 platform 이 들어 있는지 확인하고, 그 출력을 /root/etcd/restore/out/recovered.txt 에 저장하세요. 조회 대상은 127.0.0.1:12379 이며, 라이브 클러스터(2379)에는 이 오브젝트가 여전히 없어야 합니다.
8. /root/etcd/restore/runbook.md 에 복구 런북을 400바이트 이상으로 쓰세요. 각 단계는 서로 다른 줄에 두고 아래 순서를 지켜야 합니다. (1) 스냅샷 검증(snapshot status), (2) kube-apiserver 중지, (3) snapshot restore, (4) etcd 매니페스트의 hostPath/data-dir 을 새 경로로 교체, (5) kubectl get 으로 확인. 마지막에 복구가 실패했을 때의 롤백 방법도 반드시 적으세요.
참고
- 스냅샷 검증과 복구는
etcdutl이 표준입니다.command -v etcdutl로 먼저 확인해 있으면etcdutl snapshot status/etcdutl snapshot restore를 쓰고, 없으면etcdctl의 같은 하위 명령으로 대체하세요(경고가 붙지만 동작합니다). - etcd 서버 실행 파일은 별개입니다.
command -v etcd로 먼저 찾고, 없으면find "$HOME/.kwok" -name etcd -type f로 찾으세요(kwokctl 이 내려받은 바이너리가 그 아래에 있습니다). 백그라운드 기동은nohup <etcd 경로> <플래그들> > /root/etcd/restore/out/second-etcd.log 2>&1 &형태가 편합니다. - 두 번째 etcd 의 포트를 라이브 etcd(2379/2380)와 겹치게 하면 기동에 실패합니다. 반드시 12379/12380 을 쓰고, 6·7번을 채점받을 때까지 프로세스를 살려 두세요.
- 복구 로그와
kubectl의 NotFound 메시지는 모두 표준 오류로 나갑니다.명령 > 파일 2>&1또는명령 2>&1 | tee 파일로 받아야 파일에 남습니다. - etcd 에 저장된 값은 protobuf 라 그대로 보면 깨져 보입니다.
| tr -d '\0'로 널 바이트만 걷어 내면 안에 든 문자열은 그대로 읽힙니다. - 흔한 실수 1: 8번 런북에서
etcdctl snapshot restore --data-dir ...을 한 줄에 쓰는 것. 그러면snapshot restore와data-dir이 같은 줄이 되어 순서 검사에 걸립니다. 여러 줄로 나누거나 hostPath 교체를 별도 항목으로 두세요. 같은 이유로 문서 앞부분에서data-dir,kubectl get,kube-apiserver를 미리 언급하지 마세요 — 각 단어의 첫 등장 위치로 순서를 판정합니다. - 흔한 실수 2: 3번에서 라이브 클러스터의 ConfigMap 을 다시 만들어 버리는 것. 이 실습의 결론은 "복구본에서만 되살아난다"입니다.
- 실습 파드는 실습마다 새로 뜨므로 앞 실습에서 만든
etcd-lab네임스페이스와 마커는 남아 있지 않습니다. 1번에서 직접 만들고 시작하세요. 운영 절차를 기억이 아니라 런북과 매니페스트로 남겨야 하는 이유가 바로 이것입니다.
단계 8개
- 사고 전 상태를 숫자로 기록하기
- 복구에 쓸 스냅샷 확보하고 검증하기
- 삭제 사고 재현하고 흔적 남기기
- 스냅샷을 새 데이터 디렉터리로 복구하기
- 클러스터 신원 플래그를 붙여 다시 복구하기
- 복구본으로 두 번째 etcd 띄우기
- 지워진 오브젝트가 복구본에 살아 있는지 확인하기
- 복구 런북 쓰기