본문 바로가기
WIKI 기술 지식 베이스

부록 A - 볼륨 스냅샷 백업(Backup on volume snapshots)

원문 보기 위키 갱신

CloudNativePG는 Kubernetes의 네이티브 볼륨 스냅샷 API를 백업과 복구에 선언적으로 활용한 최초의 데이터베이스 오퍼레이터 사례 중 하나예요. 볼륨 스냅샷 백업을 구성하고 핫/콜드 백업, 보존 정책, 데드라인 설정을 살펴볼게요.

출처: 문서

본문

:::info[Important] 스냅샷 기능을 제공하는 지원되는 Container Storage Interface (CSI) 드라이버 전체 목록은 공식 Kubernetes 문서를 참고해 주세요. :::

CloudNativePG는 백업과 복구 작업 모두에 Kubernetes 네이티브 볼륨 스냅샷 API를 완전히 선언적인 방식으로 직접 활용하는 최초의 알려진 데이터베이스 오퍼레이터 사례 중 하나예요.

표준 볼륨 스냅샷에 대해

볼륨 스냅샷은 Kubernetes 1.12 (2018)에서 alpha로 처음 도입됐고, 1.17 (2019)에서 beta로 승격됐으며, 1.20 (2020)에서 GA로 이동했어요. 이제 안정적이고 널리 사용 가능하며 표준이 되었고, VolumeSnapshot, VolumeSnapshotContent, VolumeSnapshotClass라는 3개의 커스텀 리소스 정의를 제공해요.

이 Kubernetes 기능은 다음과 같은 일반적인 인터페이스를 정의해요:

  • PVC에서 시작해 새 볼륨 스냅샷 생성
  • 기존 스냅샷 삭제
  • 스냅샷에서 새 볼륨 생성

Kubernetes는 실제 구현을 기본 CSI 드라이버에 위임해요(모두가 볼륨 스냅샷을 지원하는 것은 아니에요). 일반적으로 볼륨 스냅샷을 제공하는 스토리지 클래스는 애플리케이션에게 투명한 방식으로 증분 및 차등 블록 레벨 백업을 지원하며, 복잡성과 독립 관리, 스냅샷의 클러스터 간 가용성까지 하위 스택에 위임할 수 있어요.

요구사항

볼륨 스냅샷이 CloudNativePG 클러스터에서 동작하려면 PostgreSQL 볼륨을 동적으로 프로비저닝하는 데 사용되는 각 스토리지 클래스(즉, storage와 walStorage 섹션)가 볼륨 스냅샷을 지원하는지 확인해야 해요.

지침은 스토리지 클래스마다 다르므로, Kubernetes 시스템에 배포한 특정 스토리지 클래스와 관련 CSI 드라이버의 문서를 참고해 주세요.

일반적으로 VolumeSnapshotClass가 특정 스토리지 클래스의 퍼시스턴트 볼륨에서 스냅샷을 찍을 수 있게 하고, 이를 VolumeSnapshot과 VolumeSnapshotContent 리소스로 관리하는 책임을 져요.

:::info[Important] 볼륨 스냅샷이 지원되는지 제3자 벤더와 확인하는 것은 사용자의 책임이에요. CloudNativePG는 이 문제에 대해 Kubernetes API와만 상호작용하며, 각각의 특정 CSI 드라이버에 대한 스토리지 레벨의 문제를 지원할 수 없어요. :::

볼륨 스냅샷 백업 구성 방법

CloudNativePG는 backup.volumeSnapshot stanza를 통해 특정 Postgres 클러스터를 볼륨 스냅샷 백업용으로 구성할 수 있게 해줘요.

:::info 전체 옵션 목록은 API 참조의 VolumeSnapshotConfiguration을 참고해 주세요. :::

볼륨 스냅샷을 사용하는 일반적인 예시(PGDATA와 WAL이 같은 스토리지 클래스를 공유한다고 가정)는 다음과 같아요:

apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
  name: snapshot-cluster
spec:
  instances: 3

  storage:
    storageClass: @STORAGE_CLASS@
    size: 10Gi
  walStorage:
    storageClass: @STORAGE_CLASS@
    size: 10Gi

  backup:
    # Volume snapshot backups
    volumeSnapshot:
       className: @VOLUME_SNAPSHOT_CLASS_NAME@
       
  plugins:
  - name: barman-cloud.cloudnative-pg.io
    isWALArchiver: true
    parameters:
      barmanObjectName: @OBJECTSTORE_NAME@

보시다시피 backup 섹션에는 volumeSnapshot stanza(볼륨 스냅샷의 물리적 기본 백업 제어)와 plugins stanza(WAL 아카이브 제어)가 모두 포함돼 있어요.

:::info plugin을 정의한 후에는 물리적 백업을 위해 볼륨 스냅샷 전략과 플러그인 백업 전략을 동시에 사용할지 결정할 수 있어요. :::

volumeSnapshot.className 옵션은 PostgreSQL 클러스터에서 정의한 모든 스토리지 볼륨에 사용되는 기본 VolumeSnapshotClass 오브젝트를 참조할 수 있게 해줘요.

:::info PGDATA와 WAL 파일에 다른 스토리지 클래스를 사용하는 경우, walClassName 옵션(기본값은 className과 동일)으로 해당 볼륨에 별도의 VolumeSnapshotClass를 지정할 수 있어요. :::

클러스터가 볼륨 스냅샷 백업용으로 정의되면, 이러한 백업을 주기적으로 요청하는 ScheduledBackup 리소스를 정의해야 해요.

핫 및 콜드 백업

:::warning 백업 문서에서 언급했듯이, 콜드 스냅샷이 명시적으로 프라이머리를 대상으로 하면 백업 동안 프라이머리가 펜싱(fenced)되어 해당 기간 동안 클러스터가 읽기 전용이 돼요. 안전을 위해 이미 펜싱된 인스턴스가 있는 클러스터에서는 콜드 스냅샷이 거부돼요. :::

기본적으로 CloudNativePG는 PostgreSQL의 기본 백업용 저수준 API 기본값을 사용해 볼륨 스냅샷에서 온라인/핫 백업을 요청해요:

  • 백업 절차를 시작할 때 즉시 체크포인트를 요청하지 않아요
  • 백업 절차를 종료할 때 WAL 아카이버가 백업의 마지막 세그먼트를 아카이브할 때까지 기다려요

:::info[Important] 기본값은 대부분의 프로덕션 환경에 적합해요. 핫 백업은 일관성이 있고, 임시 복제 슬롯을 통해 백업 시작부터 WAL 보존을 보장하므로 스냅샷 복구를 수행하는 데 사용할 수 있어요. 하지만 그 목적에는 콜드 백업에 의존할 것을 권장해요. :::

Cluster 리소스의 .spec.backup.volumeSnapshot stanza에서 다음 옵션을 통해 기본 동작을 명시적으로 변경할 수 있어요:

  • online: true(기본값) 또는 false 값을 허용
  • onlineConfiguration.immediateCheckpoint: 백업 절차를 시작하기 전에 즉시 체크포인트를 요청할지 여부; 기술적으로 PostgreSQL에서 pg_backup_start/pg_start_backup() 함수에 전달하는 fast 인수에 해당하며, true(기본값) 또는 false를 허용
  • onlineConfiguration.waitForArchive: 아카이버가 백업의 마지막 세그먼트를 처리할 때까지 기다릴지 여부; 기술적으로 PostgreSQL에서 pg_backup_stop/pg_stop_backup() 함수에 전달하는 wait_for_archive 인수에 해당하며, true(기본값) 또는 false를 허용

Postgres 클러스터가 기본적으로 콜드 백업을 수행하도록 기본 동작을 변경하려면 매니페스트에 online: false 옵션만 추가하면 돼요:

  # ...
  backup:
    volumeSnapshot:
       online: false
       # ...

대신 즉시 체크포인트를 기본 동작으로 요청하려면 이 섹션을 추가할 수 있어요:

  # ...
  backup:
    volumeSnapshot:
       online: true
       onlineConfiguration:
         immediateCheckpoint: true
       # ...

기본 동작 오버라이드하기

Backup 또는 ScheduledBackup 오브젝트에서 online과 필요 시 onlineConfiguration에 다른 값을 설정해 클러스터 리소스에 정의된 기본 동작을 변경할 수 있어요.

예를 들어, 온디맨드 콜드 백업을 발행하려면 .spec.online: false로 Backup 오브젝트를 만들 수 있어요:

apiVersion: postgresql.cnpg.io/v1
kind: Backup
metadata:
  name: snapshot-cluster-cold-backup-example
spec:
  cluster:
    name: snapshot-cluster
  method: volumeSnapshot
  online: false

ScheduledBackup도 비슷해요:

apiVersion: postgresql.cnpg.io/v1
kind: ScheduledBackup
metadata:
  name: snapshot-cluster-cold-backup-example
spec:
  schedule: "0 0 0 * * *"
  backupOwnerReference: self
  cluster:
    name: snapshot-cluster
  method: volumeSnapshot
  online: false

볼륨 스냅샷 오브젝트의 지속성

기본적으로 CloudNativePG가 만든 VolumeSnapshot 오브젝트는 이를 발생시킨 Backup 오브젝트나 이들이 참조하는 Cluster를 삭제한 후에도 보존돼요. 이러한 동작은 .spec.backup.volumeSnapshot.snapshotOwnerReference 옵션으로 제어되며 다음 값을 허용해요:

  • none: 소유권이 설정되지 않아, VolumeSnapshot 오브젝트가 Backup 및/또는 Cluster 리소스가 제거된 후에도 유지돼요
  • backup: VolumeSnapshot 오브젝트가 이를 발생시킨 Backup 리소스에 의해 소유되며, 백업 오브젝트가 제거되면 볼륨 스냅샷도 제거돼요
  • cluster: VolumeSnapshot 오브젝트가 백업된 Cluster 리소스에 의해 소유되며, Postgres 클러스터가 제거되면 볼륨 스냅샷도 제거돼요

VolumeSnapshot이 삭제되면 VolumeSnapshotContent에 지정된 deletionPolicy가 평가돼요:

  • Retain으로 설정되면 VolumeSnapshotContent 오브젝트가 유지돼요
  • Delete로 설정되면 VolumeSnapshotContent 오브젝트도 제거돼요

:::warning VolumeSnapshotContent 오브젝트는 그들이 참조하는 백업과 클러스터에 대한 모든 정보(예: VolumeSnapshot 오브젝트에 포함된 어노테이션과 레이블)를 보관하지 않아요. 가능하지만, 이런 종류의 오브젝트만으로 복원하는 것은 간단하지 않을 수 있어요. 이런 이유로 Kubernetes 레벨의 데이터 보호 솔루션을 사용하더라도 항상 VolumeSnapshot 정의를 백업할 것을 권장해요. :::

VolumeSnapshotContent의 값은 .spec.backup.volumeSnapshot.className 옵션에서 참조되는 해당 VolumeSnapshotClass 정의에 설정된 deletionPolicy에 의해 결정돼요.

이 표준 동작에 대한 자세한 내용은 Kubernetes의 Volume Snapshot Classes 문서를 참고해 주세요.

백업 볼륨 스냅샷 데드라인

CloudNativePG는 볼륨 스냅샷 방식을 사용한 백업을 지원해요. 볼륨 스냅샷 작업 중 오류가 발생할 수 있는데, CloudNativePG는 포기하기 전에 구성 가능한 시간 동안 재시도해요.

backup.cnpg.io/volumeSnapshotDeadline 어노테이션은 CloudNativePG가 이러한 오류를 백업을 실패로 표시하기 전에 계속 재시도해야 하는 시간을 정의해요.

backup.cnpg.io/volumeSnapshotDeadline 어노테이션은 Backup과 ScheduledBackup 리소스 모두에 추가할 수 있어요. ScheduledBackup 리소스의 경우, 이 어노테이션은 스케줄에서 생성되는 모든 Backup 리소스에 자동으로 상속돼요.

지정하지 않으면 기본 재시도 데드라인은 10분이에요.

오류 처리

볼륨 스냅샷 작업 중 오류가 발생하면:

  1. CloudNativePG는 첫 오류의 시간을 기록해요.
  2. 시스템은 10초마다 작업을 재시도해요.
  3. 오류가 지정된 데드라인(또는 기본 10분)을 넘어 지속되면 백업은 실패로 표시돼요.

CSI 드라이버는 스냅샷 오류를 자유 텍스트로 보고하며, 영구적인 상태(예: 누락된 VolumeSnapshotClass 또는 잘못된 자격 증명)와 일시적인 상태를 구별할 신뢰할 수 있는 방법이 없고, 영구적으로 보이는 상태도 언제든 해결될 수 있어요(예: CloudNativePG가 재시도하는 동안 누군가 누락된 클래스를 만들거나 자격 증명을 수정한 경우). 이런 이유로 CloudNativePG는 데드라인에 도달할 때까지 모든 볼륨 스냅샷 오류를 같은 방식으로 재시도해요.

예시

ScheduledBackup 리소스에 다음과 같이 어노테이션을 추가할 수 있어요:

apiVersion: postgresql.cnpg.io/v1
kind: ScheduledBackup
metadata:
  name: daily-backup-schedule
  annotations:
    backup.cnpg.io/volumeSnapshotDeadline: "20"
spec:
  schedule: "0 0 * * *"
  backupOwnerReference: self
  method: volumeSnapshot
  # other configuration...

어노테이션으로 ScheduledBackup을 정의하면, 이 스케줄에서 생성되는 모든 Backup 리소스가 지정된 타임아웃 값을 자동으로 상속해요.

다음 예시에서 스케줄에서 생성된 모든 백업은 스냅샷 오류 재시도에 30분 타임아웃을 가져요.

apiVersion: postgresql.cnpg.io/v1
kind: ScheduledBackup
metadata:
  name: weekly-backup
  annotations:
    backup.cnpg.io/volumeSnapshotDeadline: "30"
spec:
  schedule: "0 0 * * 0"  # Weekly backup on Sunday
  method: volumeSnapshot
  cluster:
    name: my-postgresql-cluster

대안으로 Backup 리소스에 직접 어노테이션을 추가할 수 있어요:

apiVersion: postgresql.cnpg.io/v1
kind: Backup
metadata:
  name: my-backup
  annotations:
    backup.cnpg.io/volumeSnapshotDeadline: "15"
spec:
  method: volumeSnapshot
  # other backup configuration...

볼륨 스냅샷 백업 예시

다음 예시는 AWS의 EKS 클러스터에서 ebs-sc 스토리지 클래스와 csi-aws-vsc 볼륨 스냅샷 클래스를 사용해 볼륨 스냅샷 기본 백업을 구성하는 방법을 보여줘요.

:::info[Important] 이 예시를 테스트하는 데 관심이 있다면, 스토리지 클래스와 스냅샷 클래스의 설치 과정에 대한 자세한 지침을 위해 Amazon Elastic Block Store (EBS) CSI 드라이버의 "Volume Snapshots"를 읽어 주세요. :::

다음 매니페스트는 볼륨 스냅샷에 사용할 준비가 된 Cluster를 만들고, Service Account용 IAM 역할(IRSA, AWS S3 참고)을 통해 WAL 아카이브를 S3 버킷에 저장해요:

apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
  name: hendrix
spec:
  instances: 3

  storage:
    storageClass: ebs-sc
    size: 10Gi
  walStorage:
    storageClass: ebs-sc
    size: 10Gi

  backup:
    volumeSnapshot:
       className: csi-aws-vsc

  plugins:
  - name: barman-cloud.cloudnative-pg.io
    isWALArchiver: true
    parameters:
      barmanObjectName: @OBJECTSTORE_NAME@

  serviceAccountTemplate:
    metadata:
      annotations:
        eks.amazonaws.com/role-arn: "@ARN@"
---
apiVersion: postgresql.cnpg.io/v1
kind: ScheduledBackup
metadata:
  name: hendrix-vs-backup
spec:
  cluster:
    name: hendrix
  method: volumeSnapshot
  schedule: '0 0 0 * * *'
  backupOwnerReference: cluster
  immediate: true

마지막 리소스는 자정에 일일 볼륨 스냅샷 백업을 정의하고, 클러스터가 생성된 직후 하나를 즉시 요청해요.

더 알아보기 (Learn more)