Tanzu Kubernetes Grid1.6でVeleroを使ってNamespaceをバックアップ/リストアする


TKGm1.6でVeleroを使った時のメモ。VeleroのインストールからPVのバックアップまでの手順を記載している。
なお、PVのバックアップには[Velero Plugin for vSphere](https://github.com/vmware-tanzu/velero-plugin-for-vsphere)を利用している。

## 前提
- S3ストレージは準備済み（今回は[こちらの手順](https://qiita.com/ipppppei/items/ad0b01498e62c2e55256)に従ってMinIOを構築した）
- S3ストレージ内にバケットも作成済み
- TKGm1.6のWorkload Clusterは作成済み
- (MinIOの場合)テナントは非TLSで構築

## Veleroのインストール
オフィシャルドキュメントの[Back Up and Restore Cluster Workloads](https://docs.vmware.com/en/VMware-Tanzu-Kubernetes-Grid/1.6/vmware-tanzu-kubernetes-grid-16/GUID-cluster-lifecycle-backup-restore-mgmt-cluster.html)あたりのページを見ながら進めていく。

最初にveleroコマンドをインストールする。今回は作業端末がMacなので、[TKGのDownloadページ](https://customerconnect.vmware.com/en/downloads/info/slug/infrastructure_operations_management/vmware_tanzu_kubernetes_grid/1_x)からVelero 1.8.1 for MacをDownloadする。

Download後、解凍してインストールする。
```
gunzip velero-mac-v1.8.1+vmware.1.gz
sudo install velero-mac-v1.8.1+vmware.1 /usr/local/bin/velero
```

CLIインストール後、veleroをクラスタへインストールする。オフィシャルの説明は[このあたり](https://docs.vmware.com/en/VMware-Tanzu-Kubernetes-Grid/1.6/vmware-tanzu-kubernetes-grid-16/GUID-cluster-lifecycle-backup-restore-mgmt-cluster.html#install-velero-on-clusters-on-vsphere-8)になる。
オプションは以下となる。
- `--provider`：`aws`で固定。vSphereなのにと思うかもしれないが、おまじないということで。
- `--plugins`：`projects.registry.vmware.com/tkg/velero/velero-plugin-for-aws:v1.4.1_vmware.1`。ドキュメントで指定があるので。
- `--secret-file`：`$CREDENTIALS`。S3にアクセスするための認証情報。
- `--bucket`：`$BUCKET`。S3ストレージのバケットの名前。今回はMinIOで事前に作成済み。
- `--backup-location-config`：`region=$REGION,s3ForcePathStyle=true,s3Url=s3Url=$S3_URL`。regionはおまじない。s3ForcePathStyleはMinIOのようなローカルストレージを利用する場合に指定するオプション。s3UrlはS3（今回はMinIO）のURLとなる。
- `--snapshot-location-config`：`region=$SNAPSHOT_REGION`。これもおまじない。



インストール時に使うS3の認証情報のファイルを作成する。
```
CREDENTIALS=./credentials-velero
AWS_ACCESS_KEY_ID=demouser
AWS_SECRET_ACCESS_KEY=demodemo123
cat << EOF > $CREDENTIALS
[default]
aws_access_key_id=$AWS_ACCESS_KEY_ID
aws_secret_access_key=$AWS_SECRET_ACCESS_KEY
EOF
```

準備が整ったのでveleroコマンドを使ってインストールする。
```sh
CREDENTIALS=./credentials-velero
BUCKET="velero-bucket"
S3_URL=http://10.180.98.247
BACKUP_REGION=minio
SNAPSHOT_REGION=default
velero install --provider aws --plugins "projects.registry.vmware.com/tkg/velero/velero-plugin-for-aws:v1.4.1_vmware.1" --bucket $BUCKET --secret-file $CREDENTIALS --backup-location-config "region=${BACKUP_REGION},s3ForcePathStyle=true,s3Url=${S3_URL}" --snapshot-location-config region="${SNAPSHOT_REGION}"
```
コマンド実行後、最後に以下のメッセージが出力される。
```
Velero is installed! ⛵ Use 'kubectl logs deployment/velero -n velero' to view the status.
```
このタイミングではまだインストールが成功しているか分からない。出力されている通り、`kubectl logs`でエラーが出ていないかを必ず確認した方がよい。MinIOのテナントをオレオレ証明書で作っている人は特に注意。

なお、エラーが出た場合は再実行してもリソースが更新されるだけでPod側で再読み込みしてくれなかったりすることもあるので、以下のコマンドでアンインストールして再実行した方が早いかもしれない。
```
kubectl delete namespace/velero clusterrolebinding/velero
kubectl delete crds -l component=velero
```

正常にインストールが終了した場合、ログにはおおよそ以下のようなメッセージが出ており、出力メッセージのレベルが`info`のみになっていると思われる。
```
$ kubectl logs deployment/velero -n velero
：（省略）
time="2022-12-26T04:28:56Z" level=info msg="Starting workers" logSource="/go/pkg/mod/github.com/bombsimon/logrusr@v1.1.0/logrusr.go:111" logger=controller.serverstatusrequest reconciler group=velero.io reconciler kind=ServerStatusRequest worker count=10
time="2022-12-26T04:28:56Z" level=info msg="Starting workers" logSource="/go/pkg/mod/github.com/bombsimon/logrusr@v1.1.0/logrusr.go:111" logger=controller.downloadrequest reconciler group=velero.io reconciler kind=DownloadRequest worker count=1
time="2022-12-26T04:28:56Z" level=info msg="Validating backup storage location" backup-storage-location=default controller=backup-storage-location logSource="pkg/controller/backup_storage_location_controller.go:114"
time="2022-12-26T04:28:56Z" level=info msg="Backup storage location valid, marking as available" backup-storage-location=default controller=backup-storage-location logSource="pkg/controller/backup_storage_location_controller.go:121"
```

## Velero Plugin for vSphereのインストール
vSphere環境の場合、PVのバックアップに専用プラグインを利用することが出来る。これにより、仮想マシンのスナップショットと同じような機能でPVのバックアップが取得でき、ファイルシステムのメタデータの不一致などによるデータコラプションを防ぐ事ができる。（要は多くのケースでバックアップ前の静止処理が不要になる）

vCenterにアクセスするための情報を書いた設定ファイルを`csi-vsphere.conf`という名前で作成する。
オフィシャルのドキュメントは何故かvSphere with Tanzuでの説明しかないが、[OSS版のドキュメント](https://github.com/vmware-tanzu/velero-plugin-for-vsphere/blob/main/docs/vanilla.md#create-vc-credential-secret)にはちゃんと記述がある。

vSphere with Tanzuの場合のコマンドは以下になる。
```
kubectl -n vmware-system-csi get secret vsphere-config-secret -o jsonpath='{.data.csi-vsphere\.conf}'| base64 -d > csi-vsphere.conf
```
TKGmの場合は以下になる（Namespaceが違うだけ）。
```
kubectl -n kube-system get secret vsphere-config-secret -o jsonpath='{.data.csi-vsphere\.conf}'| base64 -d > csi-vsphere.conf
```

出力されたファイルの中身は以下のようになる。
```sh
[Global]
insecure-flag = true
cluster-id = kube-system/tkg-test

[VirtualCenter "10.180.96.119"]
user = "administrator@vsphere.local"
password = "xxxx"
datacenters = "/vSAN-DC"
insecure-flag = true
[Network]
public-network = "/vSAN-DC/network/VM Network"
```
作成した設定ファイルをSecretとして登録する。
```
kubectl -n velero create secret generic velero-vsphere-config-secret --from-file=csi-vsphere.conf
```
作成したSecretを参照するConfigMapを作る。この辺の設定項目の説明が見つからなかったので設定内容はあまり考えずに[オフィシャルドキュメントの記述](https://docs.vmware.com/en/VMware-Tanzu-Kubernetes-Grid/1.6/vmware-tanzu-kubernetes-grid-16/GUID-cluster-lifecycle-backup-restore-mgmt-cluster.html#install-velero-on-clusters-on-vsphere-8)を淡々とコピペしていく。
```yaml
cat << EOF > ./velero-plugin.conf
apiVersion: v1
kind: ConfigMap
metadata:
  name: velero-vsphere-plugin-config
data:
  cluster_flavor: VANILLA
  vsphere_secret_name: velero-vsphere-config-secret
  vsphere_secret_namespace: velero
EOF
kubectl -n velero apply -f velero-plugin.conf
```
Velero Plugin for vSphereをveleroに追加する。
```
velero plugin add projects.registry.vmware.com/tkg/velero/velero-plugin-for-vsphere:v1.3.1_vmware.1
```
なお、OSS版で試したい人は[こちら](https://github.com/vmware-tanzu/velero-plugin-for-vsphere/releases)からOSS版のリポジトリのイメージパスを参照し、置きかえるとよい。

追加後、`datamgr-for-vsphere-plugin`というDaemonSetが作成される。
```
$ kubectl get ds -n velero
NAME                         DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR   AGE
datamgr-for-vsphere-plugin   3         3         3       3            3           <none>          8m47s
```

## バックアップの取得
Veleroを使っての最も一般的なユースケースはNamespace単位でのバックアップだと思われる。
ここでは、適当なNamespaceを作成してリソースも配置し、バックアップを取得する。

以下でまとめてリソースを作成する。
```yaml
cat << EOF | kubectl apply -f -
apiVersion: v1
kind: Namespace
metadata:
  name: testvelero
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: testvelero
  namespace: testvelero
spec:
  accessModes:
    - ReadWriteOnce
  volumeMode: Filesystem
  resources:
    requests:
      storage: 100Mi
---
apiVersion: v1
kind: Pod
metadata:
  name: pvpod
  namespace: testvelero
spec:
  volumes:
  - name: testvol
    persistentVolumeClaim:
      claimName: testvelero
  containers:
  - name: busybox
    image: busybox
    command: [ "sleep", "365d" ]
    volumeMounts:
    - name: testvol
      mountPath: "/mnt"
EOF
```
バックアップを作成する。
```
$ velero backup create testvelero --include-namespaces testvelero
Backup request "testvelero" submitted successfully.
Run `velero backup describe testvelero` or `velero backup logs testvelero` for more details.
```
メッセージにもあるように、このタイミングではまだリクエストが受け付けられただけで、バックアップが成功したかは分からない。バックアップが完了した時点でコマンドが返るようにしたい人は`--wait`をつける必要がある。

上手くいくと以下のように`STATUS`に`Completed`がついたバックアップが表示される。
```
$ velero get backup testvelero
NAME         STATUS      ERRORS   WARNINGS   CREATED                         EXPIRES   STORAGE LOCATION   SELECTOR
testvelero   Completed   0        0          2022-12-26 16:36:53 +0900 JST   29d       default            <none>
```
なお、PVだけバックアップに失敗したケースとかでは`STATUS`に`PartiallyFailed`が立つ。デバッグはかなり難しいので、サポート契約がある人は素直に問い合わせた方が早いと思う。

習得したバックアップはMinIOのCLIであるmcコマンドがある場合はこんな感じで見ることが出来る。
```
$ mc ls velero-bucket/ -r
[2022-12-26 16:37:24 JST]    29B STANDARD velero-bucket/backups/testvelero/testvelero-csi-volumesnapshotcontents.json.gz
[2022-12-26 16:37:24 JST]    29B STANDARD velero-bucket/backups/testvelero/testvelero-csi-volumesnapshots.json.gz
[2022-12-26 16:37:23 JST] 9.1KiB STANDARD velero-bucket/backups/testvelero/testvelero-logs.gz
[2022-12-26 16:37:23 JST]    29B STANDARD velero-bucket/backups/testvelero/testvelero-podvolumebackups.json.gz
[2022-12-26 16:37:24 JST]   564B STANDARD velero-bucket/backups/testvelero/testvelero-resource-list.json.gz
[2022-12-26 16:37:24 JST]    29B STANDARD velero-bucket/backups/testvelero/testvelero-volumesnapshots.json.gz
[2022-12-26 16:37:23 JST] 115KiB STANDARD velero-bucket/backups/testvelero/testvelero.tar.gz
[2022-12-26 16:37:23 JST] 2.1KiB STANDARD velero-bucket/backups/testvelero/velero-backup.json
[2022-12-26 16:37:31 JST] 100MiB STANDARD velero-bucket/plugins/vsphere-astrolabe-repo/ivd/data/ivd:e0108537-28ae-4719-8e19-9f5ef6174bd6:8136cf8c-6da6-4712-8d6a-96e7859d685b.data/000000-0000000000000000
[2022-12-26 16:37:31 JST] 4.5KiB STANDARD velero-bucket/plugins/vsphere-astrolabe-repo/ivd/md/ivd:e0108537-28ae-4719-8e19-9f5ef6174bd6:8136cf8c-6da6-4712-8d6a-96e7859d685b.md/000000-0000000000000000
[2022-12-26 16:37:31 JST]  1000B STANDARD velero-bucket/plugins/vsphere-astrolabe-repo/ivd/peinfo/ivd:e0108537-28ae-4719-8e19-9f5ef6174bd6:8136cf8c-6da6-4712-8d6a-96e7859d685b
```
plugings以下のディレクトリにPVの実体が保存される。

## バックアップのリストア

先程習得したバックアップをリストアしてみる。
最初に、確認用に作成したリソースを削除する。
```
kubectl delete ns testvelero
```
削除したリソースが戻ってくるか、リストアをして確かめる。
```
$ velero restore create testvelero-restore --from-backup testvelero
Restore request "testvelero-restore" submitted successfully.
Run `velero restore describe testvelero-restore` or `velero restore logs testvelero-restore` for more details.
```
こちらも`--wait`をつけないと即コマンドが帰ってくるので、リストアが完了したかどうかはログなり`velero restore get`なりで確認する必要がある。
無事リストアが完了すると、`STATUS`が`COMPLETED`となる。
```
$ velero restore get testvelero-restore
NAME                 BACKUP       STATUS      STARTED                         COMPLETED                       ERRORS   WARNINGS   CREATED                         SELECTOR
testvelero-restore   testvelero   Completed   2022-12-26 16:45:35 +0900 JST   2022-12-26 16:46:41 +0900 JST   0        0          2022-12-26 16:45:35 +0900 JST   <none>
```
リストア完了後、リソースを見ると復元出来ていることが分かる。
```
$ kubectl get pod,pvc -n testvelero
NAME        READY   STATUS    RESTARTS   AGE
pod/pvpod   1/1     Running   0          2m32s

NAME                               STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
persistentvolumeclaim/testvelero   Bound    pvc-c2ecae93-7b9b-458c-93ea-8c26707d9669   100Mi      RWO            default        2m49s
```

お疲れ様でした。