7.3 Recovery와 PITR
Recovery는 기존 물리 백업으로부터 인스턴스를 시작하는 과정이다. 여기서 CNPG의 중요한 성격 하나를 짚어야 한다. CNPG는 망가진 클러스터를 제자리에서 되살리는 in-place 복구를 하지 않는다. 대신 백업을 재료로 새 Cluster를 부트스트랩한다. 그래서 복구는 언제나 새 Cluster 리소스의 bootstrap.recovery로 표현된다.
flowchart TD
SRC["백업 소스"]
OS["object store"]
VS["volume snapshot"]
NEW["새 Cluster<br/>(bootstrap.recovery)"]
WAL["WAL 재생"]
TGT{"recovery target?"}
LATEST["최신까지 재생"]
PITR["지정 시점까지"]
SRC --> OS
SRC --> VS
OS --> NEW
VS --> NEW
NEW --> WAL
WAL --> TGT
TGT -->|없음| LATEST
TGT -->|있음| PITR
복구 소스 세 가지
새 Cluster의 bootstrap.recovery가 어디서 데이터를 가져오는지에 따라 세 방식이 있다.
- object store에서 복구: Barman Cloud Plugin과
ObjectStore로 오브젝트 스토리지의 백업을 읽는다. - volume snapshot에서 복구: Kubernetes 볼륨 스냅샷을 되살리고 WAL로 마무리한다.
- Backup 리소스에서 복구: 같은 namespace에 있는
Backup리소스를 이름으로 참조한다.
object store에서 복구
복구 소스가 될 ObjectStore를 정의하고, 새 Cluster가 externalClusters로 그것을 가리킨다.
apiVersion: barmancloud.cnpg.io/v1
kind: ObjectStore
metadata:
name: cluster-example-backup
spec:
configuration:
destinationPath: https://STORAGEACCOUNTNAME.blob.core.windows.net/CONTAINERNAME/
azureCredentials:
storageAccount:
name: recovery-object-store-secret
key: storage_account_name
storageKey:
name: recovery-object-store-secret
key: storage_account_key
wal:
maxParallel: 8apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
name: cluster-restore
spec:
superuserSecret:
name: superuser-secret
bootstrap:
recovery:
source: origin
externalClusters:
- name: origin
plugin:
name: barman-cloud.cloudnative-pg.io
parameters:
barmanObjectName: cluster-example-backup
serverName: cluster-examplebootstrap.recovery.source의 값(origin)이 externalClusters의 한 항목 이름과 맞아야 한다. serverName은 백업을 뜰 때 사용된 원본 클러스터 이름을 가리킨다.
wal.maxParallel은 아카이브에서 WAL을 동시에 몇 개까지 내려받을지를 정한다. 값을 키우면 WAL 재생이 빨라져 복구 시간이 줄어든다. 복구 노드의 네트워크·CPU 여유에 맞춰 조정한다.volume snapshot에서 복구
볼륨 스냅샷 이름을 bootstrap.recovery.volumeSnapshots에 지정한다. WAL이 별도 스토리지에 있으면 walStorage도 함께 준다.
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
name: cluster-restore
spec:
bootstrap:
recovery:
source: origin
volumeSnapshots:
storage:
name: <snapshot name>
kind: VolumeSnapshot
apiGroup: snapshot.storage.k8s.io
externalClusters:
- name: origin
plugin:
name: barman-cloud.cloudnative-pg.io
parameters:
barmanObjectName: cluster-example-backup
serverName: cluster-exampleBackup 리소스에서 복구
같은 namespace에 Backup 리소스가 있으면 이름으로 바로 참조한다.
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
name: cluster-example-initdb
spec:
instances: 3
bootstrap:
recovery:
backup:
name: backup-example
storage:
size: 1GiPoint-in-Time Recovery(PITR)
PITR는 base backup을 복원한 뒤 WAL을 원하는 시점까지만 재생해 멈추는 복구다. 유효한 WAL archive(7.2)가 있어야 한다. recovery target을 지정하면 Operator가 필요한 복구 파라미터를 자동으로 생성한다.
아래는 특정 시각까지 되돌리는 예다. recoveryTarget.targetTime을 준 것 외에는 object store 복구와 같다.
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
name: cluster-restore-pitr
spec:
instances: 3
storage:
size: 5Gi
bootstrap:
recovery:
source: origin
recoveryTarget:
targetTime: "2023-08-11 11:14:21.00000+02"
externalClusters:
- name: origin
plugin:
name: barman-cloud.cloudnative-pg.io
parameters:
barmanObjectName: cluster-example-backup
serverName: cluster-example실수로 실행한 DROP TABLE 직전으로 되돌리는 상황이 PITR의 대표적 쓰임새다.
recovery target 옵션
멈출 지점은 다음 중 하나로 지정한다.
| target | 의미 |
|---|---|
targetTime | 되돌릴 시각. RFC 3339 형식 또는 타임스탬프 |
targetXID | 멈출 트랜잭션 ID |
targetName | pg_create_restore_point()로 만든 명명 복원 지점 |
targetLSN | 멈출 WAL 로그 위치(LSN) |
targetImmediate | 일관된 상태에 도달하는 즉시 멈춤 |
targetName·targetXID·targetImmediate를 쓸 때는 backupID를 함께 지정해야 한다. 반면 targetTime·targetLSN은 Operator가 가장 가까운 백업을 자동으로 찾아 준다.targetName으로 명명 복원 지점까지 되돌리는 예는 다음과 같다.
bootstrap:
recovery:
source: origin
recoveryTarget:
backupID: 20220616T142236
targetName: 'restore_point_1'복구 후 애플리케이션 DB 설정
복구가 끝난 뒤 만들 데이터베이스·소유자·자격 증명을 함께 선언할 수 있다.
bootstrap:
recovery:
database: app
owner: app
secret:
name: app-secret복구가 완료되면 Operator는 데이터베이스가 없으면 만들고, 사용자가 없으면 만들고, 소유권을 부여한 뒤 secret에서 비밀번호를 갱신한다.
운영 시 주의점
- 복구는 base backup에
barman-cloud-restore, WAL에barman-cloud-wal-restore를 사용하며, init container가 이 과정을 투명하게 처리한다. - snapshot 복구 후 replica를 만들 때 Operator가
pg_basebackup으로 폴백할 수 있는데, 대용량 DB에서는 느리다. 스냅샷 복구는 단일 인스턴스 클러스터로 시작한 뒤 스케일업하는 것이 안전하다. - 공유 스토리지 버킷의 기존 데이터를 덮어쓰지 않도록 안전 점검이 걸려 있다. 충돌하면 클러스터가 setup 상태에 머물고 Pod가 에러를 낸다.
cnpg.io/skipEmptyWalArchiveCheck: enabled 어노테이션은 기존 백업을 덮어쓸 수 있어 극히 신중하게만 사용한다. 잘못 쓰면 복구 재료 자체를 잃는다.정리
- CNPG 복구는 in-place가 아니라 새 Cluster의
bootstrap.recovery로 부트스트랩한다. - 소스는 object store·volume snapshot·Backup 리소스 세 가지다.
- PITR는 base backup + WAL archive로 원하는 시점까지 재생해 멈춘다. target은 time·XID·name·LSN·immediate 중 하나.
targetName·targetXID·targetImmediate는backupID가 필요하고,targetTime·targetLSN은 자동으로 백업을 찾는다.- 스냅샷 복구는 단일 인스턴스로 시작 후 스케일업, 안전 점검 우회 어노테이션은 최후의 수단.
이것으로 백업(7.1)·WAL archiving(7.2)·복구(7.3)가 하나의 continuous backup 사이클로 이어진다.