Back Up Encrypted ZFS Data without Unlocking It

Michael Lynch

잠금 해제 없이 암호화된 ZFS 데이터 백업하기

원문은 Michael Lynch님이 에 게재했습니다. 이 블로그 구독하기

최근에 첫 홈 TrueNAS 서버를 구축했다. 개인 데이터와 업무 데이터 대부분을 이 서버에 저장하고 있어, TrueNAS와 그 파일 시스템인 ZFS를 최대한 활용하는 방법을 배우고 있다.

오늘은 암호화된 데이터를 백업하는 방법에 대해 이야기해보려 한다.

소매 패키지에 담긴 NAS 서버 부품 사진완성된 서버 조립 사진

홈랩 TrueNAS 서버

ZFS의 멋진 기능 중 하나는 암호화된 데이터를 암호화된 상태 그대로 백업할 수 있다는 것이다. 까다로운 점은 TrueNAS가 오직 다른 TrueNAS 시스템으로만 백업한다고 가정한다는 것이다. 나처럼 암호화된 데이터를 일반 클라우드 스토리지 제공업체에 백업하고 싶다면 추가 작업이 필요하다. 오늘 포스트에서 그 방법을 보여주겠다.

왜 암호화된 데이터를 백업해야 할까?

자주 접근하지는 않지만 암호화된 데이터셋에 보관하고 싶은 파일들이 있다.

이전에 쓰던 Synology NAS에서는 암호화된 볼륨을 백업할 방법이 전혀 없었다. 데이터가 암호화되면 잠금을 해제하기 전까지는 어떤 것도 접근할 수 없었다. 대부분의 데이터는 괜찮지만, 자주 접근하지 않는 볼륨은 어떻게 해야 할까? 매일 밤 실행되는 백업이 클라우드 스토리지로 복제하지 못하게 된다.

TrueNAS는 다르다! 데이터셋이 암호화되어 잠겨 있어도 전체 백업과 증분 백업을 만들 수 있다. 자주 접근하지 않는 데이터를 굳이 복호화된 상태로 유지하지 않고도 백업할 수 있는 좋은 방법처럼 보였다.

나는 resticresticpy를 이용해 데이터를 클라우드 스토리지에 백업하므로, restic이 암호화된 ZFS 백업에 접근할 방법이 필요했다. 약간의 시행착오와 수동 bash 스크립트 작업을 거쳐 결국 성공했다.

TrueNAS에서 암호화된 데이터셋 백업 시도하기 (잘못된 방법)

내가 하려는 작업을 보여주기 위해 diary-entries라는 데이터셋을 만들었다.

TrueNAS의 diary-entries 데이터셋 스크린샷

자, 이 데이터셋에 파일을 하나 넣어보자:

echo "I enjoy Taylor Swift, but I don't want anyone to know" 
  > /mnt/pool1/diary-entries/2022-07-05.txt

그리고 백업을 받을 diary-entries-backup이라는 새 데이터셋을 만들어야 한다. 이미 암호화된 백업 위에 또 암호화를 덧씌울 필요는 없으므로 이 새 데이터셋에서는 암호화를 비활성화했다:

암호화가 비활성화된 TrueNAS 데이터셋 생성 화면 스크린샷

이제 diary-entries 데이터셋의 암호화된 스냅샷을 암호화되지 않은 diary-entries-backup 데이터셋으로 백업하는 복제 작업을 설정할 준비가 됐다. 그러면 restic이 diary-entries-backup 데이터셋에 접근해 클라우드 스토리지로 복제할 수 있다.

복제 작업을 만들자 TrueNAS가 암호화된 데이터셋을 복제하고 있다는 경고를 표시한다. 괜찮다 — 정확히 내가 원하던 것이다. 암호화된 스냅샷을 그대로 암호화된 상태로 클라우드에 백업하고 싶다:

TrueNAS 경고: 다음 암호화된 데이터셋을 복제하고 있습니다: 'pool1/diary-entries'. 대상 데이터셋은 잠기며 원본 데이터셋의 암호화 키로 잠금을 해제할 수 있습니다

복제 작업을 시작했는데… 실패한다:

암호화된 데이터셋 'pool1/diary-entries'를 기존의 암호화되지 않았거나 관련 없는 데이터셋 'pool1/diary-entries-backup'으로 전송할 수 없습니다.

오류 내용은 다음과 같다:

Unable to send encrypted dataset ‘pool1/diary-entries’ to existing unencrypted or unrelated dataset ‘pool1/diary-entries-backup’.

이런!

암호화된 데이터셋을 암호화되지 않은 데이터셋으로 복제할 수 없게 한다. 스냅샷 자체가 암호화되어 잠겨 있는데, 그게 암호화된 데이터셋 위에 있든 아니든 무슨 상관이람 싶어 좀 어이없었다.

참고: 이 방법이 동작하지 않은 이유는 ZFS 복제에 대한 내 이해가 잘못됐기 때문이었다. 올바른 개념은 뒤에서 설명하겠다.

커맨드라인 인터페이스로 ZFS 사용하기

TrueNAS는 기본적으로 ZFS를 감싸는 친절한 UI다. 일을 더 쉽게 하기 위해 TrueNAS를 건너뛰고 ZFS의 더 강력한 커맨드라인 인터페이스(CLI)를 직접 사용했다.

ZFS 문서에는 데이터셋을 복제하는 예제 명령어가 나와 있다:

zfs send pool/fs@a | zfs receive poolB/received/fs@a

@a는 이름이 a인 스냅샷을 의미하므로, 2022-07-05라는 이름의 스냅샷을 만들겠다:

zfs snapshot pool1/diary-entries@2022-07-05

그리고 diary-entriesdiary-entries-backup으로 복제해보겠다:

$ zfs send pool1/diary-entries@2022-07-05 \
  | zfs receive pool1/diary-entries-backup
cannot receive new filesystem stream: destination 'pool1/diary-entries-backup' exists
must specify -F to overwrite it

그럼 기존 데이터셋으로는 복제할 수 없다는 건가? 그냥 새 데이터셋 이름인 diary-entries-backup2를 지정해보자:

$ zfs send pool1/diary-entries@2022-07-05 \
  | zfs receive pool1/diary-entries-backup
warning: cannot send 'pool1/diary-entries@2022-07-05': dataset key must be loaded
cannot receive: failed to read from stream

그럼 diary-entries가 복호화되지 않으면 복제를 거부한다는 건가? 암호화된 데이터셋을 복제할 수 있다고 생각했는데…

ZFS 문서를 다시 보니 --raw 플래그가 있다:

-w, --raw 암호화된 데이터셋의 경우, 디스크에 존재하는 그대로 데이터를 전송합니다.

좋아, 한번 시도해보자:

$ zfs send --raw pool1/diary-entries@2022-07-05 \
  | zfs receive pool1/diary-entries-backup2

성공!

TrueNAS 웹 UI로 돌아가서 뭘 만들었는지 확인해보자:

TrueNAS에서 암호화된 데이터셋으로 표시된 diary-entries-backup2 스크린샷

아, 이건 내가 원하던 게 아니었다.

ZFS가 또 다른 암호화된 데이터셋을 만들었다. 내가 원하는 건 암호화되지 않은 데이터셋 위에 있는 암호화된 백업 파일인데. ZFS는 그런 방법을 제공하지 않는 것 같았다.

깨달음: 출력을 파일로 리다이렉트할 수 있다

ZFS 복제 명령어를 다시 살펴보다가 뭔가를 깨달았다:

$ zfs send --raw pool1/diary-entries@2022-07-05 \
  | zfs receive pool1/diary-entries-backup2

그러니까 zfs send 명령어가 출력을 zfs receive 명령어로 파이프하는 구조다. 출력을 zfs receive로 파이프하는 대신 그냥 파일로 쓰면 어떨까?

$ zfs send --raw pool1/diary-entries@2022-07-05 \
  > /mnt/pool1/diary-entries-backup/snapshot@2022-07-05

오, 됐다! 암호화되지 않은 diary-entries-backup 데이터셋에 24KB짜리 백업 파일을 만들었다:

$ du -h /mnt/pool1/diary-entries-backup/*
24K    /mnt/pool1/diary-entries-backup/snapshot@2022-07-05

이제 암호화되지 않은 데이터셋에 파일 형태로 백업이 있으니, restic이 다른 파일처럼 클라우드로 백업할 수 있다.

하지만 먼저 zfs receive 명령어를 이용해 이 백업으로부터 diary-entries의 데이터를 복원할 수 있는지 테스트해보자:

$ zfs receive pool1/diary-entries-backup3 \
  < /mnt/pool1/diary-entries-backup/snapshot@2022-07-05

성공했고 풀에 새 데이터셋이 생성됐다:

암호화된 데이터셋으로 표시된 diary-entries-backup3 스크린샷

두근거리는 순간이다! diary-entries에 썼던 것과 같은 비밀번호로 diary-entries-backup3를 복호화했을 때 동일한 데이터가 들어 있다면, diary-entries-backup/snapshot@2022-07-05 파일이 스냅샷 2022-07-05 시점의 diary-entries 데이터셋에 대한 완전한 백업이라는 걸 알 수 있다.

그래서 같은 비밀번호로 diary-entries-backup3를 복호화하고 내용을 확인했다:

$ cat /mnt/pool1/diary-entries-backup3/2022-07-05.txt
I enjoy Taylor Swift, but I don’t want anyone to know

만세! 성공했다.

암호화된 데이터셋을 한 번도 잠금 해제하지 않고도 암호화된 백업 파일을 성공적으로 만들 수 있다.

증분 백업 만들기

이런 방식으로 백업하려는 데이터셋 중 하나는 스크린캐스트 영상 캡처용이다. 현재 12GB 정도이고 앞으로 더 커질 가능성이 크다. 매일 백업한다면 매일 12GB짜리 새 파일이 생기는 건 원치 않는다.

다행히 ZFS는 증분 백업을 지원한다. 월요일에 데이터셋 스냅샷을 만들고 화요일에 또 만들었다면, 월요일과 화요일 모두에 대해 전체 백업 파일을 만들 필요가 없다. 대신 화요일 백업은 월요일 대비 변경분만 담으면 된다.

보여주기 위해 diary-entries 데이터셋에 데이터를 조금 더 추가하겠다:

echo "Upon reflection, I'm not ashamed of how much I enjoy You Belong with Me" \
  > /mnt/pool1/diary-entries/2022-07-06.txt

그리고 최신 항목이 포함된 새 스냅샷을 만들겠다:

zfs snapshot pool1/diary-entries@2022-07-06

마지막으로 -i 플래그로 기준 스냅샷을 지정해 2022-07-05 스냅샷을 기준으로 증분 백업을 만들겠다:

zfs send \
  --raw \
  --verbose \
  -i pool1/diary-entries@2022-07-05 \
  pool1/diary-entries@2022-07-06 \
  > /mnt/pool1/diary-entries-backup/snapshot@2022-07-05-to-2022-07-06

성공! 명령어가 새로운 증분 백업을 만들었다:

$ du -h /mnt/pool1/diary-entries-backup/*
 24K    /mnt/pool1/diary-entries-backup/snapshot@2022-07-05
6.5K    /mnt/pool1/diary-entries-backup/snapshot@2022-07-05-to-2022-07-06

이 데모에서는 파일이 어차피 너무 작아서 좀 우습지만, 두 번째 스냅샷이 첫 번째보다 훨씬 작은 걸 볼 수 있다. 2022-07-05 스냅샷 이후 변경된 내용만 담고 있기 때문이다.

백업으로부터 원본 데이터를 복원해야 테스트가 완료되므로, 증분 백업을 이용해 새 데이터셋을 만들어보겠다:

# Recover from full backup.
zfs receive pool1/diary-entries-backup4@2022-07-05 \
  < /mnt/pool1/diary-entries-backup/snapshot@2022-07-05
# Add changes since incremental backup.
zfs receive pool1/diary-entries-backup4 \
  < /mnt/pool1/diary-entries-backup/snapshot@2022-07-05-to-2022-07-06

복원에 성공했다!

암호화된 데이터셋으로 표시된 diary-entries-backup4 스크린샷

그리고 두 파일 모두 잘 있다:

$ tail -n +1 /mnt/pool1/diary-entries-backup4/*
==> /mnt/pool1/diary-entries-backup4/2022-07-05.txt <==
I enjoy Taylor Swift, but I don't want anyone to know

==> /mnt/pool1/diary-entries-backup4/2022-07-06.txt <==
Upon reflection, I'm not ashamed of how much I enjoy Blank Space

먼저 전체 백업으로부터 복원한 뒤 증분 백업으로 업데이트해야 한다는 점에 유의하자. 증분 백업으로 바로 복원을 시도하면 ZFS가 오류를 내며 실패한다:

# This isn't going to work because it's an incremental backup.
$ zfs receive pool1/diary-entries-backup5 \
  < /mnt/pool1/diary-entries-backup/snapshot@2022-07-05-to-2022-07-06
cannot receive incremental stream: destination 'pool1/diary-entries-backup5' does not exist

백업 스크립트 작성하기

이제 ZFS로 데이터셋을 복제하는 원리를 이해했으니, 반복적인 백업 작업을 자동화할 수 있도록 셸 스크립트를 만들 차례다.

먼저 내 시스템에 특화된 내용을 정의하기 위해 settings.sh라는 파일을 만들겠다:

readonly POOL="mypool"
readonly BASE_DIR="/mnt/${POOL}/encrypted-backups"
readonly FULL_SNAPSHOTS_DIR="${BASE_DIR}/full-snapshots"
readonly INCREMENTAL_SNAPSHOTS_DIR="${BASE_DIR}/incremental-snapshots"

DATASETS=()
DATASETS+=("documents")
DATASETS+=("music")
DATASETS+=("emails")
readonly DATASETS

이제 데이터셋의 전체 백업을 만드는 replicate-full-snapshots.sh라는 스크립트를 만들겠다:

#!/bin/bash

# Create full snapshots of datasets in DATASETS array.

set -eux

. settings.sh

mkdir -p "${FULL_SNAPSHOTS_DIR}"

TIMESTAMP="$(date -Iseconds | sed 's/://g' | sed 's/+0000/Z/g')"
readonly TIMESTAMP

for DATASET in "${DATASETS[@]}"; do
  # Take a snapshot.
  SNAPSHOT_NAME="${POOL}/${DATASET}@${TIMESTAMP}"
  zfs snapshot "${SNAPSHOT_NAME}"

  # Write the snapshot to a file.
  OUTPUT_FILENAME="${SNAPSHOT_NAME//${POOL}\/}"
  zfs send --raw --verbose "${SNAPSHOT_NAME}" > "${FULL_SNAPSHOTS_DIR}/${OUTPUT_FILENAME}"
done

이 스크립트는 settings.sh에서 정의한 각 데이터셋을 순회하면서 각각의 새 스냅샷을 만들고, 각 스냅샷의 전체 백업을 생성한다.

다음으로 증분 백업을 만드는 replicate-incremental-snapshots.sh라는 스크립트를 만들겠다:

#!/bin/bash

# Create incremental snapshots of datasets in DATASETS array relative to their
# last full snapshot.

set -eux

. settings.sh

mkdir -p "${INCREMENTAL_SNAPSHOTS_DIR}"

TIMESTAMP="$(date -Iseconds | sed 's/://g' | sed 's/+0000/Z/g')"
readonly TIMESTAMP

for DATASET in "${DATASETS[@]}"; do
  # Take a snapshot.
  INCREMENTAL_SNAPSHOT="${POOL}/${DATASET}@${TIMESTAMP}"
  zfs snapshot "${INCREMENTAL_SNAPSHOT}"

  # Find the most recent full snapshot.
  BASE_SNAPSHOT_FILENAME="$(basename "$(ls -tr "${FULL_SNAPSHOTS_DIR}/${DATASET}"* | tail -1)")"
  BASE_SNAPSHOT="${POOL}/${BASE_SNAPSHOT_FILENAME}"

  # Write the incremental snapshot to a file.
  OUTPUT_FILENAME="${INCREMENTAL_SNAPSHOT//${POOL}\/}"
  OUTPUT_PATH="${INCREMENTAL_SNAPSHOTS_DIR}/${OUTPUT_FILENAME}"
  zfs send --raw --verbose -i "${BASE_SNAPSHOT}" "${INCREMENTAL_SNAPSHOT}" \
    > "${OUTPUT_PATH}"
done

replicate-incremental-snapshots.sh는 각 데이터셋의 가장 최근 전체 백업을 찾아 그것을 기준으로 증분 백업을 만든다.

replicate-incremental-snapshots.sh는 단순함을 위해 디스크 공간을 다소 낭비한다. 항상 마지막 전체 백업을 기준으로 증분 백업을 만들고, 더 최근의 증분 백업은 무시한다. 즉 월요일에 전체 백업을 만들고 이후 5일 동안 증분 백업을 만들면, 수요일 백업에 화요일 백업의 중복 데이터가 포함될 가능성이 있어 공간이 낭비된다. 증분 백업 위에 또 증분 백업을 쌓는 방식도 고려했지만, 백업 시스템에서 감수하고 싶지 않을 만큼 복잡성과 실수 가능성이 커진다.

마지막으로, 복원할 수 없으면 백업도 무용지물이므로 백업 파일을 다시 ZFS 데이터셋으로 변환하는 편의 스크립트 snapshot-to-dataset.sh를 만들었다:

#!/bin/bash
#
# Recover a dataset from an encrypted snapshot.
#
# Usage:
#   ./snapshot-to-dataset.sh new-dataset-name full-snapshot-path [incremental-snapshot-path]

set -ex

. settings.sh

NEW_DATASET_NAME="$1"
readonly NEW_DATASET_NAME

FULL_SNAPSHOT_PATH="$2"
readonly FULL_SNAPSHOT_PATH

INCREMENTAL_SNAPSHOT_PATH="$3"
readonly INCREMENTAL_SNAPSHOT_PATH

set -u

# Restore from base snapshot
zfs receive "${POOL}/${NEW_DATASET_NAME}" < "${FULL_SNAPSHOT_PATH}"

if [[ -n "${INCREMENTAL_SNAPSHOT_PATH}" ]]; then
  # Update dataset to latest incremental snapshot
  zfs receive "${POOL}/${NEW_DATASET_NAME}" < "${INCREMENTAL_SNAPSHOT_PATH}"
fi

이 스크립트들은 GitHub에서 확인할 수 있다:

편의 스크립트 실행해보기

내 스크립트가 어떻게 동작하는지 보여주기 위해 diary-entries 예제 데이터셋으로 시연해보겠다:

settings.sh 파일은 다음과 같다:

readonly POOL="pool1"
readonly BASE_DIR="/mnt/${POOL}/secure-backups"
readonly FULL_SNAPSHOTS_DIR="${BASE_DIR}/full-snapshots"
readonly INCREMENTAL_SNAPSHOTS_DIR="${BASE_DIR}/incremental-snapshots"

DATASETS=()
DATASETS+=("diary-entries")
readonly DATASETS

이제 전체 백업을 실행해보자:

./replicate-full-snapshots.sh

제대로 됐을까?

$ du -h /mnt/pool1/secure-backups/full-snapshots/diary-entries*
24K    /mnt/pool1/secure-backups/full-snapshots/diary-entries@2022-07-27T073416-0400

좋다, 예상대로 백업 파일이 생성됐다.

이제 새 데이터를 추가하겠다:

echo "I've got a blank space, so I'll write a new diary entry" \
  > /mnt/pool1/diary-entries/2022-07-27.txt

다음으로 2022-07-27.txt가 포함된 증분 백업을 만들겠다:

./replicate-incremental-snapshots.sh

이제 incremental-snapshots 폴더에 새 파일이 생겼을 것이다:

$ du -h /mnt/pool1/secure-backups/incremental-snapshots/diary-entries*
12K    /mnt/pool1/secure-backups/incremental-snapshots/diary-entries@2022-07-27T074246-0400

그리고 이 백업으로부터 복원할 수 있는지 확인해보자. 내 snapshot-to-dataset.sh 스크립트의 사용법은 다음과 같다는 걸 기억하자:

./snapshot-to-dataset.sh new-dataset-name full-backup-file [incremental-backup-file]

이를 이용해 백업으로부터 복원을 시도해보겠다:

./snapshot-to-dataset.sh \
  diary-entries-backup5 \
  /mnt/pool1/secure-backups/full-snapshots/diary-entries@2022-07-27T073416-0400 \
  /mnt/pool1/secure-backups/incremental-snapshots/diary-entries@2022-07-27T074246-0400

성공! 모든 파일이 포함된 새 데이터셋이 생성됐다:

tail -n +1 /mnt/pool1/diary-entries-backup5/*
==> /mnt/pool1/diary-entries-backup5/2022-07-05.txt <==
I enjoy Taylor Swift, but I don't want anyone to know

==> /mnt/pool1/diary-entries-backup5/2022-07-06.txt <==
Upon reflection, I'm not ashamed of how much I enjoy Blank Space

==> /mnt/pool1/diary-entries-backup5/2022-07-27.txt <==
I've got a blank space, so I'll write a new diary entry

백업 스케줄링

이제 백업을 스크립트로 만들었으니 정기적으로 실행할 예약 작업을 만들 수 있다. 다행히 TrueNAS 웹 UI에서 쉽게 할 수 있어 Tasks > Cron Jobs에서 작업을 생성하면 된다.

첫 번째 cron 작업은 전체 백업을 생성하는 월간 작업이다:

TrueNAS의 Cron 작업, 명령어 '/mnt/pool1/secure-backups/scripts/replicate-full-snapshots.sh' 및 일정 '0 0 3 * *'

매월 1일 오전 3시에 시작하도록 예약했다. 그 시간이 내가 가장 확실하게 잠들어 있을 때이기 때문이다.

다음으로 월간 스냅샷을 기준으로 증분 백업을 만드는 일일 작업을 원한다. 오전 3시의 전체 백업이 끝날 시간을 주기 위해 오전 4시에 시작하도록 하겠다:

TrueNAS의 Cron 작업, 명령어 '/mnt/pool1/secure-backups/scripts/replicate-incremental-snapshots.sh' 및 일정 '0 0 4 * *'

cron 작업이 성공적으로 실행되고 있는지 확인하려면 /var/log/cron의 로그를 확인하면 된다:

$ tail /var/log/cron
Jul 28 05:45:03 truenas 1 2022-07-28T08:45:03.757011-04:00 truenas.local cron 302 - - + OUTPUT_PATH=/mnt/pool1/secure-backups/incremental-snapshots/videos@2022-07-28T084502-0400
Jul 28 05:45:03 truenas 1 2022-07-28T08:45:03.757087-04:00 truenas.local cron 302 - - + [[ -f /mnt/pool1/secure-backups/incremental-snapshots/videos@2022-07-28T084502-0400 ]]
Jul 28 05:45:03 truenas 1 2022-07-28T08:45:03.757168-04:00 truenas.local cron 302 - - + zfs send --raw --verbose -i pool1/videos@2022-07-28T080351-0400 pool1/videos@2022-07-28T084502-0400
Jul 28 05:45:03 truenas 1 2022-07-28T08:45:03.761156-04:00 truenas.local cron 302 - - send from pool1/videos@2022-07-28T080351-0400 to pool1/videos@2022-07-28T084502-0400 estimated size is 624B
Jul 28 05:45:03 truenas 1 2022-07-28T08:45:03.761291-04:00 truenas.local cron 302 - - total estimated size is 624
Jul 28 05:45:03 truenas 1 2022-07-28T08:45:03.761877-04:00 truenas.local cron 302 - - + echo 'Finished replicating incremental snapshots'
Jul 28 05:45:03 truenas 1 2022-07-28T08:45:03.761958-04:00 truenas.local cron 302 - - Finished replicating incremental snapshots

백업 실패 알림

두 달 뒤에 백업이 실패하기 시작하면 어떻게 될까? 매일 로그를 들여다보며 백업이 잘 되고 있는지 확인할 수는 없다.

다행히 예약된 작업이 실행되지 않을 때 알려주는 다양한 서비스가 있다. 나는 무료 플랜이 넉넉하고 설정이 쉬운 Cronitor를 사용하기로 했다.

Cronitor에서 TrueNAS 서버의 전체 백업 일정과 동일한 0 0 3 * * 일정으로 새 모니터를 만들었다:

이름이 truenas-full-backups이고 일정이 0 0 3 * *인 새 Cronitor 모니터

Cronitor는 이 모니터에 대해 다음과 같은 고유 URL을 생성한다:

https://cronitor.link/p/88e0dba70a87424b83c5fd3e9227ac92/1bBG6q

전체 백업 cron 작업이 성공을 보고하도록, 백업이 성공적으로 완료되면 Cronitor에 성공 신호를 보내는 curl 명령어를 cron 작업에 추가한다:

/mnt/pool1/secure-backups/scripts/replicate-full-snapshots.sh && curl --silent https://cronitor.link/p/[my telemetry id]?state=complete

증분 백업 작업에도 같은 과정을 반복하면 끝이다!

이제 암호화된 ZFS 데이터셋의 백업을 만드는 견고한 시스템을 갖추었고, 작업이 실패하면 Cronitor로부터 알림을 받게 된다.

주의: 암호화 루트를 백업하세요

ZFS를 다른 ZFS 시스템이 아닌 파일로 백업할 때의 중요한 함정을 댓글에서 지적해준 @Invisible@adamkf에게 감사드린다.

항상 데이터셋의 암호화 루트를 백업하라.

암호화된 데이터셋의 하위 데이터셋을 백업하는 경우, 하위 데이터셋에 대한 zfs send는 다른 TrueNAS 시스템에서 스냅샷을 복원하는 데 필요한 모든 데이터를 담지 못하므로 백업이 무용지물이 된다.

데이터셋의 암호화 루트를 확인하려면 zfs get -r encryptionroot pool/dataset를 실행하면 된다. 데이터셋에 부모 암호화가 없으면 해당 데이터셋 자체가 암호화 루트임을 보여주는 출력이 나타난다:

$ zfs get -r encryptionroot pool1/diary-entries | head -n 2
NAME                                     PROPERTY        VALUE                SOURCE
pool1/diary-entries                      encryptionroot  pool1/diary-entries  -

데이터셋 자체가 암호화 루트인 경우에는 추가로 백업해야 할 데이터셋이 없다.

스냅샷 파일로부터 실제로 복원할 수 있는지 검증하기 위해 별도의 ZFS 시스템, 심지어 TrueNAS VM에서도 백업을 테스트해보기를 권장한다.

소스 코드

편의 스크립트를 GitHub에 공개해 두었다:

이 글은 muse-spark-1.2-contributor 모델을 사용해 번역했습니다.

댓글