LabHub
배우기 러닝패스 코스

Kubernetes Operations

Undoing a Deletion Incident With a Snapshot

LabHub 에서 이어서 보기

한국어 원문으로 표시합니다.

목표

실제로 오브젝트를 지운 뒤 스냅샷에서 되살려 봅니다. 복구된 데이터 디렉터리로 두 번째 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 으로 확인. 마지막에 복구가 실패했을 때의 롤백 방법도 반드시 적으세요.

참고

사고 전 상태를 숫자로 기록하기

네임스페이스 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보다 큼) 세 개입니다.

복구는 '무엇이 있었는지'를 아는 데서 시작합니다. 마커 값, /registry 키 개수, 현재 revision 세 가지를 JSON 하나로 묶으세요. revision 은 endpoint status 의 헤더에 있습니다.

복구에 쓸 스냅샷 확보하고 검증하기

복구에 쓸 스냅샷을 /root/etcd/restore/before.db 로 뜨고(20000 바이트 이상), 검증 결과를 JSON 으로 /root/etcd/restore/out/before.json 에 저장하세요. revision 이 0보다 커야 합니다.

복구용 스냅샷은 뜨자마자 검증합니다. 사고가 난 다음에 파일이 깨졌다는 사실을 알면 이미 늦습니다.

삭제 사고 재현하고 흔적 남기기

ConfigMap etcd-lab-marker 를 삭제해 사고를 재현하세요. 삭제 후 그 오브젝트를 조회한 출력을 /root/etcd/restore/out/gone.txt 에 남기세요. 파일에 NotFound 또는 not found 같은 "없다"는 응답이 들어 있어야 하고, 라이브 클러스터에는 이 ConfigMap 이 다시 생기면 안 됩니다.

오브젝트를 지우고 조회해 보세요. 없는 리소스 조회는 표준 오류로 메시지가 나가므로 리다이렉션에 표준 오류를 함께 넣어야 파일에 남습니다.

스냅샷을 새 데이터 디렉터리로 복구하기

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 에 저장하세요.

복구는 기존 경로를 덮는 것이 아니라 새 경로를 만드는 일입니다. 복구 로그도 표준 오류로 나갑니다. 결과 디렉터리 안에 member 구조가 생겼는지 보세요.

클러스터 신원 플래그를 붙여 다시 복구하기

이번에는 신원 플래그를 모두 붙여 /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 를 적으면 안 됩니다).

restore 는 사실 '새 클러스터를 하나 만드는' 명령입니다. 이름, 초기 멤버 목록, 피어 주소, 토큰 네 가지를 명시하면 뒤이어 그 데이터로 etcd 를 띄울 수 있습니다.

복구본으로 두 번째 etcd 띄우기

/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 이 보여야 합니다).

복구한 데이터 디렉터리를 실제 프로세스에 물려야 확인이 됩니다. 클라이언트·피어 포트를 라이브 etcd 와 겹치지 않게 하고, 채점이 끝날 때까지 프로세스를 살려 두세요.

지워진 오브젝트가 복구본에 살아 있는지 확인하기

복구본에서 /registry/configmaps/etcd-lab/etcd-lab-marker 키를 읽어 값에 platform 이 들어 있는지 확인하고, 그 출력을 /root/etcd/restore/out/recovered.txt 에 저장하세요. 조회 대상은 127.0.0.1:12379 이며, 라이브 클러스터(2379)에는 이 오브젝트가 여전히 없어야 합니다.

쿠버네티스 오브젝트의 etcd 키는 /registry/<종류>/<네임스페이스>/<이름> 입니다. 값은 protobuf 라 사람이 읽기 어렵지만 문자열은 그대로 보입니다.

복구 런북 쓰기

/root/etcd/restore/runbook.md 에 복구 런북을 400바이트 이상으로 쓰세요. 각 단계는 서로 다른 줄에 두고 아래 순서를 지켜야 합니다. (1) 스냅샷 검증(snapshot status), (2) kube-apiserver 중지, (3) snapshot restore, (4) etcd 매니페스트의 hostPath/data-dir 을 새 경로로 교체, (5) kubectl get 으로 확인. 마지막에 복구가 실패했을 때의 롤백 방법도 반드시 적으세요.

새벽 3시에 읽을 문서입니다. 단계 순서가 중요하고, 실패했을 때 어디로 돌아갈지도 적어야 합니다.