부록 B - 오브젝트 스토어 백업(Backup on object stores)
CloudNativePG는 오브젝트 스토어에 연속 물리적 백업과 WAL 아카이빙을 통해 PostgreSQL 클러스터의 온라인/핫 백업을 네이티브로 지원해요. Barman Cloud 기반 설정 방법과 보존 정책, 압축 알고리즘, 복구 방법을 살펴볼게요.
출처: 문서
본문
:::warning CloudNativePG 1.26부터 네이티브 Barman Cloud 지원은 더 이상 사용되지 않으며(deprecated), Barman Cloud Plugin이 이를 대신해요. 이 페이지는 참고용으로 부록으로 이동됐어요. 네이티브 통합은 당분간 기능하지만, 적절한 테스트 후 플러그인 기반 인터페이스로 점진적 마이그레이션을 시작할 것을 강력히 권장해요. 안내는 Built-in CloudNativePG Backup에서 마이그레이션을 참고하세요. :::
CloudNativePG는 오브젝트 스토어에 연속 물리적 백업과 WAL 아카이빙을 통해 PostgreSQL 클러스터의 온라인/핫 백업을 네이티브로 지원해요. 즉, 데이터베이스가 항상 가동 중(다운타임 불필요)이고 Point In Time Recovery를 사용할 수 있다는 뜻이에요.
오퍼레이터는 Barman Cloud 도구를 기반으로 한 연속 백업 인프라를 오케스트레이션할 수 있어요. 여러 PostgreSQL 인스턴스를 백업하는 Barman 서버가 있는 클래식한 아키텍처 대신, 오퍼레이터는 barman-cloud-wal-archive, barman-cloud-check-wal-archive, barman-cloud-backup, barman-cloud-backup-list, barman-cloud-backup-delete 도구에 의존해요. 그 결과 기본 백업은 tarball이 돼요. 기본 백업과 WAL 파일 모두 압축 및 암호화할 수 있어요.
이를 위해 barman-cli-cloud가 포함된 이미지를 사용해야 해요. ghcr.io/cloudnative-pg/postgresql 이미지를 이 용도로 사용할 수 있어요. 커뮤니티 PostgreSQL 이미지와 최신 barman-cli-cloud 패키지로 구성되어 있기 때문이에요.
:::info[Important] Barman cloud에 도입된 개선 사항을 활용하려면(그리고 클러스터의 보안 측면을 개선하려면) 항상 시스템에서 최신 버전의 operand를 실행하고 있는지 확인해 주세요. :::
:::warning[Barman Cloud 3.16+ 및 버킷 생성 변경 사항]
Barman Cloud 3.16부터 대부분의 Barman Cloud 명령은 대상 버킷이 이미 존재한다고 가정하고 더 이상 자동으로 생성하지 않아요. 이제 barman-cloud-check-wal-archive 명령만 버킷을 생성해요. 이것이 빈 버킷에서 실행되는 첫 번째 작업이 아닐 때마다 CloudNativePG는 오류를 발생시킬 거예요. 따라서 안정적이고 미래에도 대비된 운영을 보장하고 잠재적 문제를 피하려면, 이를 참조하는 Cluster 리소스를 만들기 전에 오브젝트 스토어 버킷을 만들고 구성할 것을 강력히 권장해요.
:::
백업은 Cluster의 프라이머리 또는 지정 프라이머리 인스턴스에서 수행되거나(지정 프라이머리 인스턴스에 대한 자세한 내용은 replica clusters 참고), 대안으로 standby에서 수행돼요.
공통 오브젝트 스토어
AWS S3, Microsoft Azure Blob Storage, Google Cloud Storage 또는 호환 프로바이더 같은 특정 오브젝트 스토어를 찾고 있다면 부록 C - 백업용 공통 오브젝트 스토어를 참고해 주세요.
WAL 아카이빙
WAL 아카이빙은 CloudNativePG에서 WAL 아카이브를 공급하는 프로세스예요.
WAL 아카이브는 Cluster 리소스의 .spec.backup.barmanObjectStore stanza에 정의돼요.
:::info
전체 옵션 목록은 barman-cloud API의 BarmanObjectStoreConfiguration을 참고해 주세요.
:::
필요하다면 WAL 파일을 업로드되는 즉시 압축 및/또는 암호화하도록 선택할 수 있어요:
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
[...]
spec:
backup:
barmanObjectStore:
[...]
wal:
compression: gzip
encryption: AES256
암호화를 버킷에서 직접 구성할 수 있고, 클러스터 구성에서 오버라이드하지 않는 한 오퍼레이터가 이를 사용해요.
PostgreSQL은 순차적 아카이빙 방식을 구현하며, 아카이브할 WAL 세그먼트마다 archive_command가 순차적으로 실행돼요.
:::info[Important]
기본적으로 CloudNativePG는 archive_timeout을 5min으로 설정해, 낮은 워크로드에서도 WAL 파일이 최소한 5분마다 닫히고 아카이브되도록 보장하며, Recovery Point Objective(RPO)에 대해 결정적인 시간 기반 값을 제공해요. PostgreSQL 구성에서 archive_timeout 설정 값을 변경하더라도, 우리 경험상 오퍼레이터가 설정한 기본값이 대부분의 사용 사례에 적합해요.
:::
PostgreSQL 인스턴스와 오브젝트 스토어 사이의 대역폭이 하나 이상의 WAL 파일을 병렬로 아카이브할 수 있을 때, 다음과 같이 인스턴스 매니저의 병렬 WAL 아카이빙 기능을 사용할 수 있어요:
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
[...]
spec:
backup:
barmanObjectStore:
[...]
wal:
compression: gzip
maxParallel: 8
encryption: AES256
이전 예시에서 인스턴스 매니저는 PostgreSQL이 요청한 WAL을 포함해 준비된 최대 8개의 WAL을 병렬로 아카이빙하여 WAL 아카이빙 프로세스를 최적화해요.
PostgreSQL이 인스턴스 매니저가 최적화로 이미 아카이브한 WAL의 아카이빙을 요청하면, 그 아카이브 요청은 긍정 상태로 그냥 무시돼요.
보존 정책(Retention policies)
CloudNativePG는 복구 기간(recovery window)을 기반으로 하는 보존 정책을 사용해 백업 오브젝트 스토어에서 백업 파일의 자동 삭제를 관리할 수 있어요.
내부적으로 보존 정책 기능은 --retention-policy “RECOVERY WINDOW OF {{ retention policy value }} {{ retention policy unit }}”와 함께 barman-cloud-backup-delete를 사용해요.
예를 들어, 백업을 30일 보존 정책으로 다음과 같이 정의할 수 있어요:
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
[...]
spec:
backup:
barmanObjectStore:
destinationPath: "<destination path here>"
s3Credentials:
accessKeyId:
name: aws-creds
key: ACCESS_KEY_ID
secretAccessKey:
name: aws-creds
key: ACCESS_SECRET_KEY
retentionPolicy: "30d"
:::note[There's more ...]
복구 기간 보존 정책은 복구 가능 지점(Point of Recoverability, PoR) 개념에 초점을 맞춰요. 이는 current time - recovery window로 결정되는 이동 지점이에요. *첫 번째 유효 백업(first valid backup)*은 PoR 이전의 첫 번째 사용 가능한 백업(역시간순)이에요. CloudNativePG는 첫 번째 유효 백업에서 시작해 PoR과 최신으로 성공적으로 아카이브된 WAL 파일 사이의 임의의 시점에서 클러스터를 복구할 수 있음을 보장해야 해요. 첫 번째 유효 백업보다 오래된 기본 백업은 obsolete로 표시되고 다음 백업이 완료된 후 영구적으로 제거돼요.
:::
압축 알고리즘
CloudNativePG는 기본적으로 백업과 WAL 파일을 압축하지 않은 상태로 아카이브해요. 하지만 barman-cloud-backup(백업용)과 barman-cloud-wal-archive(WAL 파일용)를 통한 다음 압축 알고리즘도 지원해요:
- bzip2
- gzip
- lz4
- snappy
- xz
- zstd
백업과 WAL의 압축 설정은 독립적이에요. barman-cloud API 참조의 DataBackupConfiguration과 WALBackupConfiguration 섹션을 참고하세요.
아카이브 시간, 복원 시간, 크기가 알고리즘마다 다르다는 점을 유의해야 하므로, 압축 알고리즘은 사용 사례에 따라 선택해야 해요.
Barman 팀은 Barman Cloud의 지원 알고리즘 성능 평가를 수행했어요. 다음 표는 로컬 MinIO 배포에서 백업을 수행한 시나리오를 요약해요. Barman GitHub 프로젝트에는 더 깊은 분석이 있어요.
| Compression | Backup Time (ms) | Restore Time (ms) | Uncompressed size (MB) | Compressed size (MB) | Approx ratio |
|---|---|---|---|---|---|
| None | 10927 | 7553 | 395 | 395 | 1:1 |
| bzip2 | 25404 | 13886 | 395 | 67 | 5.9:1 |
| gzip | 116281 | 3077 | 395 | 91 | 4.3:1 |
| snappy | 8134 | 8341 | 395 | 166 | 2.4:1 |
백업 오브젝트 태깅
Barman 2.18은 barman-cloud-backup과 barman-cloud-wal-archive를 통해 오브젝트 스토어에 저장할 때 백업 리소스 태깅 지원을 도입했어요. 그 결과, PostgreSQL 컨테이너 이미지에 버전 2.18 이상의 Barman이 포함되어 있으면 CloudNativePG는 기본 백업, WAL 파일, 히스토리 파일 같은 백업 오브젝트에 대한 태그를 키-값 쌍으로 지정할 수 있게 해줘요.
.spec.backup.barmanObjectStore 정의에서 다음 두 속성을 사용할 수 있어요:
tags: 백업 오브젝트 스토어의 백업 오브젝트와 아카이브된 WAL 파일에 추가할 키-값 쌍 태그historyTags: 백업 오브젝트 스토어의 아카이브된 히스토리 파일에 추가할 키-값 쌍 태그
아래 YAML 매니페스트 발췌는 이 기능의 사용 예시를 제공해요:
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
[...]
spec:
backup:
barmanObjectStore:
[...]
tags:
backupRetentionPolicy: "expire"
historyTags:
backupRetentionPolicy: "keep"
백업, WAL 아카이빙, 복원을 위한 추가 옵션
Cluster 리소스의 barmanObjectStore 섹션에서 해당 필드를 사용해 기본 barman-cloud-* 명령에 추가 옵션을 추가할 수 있어요.
barman-cloud-backup용.barmanObjectStore.data.additionalCommandArgsbarman-cloud-restore용.barmanObjectStore.data.restoreAdditionalCommandArgsbarman-cloud-wal-archive용.barmanObjectStore.wal.archiveAdditionalCommandArgsbarman-cloud-wal-restore용.barmanObjectStore.wal.restoreAdditionalCommandArgs
각 필드는 문자열 인수 목록을 허용해요. 인수가 해당 섹션의 선언된 옵션과 충돌하면 사용자 제공 값은 무시돼요.
예를 들어 --read-timeout=60을 사용해 연결 읽기 타임아웃을 커스터마이즈할 수 있어요.
barman-cloud-* 명령이 지원하는 추가 옵션은 공식 barman 문서 여기를 참고할 수 있어요.
다음은 이 속성의 사용 예시예요:
백업의 경우:
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
[...]
spec:
backup:
barmanObjectStore:
[...]
data:
additionalCommandArgs:
- "--min-chunk-size=5MB"
- "--read-timeout=60"
복원의 경우, restoreAdditionalCommandArgs는 복구가 읽는 외부 클러스터의 barmanObjectStore(즉, .spec.bootstrap.recovery.source가 이름을 지정하는 항목)에서 가져오며, .spec.backup에서 가져오지 않아요:
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
[...]
spec:
externalClusters:
- name: clusterBackup
barmanObjectStore:
[...]
data:
restoreAdditionalCommandArgs:
- "--read-timeout=60"
WAL 아카이빙 파일의 경우:
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
[...]
spec:
backup:
barmanObjectStore:
[...]
wal:
archiveAdditionalCommandArgs:
- "--max-concurrency=1"
- "--read-timeout=60"
WAL 복원 파일의 경우:
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
[...]
spec:
externalClusters:
- name: clusterBackup
barmanObjectStore:
[...]
wal:
restoreAdditionalCommandArgs:
- "--read-timeout=60"
오브젝트 스토어에서 복구하기
Barman Cloud가 만들고 지원되는 오브젝트 스토어에 저장된 백업에서 복구할 수 있어요. barmanObjectStore 섹션에 필요한 모든 구성을 포함해 외부 클러스터를 정의한 후, .spec.recovery.source 옵션에서 이를 참조해야 해요.
이 예시는 Azure의 블롭 컨테이너에 복구 오브젝트 스토어를 정의해요:
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
name: cluster-restore
spec:
[...]
superuserSecret:
name: superuser-secret
bootstrap:
recovery:
source: clusterBackup
externalClusters:
- name: clusterBackup
barmanObjectStore:
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: 8
이전 예시는 애플리케이션 데이터베이스와 이를 소유한 사용자가 기본적으로 app이라고 가정해요. 복원되는 PostgreSQL 클러스터가 다른 이름을 사용한다면, "Configure the application database"에 문서화된 대로 복구 단계를 종료하기 전에 이 이름들을 지정해야 해요.
:::info[Important]
기본적으로 recovery 메서드는 externalClusters 섹션의 클러스터 name을 오브젝트 스토어 내 백업 데이터의 메인 폴더 이름으로 엄격하게 사용해요. 이 이름은 보통 서버 이름으로 예약돼요. barmanObjectStore.serverName 속성을 사용해 다른 폴더 이름을 지정할 수 있어요.
:::
:::note 이 예시는 병렬 WAL 복원 기능을 활용해 아카이브에서 필요한 WAL 파일을 동시에 가져오는 데 최대 8개 작업을 할당해요. 이 기능은 복구 시간을 눈에 띄게 줄일 수 있어요. 이 시나리오를 미리 계획하고 환경에 맞게 이 파라미터 값을 올바르게 조정하세요. 필요할 때 차이가 있을 거예요, 확실히요. :::