VeleroでPVを含むKubernetesのバックアップを取得してみた(実践手順付き)

この記事は[NTTコムウェア Advent Calendar 2023](https://qiita.com/advent-calendar/2023/nttcomware) 3日目の記事です。

こんにちは。NTTコムウェアの土井と申します。
業務でKubernetesを触り始めて２年半くらいになります。
みなさんは、Kubernetesのバックアップはどうされていますか？
私には、PVを含むKubernetesリソースのバックアップが必要になったことがあります。
巷には、Kubernetesでもバックアップは必要ですよ。といった投稿があったりもしますが、クラスタ丸っととか、etcdのバックアップといった、いざというときの基盤運用者のための備え的な投稿が多い印象がありました。
このような経緯から、Kubernetesリソースのバックアップが必要な環境で、特定のKubernetesリソースをピンポイントでバックアップを取るという使い方をVeleroを用いて実現していることと、Velero使っての苦労や心構えを紹介させていただきます。

## 前提
+ 本記事は、Kubernetes及びAzureの基礎的な知識を前提とします。

## 環境
| コンポーネント                     | バージョン |
| ---------------------------------- | ---------- |
| Azure Kubernetes Service (AKS)     | 1.25.6     |
| Velero                             | 1.11.0     |
| Velero plugins for Microsoft Azure | 1.7.0      |

## Veleroのセットアップ手順
詳細については、VeleroのAzureプラグインのREADMEに記載がありますので、ご確認ください。私たちは、helmを使ってVeleroをインストールしています。
+ https://github.com/vmware-tanzu/velero-plugin-for-microsoft-azure

1. マニフェストバックアップ用のストレージを作成する。
1. 永続領域用ディスクの格納リソースグループを取得する。
1. Velero用のEntra IDアプリを作成し、ロールをアサインする。
1. Veleroをインストールする

## Veleroでバックアップを取得してみる
それでは、実際に、バックアップを取得してみます。

+ まずは、テスト用のリソースを作成します。
ポイントは、バックアップを取得したいリソースに、「velero: debug」のようなlabelを付与しておくことです。

```bash
$ cat <<EOF | kubectl create -f -
---
apiVersion: v1
kind: Namespace
metadata:
  name: backup-test
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: test
  namespace: backup-test
  labels:
    velero: debug
spec:
  replicas: 1
  selector:
    matchLabels:
      velero: debug
  template:
    metadata:
      labels:
        velero: debug
    spec:
      containers:
      - name: test
        image: 'alpine:latest'
        command: ["/bin/ash", "-c", "while true; do sleep 3600; done"]
        volumeMounts:
        - mountPath: "/home/tmp"
          name: tmp-volume
      volumes:
      - name: tmp-volume
        persistentVolumeClaim:
          claimName: tmp-volume
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: tmp-volume
  namespace: backup-test
  labels:
    velero: debug
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1024Mi
EOF

```

+ 作成が完了したら、永続領域に、書き込みを行います。

```bash
$ POD_NAME=$(kubectl get pod -n backup-test \
    -o jsonpath={.items..metadata.name}) && \
    echo "POD_NAME=${POD_NAME}"
$ kubectl exec -it $POD_NAME -n backup-test \
    -- sh -c "echo 'velero test' > /home/tmp/test.txt; sync; ls -l /home/tmp"
```

+ 永続領域への書き込みができたら、実際にバックアップを取得してみます。
さらに、バックアップの取得が成功していることも確認します。

```bash
$ velero backup create test-backup --selector velero=debug

# STATUSがCompletedであることを確認する
$ velero backup get
NAME          STATUS      ERRORS   WARNINGS   CREATED                         EXPIRES   STORAGE LOCATION   SELECTOR
test-backup   Completed   0        0          2023-11-21 10:27:06 +0900 JST   29d       default            velero=debug
```

+ バックアップが取得できていることを確認できたら、リストア対象リソースを削除します。
`NOTE`：Veleroのリストアはリソースが削除されていることが前提です。

```bash
$ kubectl delete -n backup-test \
    deployment/test \
    pvc/tmp-volume
```

+ さらに、バックアップの実態の確認も可能です。
インストール時に作成した、ストレージアカウントの中に、マニフェストのバックアップが格納されています。
また、永続領域用ディスク（Azure Diskというリソース）の格納リソースグループ内に、Azure Snapshotというリソースで永続領域用ディスクのバックアップが取得されています。

```bash
NAME                                                                CTIME
------------------------------------------------------------------  -------------------------
backups/test-backup/test-backup-csi-volumesnapshotclasses.json.gz   2023-11-21T01:27:13+00:00
backups/test-backup/test-backup-csi-volumesnapshotcontents.json.gz  2023-11-21T01:27:13+00:00
backups/test-backup/test-backup-csi-volumesnapshots.json.gz         2023-11-21T01:27:13+00:00
backups/test-backup/test-backup-itemoperations.json.gz              2023-11-21T01:27:13+00:00
backups/test-backup/test-backup-logs.gz                             2023-11-21T01:27:13+00:00
backups/test-backup/test-backup-podvolumebackups.json.gz            2023-11-21T01:27:13+00:00
backups/test-backup/test-backup-resource-list.json.gz               2023-11-21T01:27:13+00:00
backups/test-backup/test-backup-results.gz                          2023-11-21T01:27:13+00:00
backups/test-backup/test-backup-volumesnapshots.json.gz             2023-11-21T01:27:13+00:00
backups/test-backup/test-backup.tar.gz                              2023-11-21T01:27:13+00:00
backups/test-backup/velero-backup.json                              2023-11-21T01:27:13+00:00
```

```bash
NAME                                                                           CTIME
-----------------------------------------------------------------------------  --------------------------------
pvc-213bf84b-7171-4827-ae2c-8c239012d2e4-c8d5c2be-4bce-494e-91d3-4ea710da542f  2023-11-21T01:27:10.907441+00:00
```

+ では、実際にリストアをしてみます。リストアが完了したことを確認します。

```bash
$ velero restore create test-restore --from-backup  test-backup
$ velero restore get
NAME           BACKUP        STATUS      STARTED                         COMPLETED                       ERRORS   WARNINGS   CREATED                         SELECTOR
test-restore   test-backup   Completed   2023-11-21 10:34:45 +0900 JST   2023-11-21 10:34:49 +0900 JST   0        0          2023-11-21 10:34:45 +0900 JST   <none>
```

+ 永続領域に書き込んだデータが復元されているか確認します。
確かに書き込んだデータが復元されています。
私たちは、statefulsetとPVCなどを主にバックアップ取得するようにVeleroを使用しています。

```bash
$ POD_NAME=$(kubectl get pod -n backup-test \
    -o jsonpath={.items..metadata.name}) && \
    echo "POD_NAME=${POD_NAME}"
$ kubectl exec -it $POD_NAME -n backup-test \
    -- sh -c "ls -l /home/tmp; cat /home/tmp/test.txt"
# 出力結果
total 20
drwx------    2 root     root         16384 Apr 11 05:47 lost+found
-rw-r--r--    1 root     root            12 Apr 11 06:34 test.txt
velero test     # バックアップした内容がリストアされたことを確認する

```

## Veleroを運用していて経験した苦労
AKSとVeleroを運用していて、経験した苦労についても記載させてください。

### AKSのdefaultのStorageClassが変更になった
+ AKS 1.20から1.21にバージョンアップした際にdefaultのStorageClassが```Kubernetes.io/azure-disk```から```disk.csi.azure.com```に変更となりました。
+ しかし、Velero 1.7.0が```disk.csi.azure.com```に対応していない・・
+ Kubernetes的にも、```disk.csi.azure.com```が主流になっていくみたいだった・・
+ ```velero-plugin-for-csi:v0.2.0```というプラグインを追加して何とか対応することに・・
+ リリース前だったので、ユーザ影響なしでリリースできたけど、後々悲劇を呼ぶことに・・

### Veleroが```disk.csi.azure.com```に対応してきた
+ AKS 1.22にバージョンアップした際に、Velero 1.8.0が```disk.csi.azure.com```に対応してきました。
+ この前追加した、```velero-plugin-for-csi:v0.2.0```のプラグインはいらないのではないか？
+ 他のサードパーティーのアプリのインストールでも使用している、helmで管理したい・・
+ そのため、プラグインは1本化し、helmでインストール・管理するように構成変更することを決断。
+ しかし、この構成変更をすると、既存のバックアップスケジュールもPVのバックアップも使えなくなることが判明・・
+ 今回は、ユーザにしっかりと説明をしたことで、既存のバックアップとスケジュールを削除する許可を得ることができた。
+ もうこのような苦労がないことを願いたい。

## 今後に向けて
今回の投稿が皆さまのお役に少しでも立てば幸いです。
Veleroは、ストレージドライバに引き連られて、苦労したりしなかったりする運命にありそうです。そのため、日頃の情報収集が重要と思います。（慌てないために・・）
今後は、バックアップ取得前に、VeleroのBackup Hooksを使って、静止点を取得しバックアップを取得するような実装にチャレンジしてみます。（権限的なところがポイントと想定しています）
最新版のVeleroでは、ストレージアカウントへの書き込みに、MicrosoftEntraIDの認証を使用できるように修正が加えられています。こちらを使用するようにし、セキュリティ性の向上を狙いたいと思います。
`補足`：従来は、ストレージアカウントのアクセス制御に、アクセスキーという文字列を使用する方式が採用されており、このアクセスキーを参照できる権限を与えることで、ストレージアカウントへの書き込みを行っていました。

## 最後に
記載されている会社名、製品名、サービス名は、各社の商標または登録商標です。