백업 성공 ≠ 복구 가능
백업 잡이 초록불이어도 파일이 손상됐거나, 빠진 리소스가 있거나, 복구 절차를 아무도 모르는 경우가 흔하다. 확인하는 방법은 하나 — 해 보는 것.
“백업이 있다”와 “복구해 봤다”는 다른 말이다 — 이 장의 마지막 절이 제일 중요하다
RPORecovery Point ObjectiveRTORecovery Time Objectiveetcd 스냅샷VeleroKopia실패 도메인Failure DomainDRDisaster Recovery, 재해 복구“백업 돌고 있어요”라는 말은 대개 일부만 백업하고 있다는 뜻이다. 먼저 세어 본다.
| 잃을 수 있는 것 | 잃으면 | 무엇이 지키나 |
|---|---|---|
| 매니페스트·설정 | 무엇이 있었는지 모른다 | Git (9장) |
| etcd (오브젝트 전체) | 클러스터의 기억이 통째로 | etcd 스냅샷 |
| PV 데이터 | 앱이 쌓아 둔 파일 | Velero (+ CSI 스냅샷) |
| 데이터베이스 | 업무 데이터 | CNPG 백업 + WAL (7장) |
| 오브젝트 스토리지 | 로그·트레이스·백업 자체 | 복제 또는 오프사이트 (6장) |
| Sealed Secrets sealing key 세트 | Git의 모든 비밀을 영영 못 푼다 | 별도 금고 (10장) |
| 사내 CA 개인키 | 발급한 인증서 체계를 다시 세워야 | 별도 금고 (4장) |
| Keycloak realm 설정 | SSO를 처음부터 다시 | CNPG 백업 (DB가 원본) |
# 컨트롤 플레인 노드에서 (kubeadm 기준 경로)sudo ETCDCTL_API=3 etcdctl snapshot save /var/backups/etcd-$(date +%F-%H%M).db \ --endpoints=https://127.0.0.1:2379 \ --cacert=/etc/kubernetes/pki/etcd/ca.crt \ --cert=/etc/kubernetes/pki/etcd/server.crt \ --key=/etc/kubernetes/pki/etcd/server.key
# 확인 (여기서 에러가 나면 그 스냅샷은 못 쓴다)sudo etcdctl --write-out=table snapshot status /var/backups/etcd-*.db
# 노드 밖으로 즉시 옮긴다 — 노드에만 있으면 노드와 함께 죽는다mc cp /var/backups/etcd-*.db store/cluster-backups/etcd/apiVersion: velero.io/v1kind: Schedulemetadata: name: daily namespace: velerospec: schedule: "0 3 * * *" template: includedNamespaces: ["*"] excludedNamespaces: [kube-system, observability] # 재생성 가능한 것은 뺀다 defaultVolumesToFsBackup: true # CSI 스냅샷을 못 쓰면 파일 단위(Kopia)로 ttl: 720h # 30일 storageLocation: default # 6장의 오브젝트 스토리지| 방식 | 어떻게 | 언제 |
|---|---|---|
| CSI 스냅샷 | 스토리지가 순간 스냅샷을 뜬다. 빠르다 | 벤더 CSI가 지원할 때 |
| 파일 백업(Kopia) | 볼륨 내용을 읽어 오브젝트 스토리지로 | 스냅샷을 못 쓸 때. 느리지만 이식성이 좋다 |
지금까지의 백업은 전부 오브젝트 스토리지 하나에 모였다. 그 스토리지가 있는 랙이 타면 전부 사라진다.
| 방법 | 내용 |
|---|---|
| 버킷 복제 | 다른 사이트의 S3 호환 스토리지로 지속 복제 |
| 주기적 동기화 | mc mirror를 cron으로 — 단순하지만 확실하다 |
| 오프라인 매체 | 규정상 필요하면. 랜섬웨어 대비로는 이쪽이 확실하다 |
# 최소한 이 정도는 — 백업 버킷만이라도 다른 곳으로mc mirror --overwrite --remove store/cluster-backups dr/cluster-backupsmc mirror --overwrite store/pg-backups dr/pg-backups“백업합니다”가 아니라 숫자로 적어야 계획이 된다. 아래는 출발점으로 쓸 만한 값이다.
| 대상 | 백업 주기 | RPO | 복구 방법 | RTO 어림 |
|---|---|---|---|---|
| 매니페스트 | 커밋마다 | 0 | Argo CD 동기화 | 분 |
| etcd | 1일 + 작업 전 | 24시간 | 스냅샷 복구 (최후 수단) | 시간 |
| PostgreSQL | 베이스 1일 + WAL 연속 | 분 단위 | 새 Cluster로 PITR | 1~수 시간 (데이터 크기) |
| PV 데이터 | 1일 | 24시간 | Velero restore | 시간 |
| 오브젝트 스토리지 | 지속 복제 | 분~시간 | 복제본으로 전환 | 데이터 크기에 비례 |
| sealing key 세트·CA 키 | 변경·갱신 시마다 | 0 | 금고에서 복원 (10장) | 분 |
백업 성공 ≠ 복구 가능
백업 잡이 초록불이어도 파일이 손상됐거나, 빠진 리소스가 있거나, 복구 절차를 아무도 모르는 경우가 흔하다. 확인하는 방법은 하나 — 해 보는 것.
분기 1회 · 30분
전면 DR 훈련이 아니어도 된다. 새 네임스페이스에 DB 복구본 하나 띄우고 행 수를 세는 것만으로 대부분의 문제가 드러난다.
문서는 복구 중에 쓴다
평시에 쓴 절차서는 대체로 틀렸다. 리허설하면서 막힌 지점을 그대로 적은 것이 진짜 runbook이다.
사람 의존을 없앤다
“그건 ○○님만 압니다”가 있으면 그게 최대 위험이다. 리허설은 매번 다른 사람이 절차서만 보고 한다.
# ① DB — 백업에서 새 클러스터를 띄워 행 수를 센다 (7장의 복구 매니페스트)kubectl apply -f drill/platform-pg-restored.yamlkubectl cnpg status platform-pg-restored -n drillkubectl -n drill exec -it platform-pg-restored-1 -- \ psql -U postgres -d appdb -c "SELECT count(*) FROM orders;"
# ② Velero — 네임스페이스 하나를 다른 이름으로 복구velero restore create drill-$(date +%F) \ --from-backup daily-20260810030000 \ --include-namespaces prod --namespace-mappings prod:drill-prodvelero restore describe drill-$(date +%F) --details
# ③ 시크릿 — sealing key 세트로 실제 복호화가 되나 (백업본으로)kubeseal --recovery-unseal --recovery-private-key sealed-secrets-keys.yaml \ < observability/loki/sealedsecret-s3.yaml | head
# ④ etcd 스냅샷 — 파일이 온전한가etcdctl --write-out=table snapshot status /path/to/etcd-latest.db
# ⑤ 정리kubectl delete ns drill drill-prod| 리허설에서 자주 드러나는 것 | |
|---|---|
| WAL 보존이 짧아 원하는 시점으로 못 간다 | 7장 retentionPolicy |
| 복구본이 뜰 StorageClass·용량이 없다 | 여유 용량을 미리 확보 |
| sealing key 세트 백업이 3개월 전 것이다 | 키 갱신 후 백업을 안 했다 |
| Velero가 CRD를 복구하지 못한다 | 포함 규칙과 순서 확인 |
| 절차서의 명령이 옛 버전 것이다 | 리허설 중에 고친다 |
# 백업이 실제로 최근 것인가 — "성공 로그"가 아니라 산출물을 본다velero backup get | headmc ls store/pg-backups/platform-pg/base/ | tail -3mc ls store/cluster-backups/etcd/ | tail -3mc ls dr/cluster-backups/etcd/ | tail -3 # 오프사이트에도 갔나| 증상 | 흔한 원인 |
|---|---|
| 백업은 초록불인데 파일이 없다 | 스토리지 위치 설정이 다른 버킷을 본다 |
| PV가 백업 안 됨 | defaultVolumesToFsBackup 누락 · 노드 에이전트 미배포 |
| 복구했는데 앱이 안 뜬다 | Secret이 빠졌다 (시크릿을 별도 체계로 관리 중) |
| PITR이 원하는 시점 이전으로 안 간다 | WAL 보존 기간 |
| 복구가 너무 오래 걸린다 | 파일 백업의 한계 — CSI 스냅샷 지원 확인 |