Trident Protect 25.06에서 예약된 전체 백업이 도입

NetApp Tech Blog에 갔다가 Trident 관련해서 흥미로운 주제의 글이 보여서 AI 번역(+약간 수정)의 힘을 빌려 읽어보았습니다.
출처: https://community.netapp.com/t5/Tech-ONTAP-Blogs/Trident-protect-25-06-introduces-scheduled-full-backups/ba-p/463884

NetApp® Trident™ Protect는 애플리케이션 데이터 관리에 혁신을 일으켜 NetApp ONTAP 스토리지 시스템과 NetApp Trident Container Storage Interface(CSI) 스토리지 프로비저너가 지원하는 상태 저장 Kubernetes 애플리케이션의 기능과 가용성을 향상시킵니다. 다양한 완전 관리형 및 자체 관리형 Kubernetes 제품과 호환되는 Trident Protect는 다양한 플랫폼과 지역에서 Kubernetes 서비스를 보호하는 최고의 솔루션입니다.

영구 데이터를 개체 스토리지에 백업하기 위해 Trident Protect는 데이터 무버( Restic 또는 기본적으로 Kopia )를 사용하여 영구 볼륨의 CSI 스냅샷에서 개체 스토리지로 데이터를 원활하게 전송합니다. 두 데이터 무버 모두 초기 백업에서 증분 백업을 수행하여 “증분식 영구 백업(incremental forever)” 방식을 보장합니다.

“증분식 영구 백업” 전략은 첫 번째 백업이 전체 백업이고 이후 모든 백업이 증분식 백업으로 진행되는 방식으로, 저장 공간 효율성과 빠른 백업 시간을 제공합니다. 하지만 다음과 같은 몇 가지 과제가 있습니다.

  • 더 긴 복구 시간
    • 종속성 체인 – 데이터를 복원하려면 마지막 전체 백업부터 시작하여 모든 증분 백업을 순서대로 적용해야 합니다. 즉, 복원 프로세스는 체인에서 가장 느린 증분 백업의 속도에 따라 달라집니다.
    • 누적 오버헤드 – 증분 백업이 많을수록 복원 프로세스가 더 오래 걸립니다. 특히 체인이 길거나 증분 백업이 손상되었거나 누락된 경우 더욱 그렇습니다.
  • 복잡성 증가
    • 관리 오버헤드 – 증분 백업의 긴 체인을 추적하고 관리하는 작업은 특히 대규모 또는 동적인 환경에서 오류가 발생하기 쉽습니다.
    • 실패의 위험
      • 체인의 단일 증분 백업이 손상되거나 손실되면 전체 복원 프로세스가 실패하거나 수동 개입이 필요할 수 있습니다.
      • 데이터 중복이 제거되면 단일 데이터 손상으로 인해 모든 복원 지점이 한꺼번에 무효화될 수 있습니다.
    • 성능 병목 현상
      • I/O 및 CPU 부하 – 많은 증분 백업에서 복원하면 스토리지 시스템과 CPU에 큰 부하가 걸려 전체 프로세스가 느려질 수 있습니다.
    • 특정 시점 복구 과제
      • 세분성 문제 – 증분적 영구 복구는 특정 시점 복구를 허용하는 반면, 특정 시점으로 복원하려면 해당 시점까지 전체 체인을 재구성해야 할 수 있으며, 이는 시간이 많이 걸릴 수 있습니다.

다음의 경우 문제가 될 수 있습니다.

  • 대용량 데이터: 대용량 데이터 세트나 빈번한 변경 사항을 처리할 때 단점이 더욱 커집니다.
  • 중요 시스템: 빠른 복구가 필수적인 시스템(예: 데이터베이스, 미션 크리티컬 애플리케이션)의 경우 복원 시간이 느리다는 것은 큰 단점이 될 수 있습니다.

요약하자면, 증분적 영구 백업은 저장 및 백업 속도 측면에서 효율적이지만, 그 대가로 복원 속도가 더 느리고 더 복잡해질 수 있으며, 이는 복구 시나리오에서 심각한 제한이 될 수 있습니다.

사용자 환경에 맞는 최적의 백업 전략을 찾을 수 있도록 Trident Protect 25.06은 “증분식 영구 백업”과 간헐적인 전체 백업을 결합하는 기능을 제공합니다. 이러한 균형 잡힌 접근 방식은 스토리지 효율성을 높이는 동시에 복원 속도도 향상시킵니다.

이 블로그 게시물에서는 온디맨드 백업과 예약 백업 모두에 이 새로운 기능을 활용하는 방법을 단계별로 안내해 드리겠습니다. 지금부터 자세히 살펴보고 백업 전략을 한 단계 업그레이드해 보세요!

필수 조건

이 가이드를 따라가려면 다음 사항이 있는지 확인하세요.

  • 최신 버전의 Trident 및 Trident Protect가 설치된 Kubernetes 클러스터와 관련 kubeconfig 파일
  • 구성된 스토리지 백엔드, 스토리지 클래스 및 볼륨 스냅샷 클래스가 있는 NetApp ONTAP 스토리지 백엔드 및 Trident
  • 백업 및 메타데이터 정보를 저장하기 위한 구성된 개체 스토리지 버킷
  • kubeconfig를 사용하도록 구성된 kubectl이 있는 워크스테이션
  • 워크스테이션에 설치된 Trident protect의 tridentctl -protect CLI
  • Kubernetes 클러스터에 대한 관리자 권한
  • 선택적으로 워크스테이션에 Kopia CLI가 설치됩니다.

테스트 환경

먼저, 블로그 전체에서 사용한 테스트 환경의 설정을 간략히 살펴보겠습니다.

Azure Kubernetes Service(AKS) 테스트 클러스터의 서로 다른 네임스페이스에서 NGINX와 Alpine이라는 두 가지 간단한 샘플 애플리케이션을 사용합니다.

NGINX 애플리케이션은 웹 네임스페이스에 배포되며 NetApp Azure File(ANF) 스토리지로 지원되는 영구 볼륨(PV)이 하나 있습니다. 여기에 몇 가지 무작위 파일을 추가했습니다.

$ kubectl get all -n web
NAME                       READY   STATUS    RESTARTS   AGE
pod/web-64cdb84b99-pnvnm   1/1     Running   0          5d23h

NAME                  READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/web   1/1     1            1           5d23h

NAME                             DESIRED   CURRENT   READY   AGE
replicaset.apps/web-64cdb84b99   1         1         1       5d23h

NAME                              STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS                  VOLUMEATTRIBUTESCLASS   AGE
persistentvolumeclaim/nginxdata   Bound    pvc-1ff159f4-a3ea-45e5-bdb7-b0b5f3878466   50Gi       RWX            azure-netapp-files-standard   <unset>                 5d23h

$ kubectl -n web exec -it pod/web-64cdb84b99-pnvnm -- df -h /data
Filesystem                                           Size  Used Avail Use% Mounted on
10.21.2.7:/pvc-1ff159f4-a3ea-45e5-bdb7-b0b5f3878466   50G   41M   50G   1% /data
~$ k -n web exec -it pod/web-64cdb84b99-pnvnm -- ls -l /data
total 41164
-rw-r--r-- 1 nobody nogroup    10240 Oct 10 09:41 file1
-rw-r--r-- 1 nobody nogroup 10485760 Oct 16 08:15 file2
-rw-r--r-- 1 nobody nogroup 10485760 Oct 16 08:15 file3
-rw-r--r-- 1 nobody nogroup 10485760 Oct 16 08:15 file4
-rw-r--r-- 1 nobody nogroup 10485760 Oct 16 08:16 file5

Trident protect에 웹 네임스페이스를 애플리케이션 웹 으로 추가합니다 .

$ tridentctl-protect create app web --namespaces web -n web
Application "web" created.

두 번째 샘플 애플리케이션은 ANF로 백업된 두 개의 PV가 있는 alpine 네임스페이스의 Alpine 컨테이너로 , 각 PV에는 무작위 파일 하나가 채워져 있으며, 이를 Trident protect에 alpine 애플리케이션으로 추가합니다 .

$ kubectl get all -n alpine
NAME                          READY   STATUS    RESTARTS   AGE
pod/alpine-6cd7c6fdf7-fm9dm   1/1     Running   0          7m9s

NAME                     READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/alpine   1/1     1            1           7m10s

NAME                                DESIRED   CURRENT   READY   AGE
replicaset.apps/alpine-6cd7c6fdf7   1         1         1       7m10s

NAME                                 STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS                  VOLUMEATTRIBUTESCLASS   AGE
persistentvolumeclaim/alpinedata     Bound    pvc-9601c314-f343-4894-927a-c5ad2ac59644   50Gi       RWX            azure-netapp-files-standard   <unset>                 7m10s
persistentvolumeclaim/alpinedata-2   Bound    pvc-95bd408e-b0c7-4b68-83d0-9d85dadb3e46   50Gi       RWX            azure-netapp-files-standard   <unset>                 7m9s

$ kubectl -n alpine exec -it pod/alpine-6cd7c6fdf7-fm9dm -- ls -l /data /data2
/data:
total 102808
-rw-r--r--    1 nobody   nobody   104857600 Oct 21 13:41 file1

/data2:
total 102808
-rw-r--r--    1 nobody   nobody   104857600 Oct 21 13:46 file1
~$ k -n alpine exec -it pod/alpine-6cd7c6fdf7-fm9dm -- df -h | grep data
                         50.0G    101.0M     49.9G   0% /data
                         50.0G    101.0M     49.9G   0% /data2

$ tridentctl-protect create app alpine --namespaces alpine -n alpine
Application "alpine" created.

이제 두 개의 Trident Protect 애플리케이션이 정의되었습니다.

$ tridentctl-protect get application -A
+-----------+--------+------------+-------+-------+
| NAMESPACE |  NAME  | NAMESPACES | STATE |  AGE  |
+-----------+--------+------------+-------+-------+
| alpine    | alpine | alpine     | Ready | 1d3h  |
| web       | web    | web        | Ready | 1d4h  |
+-----------+--------+------------+-------+-------+

백업 데이터를 저장하는 개체 저장소로 Azure Storage 계정 puneptunetest 의 Azure Storage Blob 컨테이너 데모 를 사용합니다 . 이는 Trident protect appVault 사용자 지정 리소스(CR) 데모 로 표현됩니다 .

$ tridentctl-protect get appvault
+------+----------+-----------+-------+---------+--------+
| NAME | PROVIDER |   STATE   | ERROR | MESSAGE |  AGE   |
+------+----------+-----------+-------+---------+--------+
| demo | Azure    | Available |       |         | 19d23h |
+------+----------+-----------+-------+---------+--------+

AppVault CR을 생성하는 방법과 데이터 무버 저장소의 비밀번호를 설정하는 방법에 대한 자세한 단계와 예시는 Trident Protect 문서를 참조하세요 . 여기서 설정한 Kopia 데이터 무버 비밀번호를 기록해 두세요. 나중에 필요합니다.

이제 Trident Protect를 사용하여 전체 백업을 조사할 준비가 되었습니다.

주문형 백업

온디맨드 백업부터 시작하여 전체 및 증분 온디맨드 백업 생성을 어떻게 제어할 수 있는지 살펴보겠습니다.

백업 유형은 Trident Protect의 metadata.annotations.protect.trident.netapp.io/full-backup 애노테이션을 통해 구성됩니다. 이 애노테이션을 true 로 설정하면 백업이 비증분 백업으로 설정됩니다. 지정하지 않으면 기본 증분 백업 설정을 따릅니다.

다음은 전체 주문형 백업에 대한 샘플 YAML 매니페스트입니다.

apiVersion: protect.trident.netapp.io/v1
kind: Backup
metadata:
  namespace: my-app-namespace
  name: my-cr-name
  annotations:
    protect.trident.netapp.io/full-backup: "true"
spec:
  applicationRef: my-application
  appVaultRef: appvault-name
  dataMover: Kopia

Trident protect의 강력한 CLI를 사용하여 전체 주문형 백업을 생성할 때 tridentctl-protect create backup 명령에 –full-backup 플래그를 추가합니다 .

다음으로, 이제 알파인 애플리케이션의 전체 주문형 백업을 생성합니다.

$ tridentctl-protect create backup alpine-full-1 --app alpine --appvault demo --full-backup -n alpine
Backup "alpine-full-1" created.

$ tridentctl-protect get backup -n alpine
+---------------+--------+----------------+-----------+-------+-------+
|     NAME      |  APP   | RECLAIM POLICY |   STATE   | ERROR |  AGE  |
+---------------+--------+----------------+-----------+-------+-------+
| alpine-full-1 | alpine | Retain         | Completed |       | 6m18s |
+---------------+--------+----------------+-----------+-------+-------+

백업이 완료되면 해당 백업 YAML 매니페스트를 자세히 살펴보겠습니다.

$ kubectl -n alpine get backup alpine-full-1 -o yaml
apiVersion: protect.trident.netapp.io/v1
kind: Backup
metadata:
  annotations:
    protect.trident.netapp.io/correlationid: 1f15357e-1330-4478-a902-a826a26d4a67
    protect.trident.netapp.io/full-backup: "true"
  creationTimestamp: "2025-10-21T14:00:51Z"
  finalizers:
  .. ..
  generation: 1
  name: alpine-full-1
  namespace: alpine
  ownerReferences:
  - apiVersion: protect.trident.netapp.io/v1
    kind: Application
    name: alpine
    uid: 8ef17301-234c-4d48-b7c4-2809d592f125
  resourceVersion: "11054926"
  uid: 1736c690-98a2-4a04-977b-94ef1fec264d
spec:
  appVaultRef: demo
  applicationRef: alpine
  cleanupSnapshot: false
  dataMover: Kopia
  reclaimPolicy: Retain
status:
  appArchivePath: alpine_8ef17301-234c-4d48-b7c4-2809d592f125/backups/alpine-full-1_1736c690-98a2-4a04-977b-94ef1fec264d
  appVaultRef: demo
  completionTimestamp: "2025-10-21T14:05:05Z"
  conditions:
.. ..
  - lastTransitionTime: "2025-10-21T14:00:52Z"
    message: Not yet reconciled
    reason: Pending
    status: Unknown
    type: OnFailurePostBackupExecHooksRunCompleted
  latestRepositoryTimestamp: "20251021_140113"
  postBackupExecHooksRunResults: []
  postSnapshotExecHooksRunResults: []
  preBackupExecHooksRunResults: []
  preSnapshotExecHooksRunResults: []
  progress:
    volumeBackups:
    - completionTimestamp: "2025-10-21T14:05:04Z"
      progress:
        bytesCompleted: 104857600
        bytesRemaining: 0
        bytesTotal: 104857600
        updatedAt: "2025-10-21T14:04:01Z"
      pvcUid: 9601c314-f343-4894-927a-c5ad2ac59644
      repositoryPath: alpine_8ef17301-234c-4d48-b7c4-2809d592f125/kopia_20251021_140113/alpine/alpinedata_9601c314-f343-4894-927a-c5ad2ac59644/
      snapshotID: eb9bdc9f7f54ed1bd57fd63482575a21
      sourceVolumeSnapshot:
        name: snapshot-d9ec9c10-2963-4d4f-beb3-61434d26938f-pvc-9601c314-f343-4894-927a-c5ad2ac59644
        namespace: alpine
      volumeBackupCompleted: true
      volumeBackupCreated: true
      volumeSnapshotContentCopyName: backup-1736c690-98a2-4a04-977b-94ef1fec264d-vsc-e97828fc-99c7-4d3a-88c5-7559fdd3d3a4
      volumeSnapshotCopied: true
      volumeSnapshotCopyDeleted: true
      volumeSnapshotCopyName: backup-1736c690-98a2-4a04-977b-94ef1fec264d-vs-6ada2115-8252-4e91-88c8-fbd227193453
      volumeSnapshotCopyReadyToUse: true
    - completionTimestamp: "2025-10-21T14:04:51Z"
      progress:
        bytesCompleted: 104857600
        bytesRemaining: 0
        bytesTotal: 104857600
        updatedAt: "2025-10-21T14:03:50Z"
      pvcUid: 95bd408e-b0c7-4b68-83d0-9d85dadb3e46
      repositoryPath: alpine_8ef17301-234c-4d48-b7c4-2809d592f125/kopia_20251021_140113/alpine/alpinedata-2_95bd408e-b0c7-4b68-83d0-9d85dadb3e46/
      snapshotID: 0d7c8b2c34c17d0a48d1529d399e0c52
      sourceVolumeSnapshot:
        name: snapshot-d9ec9c10-2963-4d4f-beb3-61434d26938f-pvc-95bd408e-b0c7-4b68-83d0-9d85dadb3e46
        namespace: alpine
      volumeBackupCompleted: true
      volumeBackupCreated: true
      volumeSnapshotContentCopyName: backup-1736c690-98a2-4a04-977b-94ef1fec264d-vsc-3589ff58-854a-4b64-8f1b-78af102193db
      volumeSnapshotCopied: true
      volumeSnapshotCopyDeleted: true
      volumeSnapshotCopyName: backup-1736c690-98a2-4a04-977b-94ef1fec264d-vs-0d01ecc5-0b44-47d9-a4eb-40821d49eddc
      volumeSnapshotCopyReadyToUse: true
  sourceSnapshotName: backup-1736c690-98a2-4a04-977b-94ef1fec264d
  state: Completed

메타데이터에서 전체 백업 주석이 protect.trident.netapp.io/full-backup: “true” 로 올바르게 설정되어 있는 것을 확인할 수 있습니다 .

$ kubectl -n alpine get backup alpine-full-1 -o yaml | yq '.metadata.annotations."protect.trident.netapp.io/full-backup"'
true

백업할 PV가 두 개 있으므로 yaml의 진행률 섹션에서 두 개의 해당 volumeBackups를 볼 수 있으며 각각 고유한 repositoryPath 값이 있습니다.

$ kubectl -n alpine get backup alpine-full-1 -o yaml | yq '.status.progress.volumeBackups[].repositoryPath'
alpine_8ef17301-234c-4d48-b7c4-2809d592f125/kopia_20251021_140113/alpine/alpinedata_9601c314-f343-4894-927a-c5ad2ac59644/
alpine_8ef17301-234c-4d48-b7c4-2809d592f125/kopia_20251021_140113/alpine/alpinedata-2_95bd408e-b0c7-4b68-83d0-9d85dadb3e46/ 

두 개의 repositoryPath 값을 사용하면 Kopia CLI를 사용하여 Azure Storage 컨테이너에서 백업 중에 생성된 Kopia 저장소에 연결할 수 있습니다. 첫 번째 Kopia 저장소에 연결해 보겠습니다.

$ kopia repository connect azure --storage-account=puneptunetest --storage-key="<REDACTED>" --container=demo --prefix=$(k -n alpine get backup alpine-full-1 -o yaml | yq '.status.progress.volumeBackups[0].repositoryPath')
Enter password to open repository:

Connected to repository.

NOTICE: Kopia will check for updates on GitHub every 7 days, starting 24 hours after first use.
To disable this behavior, set environment variable KOPIA_CHECK_FOR_UPDATES=false
Alternatively you can remove the file "/Users/patricu/Library/Application Support/kopia/repository.config.update-info.json".

이제 첫 번째 Kopia 저장소에 있는 Kopia 스냅샷을 나열할 수 있습니다. 여기에는 하나의 파일의 백업을 포함하는 첫 번째(전체) 백업에 해당하는 스냅샷이 있습니다.

$ kopia snapshot list --all
root@protect.trident.netapp.io:/sourceVolume
  2025-10-21 16:01:41 CEST k8900e92b09583eec8c3932762fb57e17 104.9 MB drwxrwxrwx files:1 dirs:1 (latest-1)

두 번째 Kopia 저장소에서도 같은 상황을 볼 수 있습니다.

$ kopia repository connect azure --storage-account=puneptunetest --storage-key="<REDACTED>" --container=demo --prefix=$(k -n alpine get backup alpine-full-1 -o yaml | yq '.status.progress.volumeBackups[1].repositoryPath')
Enter password to open repository:

Connected to repository.

NOTICE: Kopia will check for updates on GitHub every 7 days, starting 24 hours after first use.
To disable this behavior, set environment variable KOPIA_CHECK_FOR_UPDATES=false
Alternatively you can remove the file "/Users/patricu/Library/Application Support/kopia/repository.config.update-info.json".

~$ kopia snapshot list --all
root@protect.trident.netapp.io:/sourceVolume
  2025-10-21 16:01:29 CEST k32e40ed699bc3e3d938c0ea65497f95f 104.9 MB drwxrwxrwx files:1 dirs:1 (latest-1)

이제 Alpine 컨테이너의 /data 디렉토리에 다른 파일을 추가하고 나중에 증분 백업을 실행하면 어떤 일이 일어나는지 살펴보겠습니다 .

$ kubectl -n alpine exec -it pod/alpine-6cd7c6fdf7-fm9dm -- ls -l /data /data2
/data:
total 205616
-rw-r--r--    1 nobody   nobody   104857600 Oct 21 13:41 file1
-rw-r--r--    1 nobody   nobody   104857600 Oct 21 14:13 file2

/data2:
total 102808
-rw-r--r--    1 nobody   nobody   104857600 Oct 21 13:46 file1

이제 또 다른 주문형 백업 alpine-inc-1 을 시작하는데 , –full-backup 플래그를 지정하지 않으면 증분 백업이 됩니다.

$ tridentctl-protect create backup alpine-inc-1 --app alpine --appvault demo -n alpine
Backup "alpine-inc-1" created.

$ tridentctl-protect get backup -n alpine
+---------------+--------+----------------+-----------+-------+-------+
|     NAME      |  APP   | RECLAIM POLICY |   STATE   | ERROR |  AGE  |
+---------------+--------+----------------+-----------+-------+-------+
| alpine-full-1 | alpine | Retain         | Completed |       | 2h45m |
| alpine-inc-1  | alpine | Retain         | Completed |       | 4m15s |
+---------------+--------+----------------+-----------+-------+-------+

알파인 네임스페이스 의 각 백업 옆에 전체 백업 주석을 나열해 보겠습니다 .

$ for i in $(k -n alpine get backups | awk '/alpine/ {print $1}'); do type=$(k -n alpine get backup ${i} -o yaml | yq '.metadata.annotations."protect.trident.netapp.io/full-backup"'); printf "${i}\t ${type} \n";done

alpine-full-1	 true
alpine-inc-1	 null

새로 생성된 백업 alpine-inc-1 에서 repositoryPath 값을 확인하면 값이 변경되지 않은 것을 알 수 있습니다( repositoryPath 이름 중간에 있는 타임스탬프 . ./kopia_<timestamp>/ 를 살펴보세요 ).

$ kubectl -n alpine get backup alpine-inc-1 -o yaml | yq '.status.progress.volumeBackups[].repositoryPath'
alpine_8ef17301-234c-4d48-b7c4-2809d592f125/kopia_20251021_140113/alpine/alpinedata_9601c314-f343-4894-927a-c5ad2ac59644/
alpine_8ef17301-234c-4d48-b7c4-2809d592f125/kopia_20251021_140113/alpine/alpinedata-2_95bd408e-b0c7-4b68-83d0-9d85dadb3e46/

증분 백업 데이터는 동일한 Kopia 저장소에 기록되었으며, Kopia 저장소를 다시 살펴보면 이를 확인할 수 있습니다. 첫 번째 Kopia 저장소에는 /data 에 다른 파일을 추가하여 두 번째 새 스냅샷이 생성되었습니다 .

$ kopia repository connect azure --storage-account=puneptunetest --storage-key="AUdQ0hKBW1xw6e6GwqxHGXuiEdrrrmWUY1Ft9E26yDx7dylKW/CUsbGG2/ff36RJ2K2PnAoHAUtC+AStgmsdiA==" --container=demo --prefix=$(k -n alpine get backup alpine-inc-1 -o yaml | yq '.status.progress.volumeBackups[0].repositoryPath')
Enter password to open repository:

Connected to repository.

NOTICE: Kopia will check for updates on GitHub every 7 days, starting 24 hours after first use.
To disable this behavior, set environment variable KOPIA_CHECK_FOR_UPDATES=false
Alternatively you can remove the file "/Users/patricu/Library/Application Support/kopia/repository.config.update-info.json".

~$ kopia snapshot list --all
root@protect.trident.netapp.io:/sourceVolume
  2025-10-21 16:01:41 CEST k8900e92b09583eec8c3932762fb57e17 104.9 MB drwxrwxrwx files:1 dirs:1 (latest-2)
  2025-10-21 18:42:47 CEST k00275f811aca280b34c4c9599c1a7278 209.7 MB drwxrwxrwx files:2 dirs:1 (latest-1)

두 번째 Kopia 저장소에는 /data2 디렉토리 에서 아무것도 변경하지 않았기 때문에 동일한 추가 스냅샷이 있습니다 .

$ kopia repository connect azure --storage-account=puneptunetest --storage-key="AUdQ0hKBW1xw6e6GwqxHGXuiEdrrrmWUY1Ft9E26yDx7dylKW/CUsbGG2/ff36RJ2K2PnAoHAUtC+AStgmsdiA==" --container=demo --prefix=$(k -n alpine get backup alpine-inc-1 -o yaml | yq '.status.progress.volumeBackups[1].repositoryPath')
Enter password to open repository:

Connected to repository.

NOTICE: Kopia will check for updates on GitHub every 7 days, starting 24 hours after first use.
To disable this behavior, set environment variable KOPIA_CHECK_FOR_UPDATES=false
Alternatively you can remove the file "/Users/patricu/Library/Application Support/kopia/repository.config.update-info.json".

~$ kopia snapshot list --all
root@protect.trident.netapp.io:/sourceVolume
  2025-10-21 16:01:29 CEST k32e40ed699bc3e3d938c0ea65497f95f 104.9 MB drwxrwxrwx files:1 dirs:1 (latest-1..2)
  + 1 identical snapshots until 2025-10-21 18:42:48 CEST

마지막 단계에서는 /data2 디렉토리에 새 파일을 추가한 후 전체 백업을 다시 실행해 보겠습니다.

$ kubectl -n alpine exec -it pod/alpine-6cd7c6fdf7-fm9dm -- ls -l /data /data2
/data:
total 205616
-rw-r--r--    1 nobody   nobody   104857600 Oct 21 13:41 file1
-rw-r--r--    1 nobody   nobody   104857600 Oct 21 14:13 file2

/data2:
total 205616
-rw-r--r--    1 nobody   nobody   104857600 Oct 21 13:46 file1
-rw-r--r--    1 nobody   nobody   104857600 Oct 22 07:56 file2

$ tridentctl-protect create backup alpine-full-2 --app alpine --appvault demo --full-backup -n alpine
Backup "alpine-full-2" created.

$ tridentctl-protect get backups -n alpine
+---------------+--------+----------------+-----------+-------+--------+
|     NAME      |  APP   | RECLAIM POLICY |   STATE   | ERROR |  AGE   |
+---------------+--------+----------------+-----------+-------+--------+
| alpine-full-1 | alpine | Retain         | Completed |       | 19h57m |
| alpine-full-2 | alpine | Retain         | Completed |       | 1h50m  |
| alpine-inc-1  | alpine | Retain         | Completed |       | 17h16m |
+---------------+--------+----------------+-----------+-------+--------+

$ printf "BACKUP \t\t FULL?\n"; for i in $(k -n alpine get backups | awk '/alpine/ {print $1}'); do type=$(k -n alpine get backup ${i} -o yaml | yq '.metadata.annotations."protect.trident.netapp.io/full-backup"'); printf "${i}\t ${type} \n";done
BACKUP 	 	 FULL?
alpine-full-1	 true
alpine-full-2	 true
alpine-inc-1	 null

두 번째 전체 백업 alpine-full-2 의 repositoryPath 값을 확인하면 새로운 Kopia 저장소가 생성된 것을 알 수 있습니다( repositoryPath 이름 중간에 있는 타임스탬프 ../kopia_<timestamp>/ 를 확인하세요 ).

$ kubectl -n alpine get backup alpine-full-2 -o yaml | yq '.status.progress.volumeBackups[].repositoryPath'
alpine_8ef17301-234c-4d48-b7c4-2809d592f125/kopia_20251022_080816/alpine/alpinedata_9601c314-f343-4894-927a-c5ad2ac59644/
alpine_8ef17301-234c-4d48-b7c4-2809d592f125/kopia_20251022_080816/alpine/alpinedata-2_95bd408e-b0c7-4b68-83d0-9d85dadb3e46/

새로운 Kopia 저장소에는 이제 Kopia 스냅샷이 하나씩 포함되어 있으며, 각 디렉토리 /data 및 /data2 에 있는 두 개의 데이터 파일을 보호합니다 .

$ kopia repository connect azure --storage-account=puneptunetest --storage-key="AUdQ0hKBW1xw6e6GwqxHGXuiEdrrrmWUY1Ft9E26yDx7dylKW/CUsbGG2/ff36RJ2K2PnAoHAUtC+AStgmsdiA==" --container=demo --prefix=$(k -n alpine get backup alpine-full-2 -o yaml | yq '.status.progress.volumeBackups[0].repositoryPath')
Enter password to open repository:

Connected to repository.

NOTICE: Kopia will check for updates on GitHub every 7 days, starting 24 hours after first use.
To disable this behavior, set environment variable KOPIA_CHECK_FOR_UPDATES=false
Alternatively you can remove the file "/Users/patricu/Library/Application Support/kopia/repository.config.update-info.json".

~$ kopia snapshot list --all
root@protect.trident.netapp.io:/sourceVolume
  2025-10-22 10:08:28 CEST k74861c2a36fa0237c7e601638b2d3b9f 209.7 MB drwxrwxrwx files:2 dirs:1 (latest-1)
$ kopia repository connect azure --storage-account=puneptunetest --storage-key="AUdQ0hKBW1xw6e6GwqxHGXuiEdrrrmWUY1Ft9E26yDx7dylKW/CUsbGG2/ff36RJ2K2PnAoHAUtC+AStgmsdiA==" --container=demo --prefix=$(k -n alpine get backup alpine-full-2 -o yaml | yq '.status.progress.volumeBackups[1].repositoryPath')
Enter password to open repository:

Connected to repository.

NOTICE: Kopia will check for updates on GitHub every 7 days, starting 24 hours after first use.
To disable this behavior, set environment variable KOPIA_CHECK_FOR_UPDATES=false
Alternatively you can remove the file "/Users/patricu/Library/Application Support/kopia/repository.config.update-info.json".

~$ kopia snapshot list --all
root@protect.trident.netapp.io:/sourceVolume
  2025-10-22 10:08:28 CEST kc054b7ac1b577b6d627bc28fd87d5177 209.7 MB drwxrwxrwx files:2 dirs:1 (latest-1)

예약된 백업

이제 Trident Protect에서 전체 주문형 백업이 어떻게 작동하는지 살펴보았으므로 Trident Protect의 스케줄러를 사용하여 예약된 백업을 위한 이 새로운 기능을 어떻게 활용할 수 있는지 살펴보겠습니다.

스케줄러를 사용하면 metadata.annotations.protect.trident.netapp.io/full-backup-rule 애노테이션을 사용하여 비증분 전체 백업을 예약 할 수 있습니다 . 기본적으로 모든 백업은 증분 백업입니다. 모든 백업 단위에 대해 지속적인 전체 백업을 수행하려면 Always으로 설정하고, 일별 단위의 경우 전체 백업을 수행할 요일( 월, 화, 수, 목, 금, 토, 일 )을 지정할 수 있습니다. Trident protect CLI를 사용하여 일정을 생성할 때 –full-backup-rule 플래그를 사용하여 백업 일정의 일별 단위를 사용하여 전체 백업을 수행할 요일을 지정하거나, 지속적인 전체 백업을 수행하려면 Always로 설정할 수 있습니다 .

tridentctl-protect를 사용하여 두 번째 샘플 애플리케이션 web 의 일일 백업 일정을 생성해 보겠습니다 . 일일 백업은 UTC 기준 12시 12분에 실행되고, 스케줄러가 최근 10개의 백업을 보관하면서 월요일, 수요일, 금요일, 일요일에 전체 백업을 생성하도록 설정하려고 합니다.

$ tridentctl-protect create schedule --app web --appvault demo --backup-retention 10 --granularity Daily --hour 12 --minute 12 --full-backup-rule "Monday,Wednesday,Friday,Sunday" -n web
Schedule "web-qfr01u" created.

새로 생성된 일정에 대한 kubectl describe 명령은 full-backup-rule 주석의 올바른 설정 을 보여 줍니다 .

$ kubectl -n web describe schedule web-qfr01u
Name:         web-qfr01u
Namespace:    web
Labels:       <none>
Annotations:  protect.trident.netapp.io/full-backup-rule: Monday,Wednesday,Friday,Sunday
API Version:  protect.trident.netapp.io/v1
Kind:         Schedule
Metadata:
  Creation Timestamp:  2025-10-16T08:51:51Z
  Generation:          1
  Owner References:
    API Version:     protect.trident.netapp.io/v1
    Kind:            Application
    Name:            web
    UID:             0a87fec1-1c9a-4ef4-bee2-9b94a3df5c62
  Resource Version:  12337070
  UID:               97f37f06-9c3e-4af6-8db0-9ba99b13eaf4
Spec:
  App Vault Ref:          demo
  Application Ref:        web
  Backup Retention:       10
  Data Mover:             Kopia
  Day Of Month:
  Day Of Week:
  Enabled:                true
  Granularity:            Daily
  Hour:                   12
  Minute:                 12
  Recurrence Rule:
  Replication Retention:  0
  Snapshot Retention:     0
Events:                <none>

2025년 10월 16일 목요일 첫 번째 백업 실행 후 다시 확인해 보겠습니다.

$ date
Thu Oct 16 14:46:07 CEST 2025
$ tridentctl-protect get backup -n web
+----------------------------+-----+----------------+-----------+-------+--------+
|            NAME            | APP | RECLAIM POLICY |   STATE   | ERROR |  AGE   |
+----------------------------+-----+----------------+-----------+-------+--------+
| daily-90652-20251016121200 | web | Retain         | Completed |       | 34m10s |
+----------------------------+-----+----------------+-----------+-------+--------+

이는 최초로 예약된 백업이므로 전체 백업 주석이 true 로 설정되지 않았 음에도 불구하고 암묵적으로 전체 백업입니다 .

$ kubectl -n web get backup daily-90652-20251016121200 -o yaml | yq '.metadata.annotations."protect.trident.netapp.io/full-backup"'
null

애플리케이션 웹에는 PV가 하나뿐이므로 초기 예약 백업을 위해 Kopia 저장소가 하나만 생성되었습니다.

$ kubectl -n web get backup daily-90652-20251016121200 -o yaml | yq '.status.progress.volumeBackups[].repositoryPath'
web_0a87fec1-1c9a-4ef4-bee2-9b94a3df5c62/kopia/web/nginxdata_1ff159f4-a3ea-45e5-bdb7-b0b5f3878466/

다음 주 금요일에 다시 확인해보니 금요일, 일요일, 월요일, 수요일, 그리고 금요일에 예정된 백업이 전체 백업이었고, 각 전체 백업이 새로운 Kopia 저장소에 기록되었습니다( 저장소 경로 이름 중간에 있는 타임스탬프 ../kopia_ <타임스탬프>/를 확인하세요 ).

$ tridentctl-protect get backup -n web
+----------------------------+-----+----------------+-----------+-------+--------+
|            NAME            | APP | RECLAIM POLICY |   STATE   | ERROR |  AGE   |
+----------------------------+-----+----------------+-----------+-------+--------+
| daily-90652-20251016121200 | web | Retain         | Completed |       | 8d     |
| daily-90652-20251017121200 | web | Retain         | Completed |       | 7d     |
| daily-90652-20251018121200 | web | Retain         | Completed |       | 6d     |
| daily-90652-20251019121200 | web | Retain         | Completed |       | 5d     |
| daily-90652-20251020121200 | web | Retain         | Completed |       | 4d     |
| daily-90652-20251021121200 | web | Retain         | Completed |       | 3d     |
| daily-90652-20251022121200 | web | Retain         | Completed |       | 2d     |
| daily-90652-20251023121200 | web | Retain         | Completed |       | 1d     |
| daily-90652-20251024121200 | web | Retain         | Completed |       | 37m29s |
+----------------------------+-----+----------------+-----------+-------+--------+

$ printf "BACKUP \t\t\t\t FULL? \t REPO \n"; for i in $(k -n web get backups | awk '/daily/ {print $1}'); do type=$(k -n web get backup ${i} -o yaml | yq '.metadata.annotations."protect.trident.netapp.io/full-backup"'); repo=$(k -n web get backup ${i} -o yaml | yq '.status.progress.volumeBackups[0].repositoryPath'); printf "${i}\t ${type}\t ${repo}\n"; done
BACKUP 				 FULL? REPO
daily-90652-20251016121200	 null	 web_0a87fec1-1c9a-4ef4-bee2-9b94a3df5c62/kopia/web/nginxdata_1ff159f4-a3ea-45e5-bdb7-b0b5f3878466/
daily-90652-20251017121200	 true	 web_0a87fec1-1c9a-4ef4-bee2-9b94a3df5c62/kopia_20251017_121216/web/nginxdata_1ff159f4-a3ea-45e5-bdb7-b0b5f3878466/
daily-90652-20251018121200	 null	 web_0a87fec1-1c9a-4ef4-bee2-9b94a3df5c62/kopia_20251017_121216/web/nginxdata_1ff159f4-a3ea-45e5-bdb7-b0b5f3878466/
daily-90652-20251019121200	 true	 web_0a87fec1-1c9a-4ef4-bee2-9b94a3df5c62/kopia_20251019_121213/web/nginxdata_1ff159f4-a3ea-45e5-bdb7-b0b5f3878466/
daily-90652-20251020121200	 true	 web_0a87fec1-1c9a-4ef4-bee2-9b94a3df5c62/kopia_20251020_121215/web/nginxdata_1ff159f4-a3ea-45e5-bdb7-b0b5f3878466/
daily-90652-20251021121200	 null	 web_0a87fec1-1c9a-4ef4-bee2-9b94a3df5c62/kopia_20251020_121215/web/nginxdata_1ff159f4-a3ea-45e5-bdb7-b0b5f3878466/
daily-90652-20251022121200	 true	 web_0a87fec1-1c9a-4ef4-bee2-9b94a3df5c62/kopia_20251022_121215/web/nginxdata_1ff159f4-a3ea-45e5-bdb7-b0b5f3878466/
daily-90652-20251023121200	 null	 web_0a87fec1-1c9a-4ef4-bee2-9b94a3df5c62/kopia_20251022_121215/web/nginxdata_1ff159f4-a3ea-45e5-bdb7-b0b5f3878466/
daily-90652-20251024121200	 true	 web_0a87fec1-1c9a-4ef4-bee2-9b94a3df5c62/kopia_20251024_121214/web/nginxdata_1ff159f4-a3ea-45e5-bdb7-b0b5f3878466/

결론

결론적으로, NetApp® Trident™ protect 25.06은 증분 백업과 함께 전체 백업을 예약할 수 있는 기능을 도입하여 쿠버네티스 애플리케이션 데이터 관리를 크게 향상시킵니다. 이 새로운 기능은 스토리지 효율성과 빠른 복구 시간 간의 균형을 제공하여 “영구 증분 백업” 전략의 문제점을 해결합니다. 온디맨드 및 예약된 전체 백업을 모두 활용함으로써 중요한 시스템의 강력한 데이터 보호와 신속한 복구를 보장할 수 있습니다.

이제 이러한 기능을 구현할 수 있는 지식을 갖추었으니, 실제로 구현해 볼 차례입니다! 이 가이드에 설명된 단계에 따라 Trident Protect를 사용하여 백업 전략을 설정하고 최적화하세요. 필수 구성 요소를 갖추고 Kubernetes 애플리케이션을 효과적으로 보호하기 위해 온디맨드 및 예약 백업을 생성하세요.

너무 늦을 때까지 기다리지 마세요. 지금 당장 Trident protect 25.06으로 데이터 보호 전략을 강화하세요!

자세한 지침과 예시는 Trident Protect 설명서를 참조하세요 . 궁금한 점이 있거나 추가 지원이 필요하시면 언제든지 지원팀에 문의하시거나 NetApp 커뮤니티 포럼에 참여해 주세요.

즐거운 백업 되세요!

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다

You May Also Like
Read More

B2B – What Happens When a NFS Share is Mounted

NetApp Tech Blog에 갔다가 흥미로운 주제의 글이 보여서 AI 번역(+약간 수정)의 힘을 빌려 읽어보았습니다. 출처: https://community.netapp.com/t5/Tech-ONTAP-Blogs/B2B-What-Happens-When-a-NFS-Share-is-Mounted/ba-p/462010 “Back to…
Read More

NVM Express Explained

왜 NVM Express인가? 그림 1에서 볼 수 있듯이 DRAM과 하드 드라이브의 가격 대비 성능 격차가 점점 더 커지고…
Read More

SAN 관련 교육 및 TR 정리

SAN(AFF, ASA 포함)과 관련해서 NetApp Learning Services에서 제공하는 교육을 정리해 보았습니다. 무료 교육 과정 NetApp LearningCenter의 홈페이지에서 “Start…