はじめに
本記事では Kubernetes クラスタのバックアップを取る方法を紹介します。
普段運用している Kubernetes クラスタでは fluxCD を使用しているため、単にオブジェクトを復元するだけであれば fluxCD の機能を使えばよかったのですが、Volume のバックアップも取りたいという要望があったため、バックアップツールを導入することにしました。
技術選定
使用するツールの条件として以下のようなものを考えました。
- 定期的に自動でバックアップがされる
- PV (PVC)もバックアップできる
- リストアが 1~2 個のコマンドで手軽にできる
- メンテナンスがされていて、ドキュメントが豊富
これを踏まえて次の 3 つを候補として考えました。
- Velero
- longhorn によるバックアップ
- kube-backup
ツール | メリット | デメリット |
---|---|---|
Velero | Test 用のクラスタに使い回せる バックアップスケジューラ内包 |
flux を入れてるのに k8s オブジェクトまで Backup ツールで復元する必要ことになってちょっと微妙(それは他のツールでも同じ?) |
longhorn | すでにストレージに使っている longhorn をそのまま使える 友人が longhorn でバックアップを取っていて参考にできる |
別のストレージサービスを使うことになった場合別途バックアップをする必要がある(?) バックアップとストレージは疎結合にしておきたい |
kube-backup | メンテナンスが 5 年前からされていない |
今後 longhorn 以外のストレージサービスを使う可能性もあるため、今回は Velero を選択しました。
手順
1. CLI のインストール
参考: https://velero.io/docs/v1.13/basic-install/
wget https://github.com/vmware-tanzu/velero/releases/download/v1.13.0/velero-v1.13.0-linux-amd64.tar.gz
tar -xvf velero-v1.13.0-linux-amd64.tar.gz
sudo mv velero-v1.13.0-linux-amd64/velero /usr/local/bin
if type _init_completion > /dev/null; then echo "bash completion has already been installed!"; else sudo apt-get update; sudo apt-get install bash-completion; fi
if type _init_completion > /dev/null; then echo "bash completion installed!"; else source /usr/share/bash-completion/bash_completion; fi
velero completion bash | sudo tee /etc/bash_completion.d/velero
2. GCP の認証情報の設定
今回はバックアップを GCP に保存するため、GCP のプラグインの README に従って認証情報を設定します。
このセクションの操作はローカル PC で行って問題ありません。最後にダウンロードしたファイルをサーバーにアップロードするのを忘れないようにしてください。
参考: https://github.com/vmware-tanzu/velero-plugin-for-gcp?tab=readme-ov-file#Set-permissions-for-Velero
gcloud CLI
を使って認証情報を設定するため、 ローカルマシンにgcloud
がインストールされていない場合はインストール・初期化を行います。
GCS のバケットを作成:
BUCKET=<YOUR_BUCKET>
gsutil mb gs://$BUCKET/
GCP のサービスアカウントを作成:
次のコマンドでvelero
という名前のサービスアカウントを作成します。
PROJECT_ID=$(gcloud config get-value project)
GSA_NAME=velero
gcloud iam service-accounts create $GSA_NAME \
--display-name "Velero service account"
gcloud iam service-accounts list
で作成したサービスアカウントを確認できるはずです。
サービスアカウントに必要な権限を付与:
SERVICE_ACCOUNT_EMAIL=$(gcloud iam service-accounts list \
--filter="displayName:Velero service account" \
--format 'value(email)')
ROLE_PERMISSIONS=(
compute.disks.get
compute.disks.create
compute.disks.createSnapshot
compute.projects.get
compute.snapshots.get
compute.snapshots.create
compute.snapshots.useReadOnly
compute.snapshots.delete
compute.zones.get
storage.objects.create
storage.objects.delete
storage.objects.get
storage.objects.list
iam.serviceAccounts.signBlob
)
gcloud iam roles create velero.server \
--project $PROJECT_ID \
--title "Velero Server" \
--permissions "$(IFS=","; echo "${ROLE_PERMISSIONS[*]}")"
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member serviceAccount:$SERVICE_ACCOUNT_EMAIL \
--role projects/$PROJECT_ID/roles/velero.server
gsutil iam ch serviceAccount:$SERVICE_ACCOUNT_EMAIL:objectAdmin gs://${BUCKET}
サービスアカウントの鍵を作成してダウンロード:
credentials-velero
という名前のファイルがダウンロードされます。
gcloud iam service-accounts keys create credentials-velero \
--iam-account $SERVICE_ACCOUNT_EMAIL
3. Velero server のインストール
gcloud
の設定をローカル PC で行った場合は、サーバーにcredentials-velero
をアップロードします。
scp credentials-velero user@server:/path/to/credentials-velero.json
インストール方法には helm を使う方法とvelero install
を使う方法があります。今回は Helm を使う方法をとりました。
velero
という名前の namespace を作成:
kubectl create namespace velero
サーバーにアップロードした鍵をもとに secret を作成:
kubectl create secret generic google-credentials -n velero --from-file=gcp=./credentials-velero.json
Helm 用のvalues.yaml
を作成:
ポイントは次の 5 点です。
-
initContainers
にvelero-plugin-for-csi
とvelero-plugin-for-gcp
を追加 -
configuration.features
にEnableCSI
を追加 -
nodeAgent
を設定・deployNodeAgent
をtrue
にする -
schedules
でsnapshotVolume
をtrue
にする -
defaultSnapshotMoveData: true
を指定する
これによってボリュームのスナップショットもバックアップされるようになります。
image:
repository: velero/velero
tag: v1.13.0
pullPolicy: IfNotPresent
resources:
requests:
cpu: 500m
memory: 128Mi
limits:
cpu: 1000m
memory: 512Mi
initContainers:
- name: velero-plugin-for-csi
image: velero/velero-plugin-for-csi:v0.7.1
imagePullPolicy: IfNotPresent
volumeMounts:
- mountPath: /target
name: plugins
- name: velero-plugin-for-gcp
image: velero/velero-plugin-for-gcp:v1.9.1
volumeMounts:
- mountPath: /target
name: plugins
configuration:
backupStorageLocation:
- name: default
provider: velero.io/gcp
bucket: velero-piny940
credential:
name: google-credentials
key: gcp
volumeSnapshotLocation:
- name: default
provider: velero.io/gcp
credential:
name: google-credentials
key: gcp
features: EnableCSI
defaultSnapshotMoveData: true
deployNodeAgent: true
nodeAgent:
podVolumePath: /var/lib/kubelet/pods
resources:
requests:
cpu: 500m
memory: 512Mi
schedules:
backup-daily:
disabled: false
schedule: "48 3 * * *"
template:
labels:
app: velero-backup-daily
snapshotVolumes: true
helm repo add vmware-tanzu https://vmware-tanzu.github.io/helm-charts
helm install velero vmware-tanzu/velero --namespace velero --values velero/values.yaml
4. バックアップを手動で実行する
velero のインストールが完了したら、正常にバックアップを作成できるかチェックします。
velero backup create --from-schedule backup-schedule
5. バックアップのリストア
バックアップをリストアするには、velero restore
コマンドを使います。
velero restore create --from-backup <backup-name>
上手く行けば、バックアップがリストアされます。
最後に
今回は Velero を使ってクラスタのバックアップを取る方法を紹介しました。
これでサーバーが壊れても安心です!
次回は kubernetes のログ周りをいい感じに整えたいと思います。
付録
エラー対応
バックアップを作成しようとしたら、VolumeSnapshotClass
が見つからないというエラーが発生しました。
k logs velero-7ff79d67b6-5bn6d -n velero | grep error
Defaulted container "velero" out of: velero, velero-velero-plugin-for-gcp (init), velero-velero-plugin-for-csi (init)
time="2024-04-22T02:18:36Z" level=error msg="Current BackupStorageLocations available/unavailable/unknown: 0/0/1)" controller=backup-storage-location logSource="pkg/controller/backup_storage_location_controller.go:180"
time="2024-04-22T02:25:14Z" level=info msg="1 errors encountered backup up item" backup=velero/backup-20240422112304 logSource="pkg/backup/backup.go:457" name=postgres-cluster-0
time="2024-04-22T02:25:14Z" level=error msg="Error backing up item" backup=velero/backup-20240422112304 error="error executing custom action (groupResource=persistentvolumeclaims, namespace=database, name=pgdata-postgres-cluster-0): rpc error: code = Unknown desc = failed to get volumesnapshotclass for storageclass longhorn: error listing volumesnapshot classes: the server could not find the requested resource (get volumesnapshotclasses.snapshot.storage.k8s.io)" logSource="pkg/backup/backup.go:461" name=postgres-cluster-0
time="2024-04-22T02:25:14Z" level=info msg="1 errors encountered backup up item" backup=velero/backup-20240422112304 logSource="pkg/backup/backup.go:457" name=data-postgresql-0
time="2024-04-22T02:25:14Z" level=error msg="Error backing up item" backup=velero/backup-20240422112304 error="error executing custom action (groupResource=persistentvolumeclaims, namespace=database, name=data-postgresql-0): rpc error: code = Unknown desc = failed to get volumesnapshotclass for storageclass longhorn: error listing volumesnapshot classes: the server could not find the requested resource (get volumesnapshotclasses.snapshot.storage.k8s.io)" error.file="/go/src/github.com/vmware-tanzu/velero/pkg/backup/item_backupper.go:380" error.function="github.com/vmware-tanzu/velero/pkg/backup.(*itemBackupper).executeActions" logSource="pkg/backup/backup.go:461" name=data-postgresql-0
time="2024-04-22T02:25:16Z" level=error msg="no matches for kind \"VolumeSnapshot\" in version \"snapshot.storage.k8s.io/v1\"" backup=velero/backup-20240422112304 logSource="pkg/backup/snapshots.go:56"
time="2024-04-22T02:25:17Z" level=error msg="no matches for kind \"VolumeSnapshotContent\" in version \"snapshot.storage.k8s.io/v1\"" backup=velero/backup-20240422112304 logSource="pkg/backup/snapshots.go:61"
time="2024-04-22T02:25:19Z" level=error msg="cannot list VolumeSnapshotClass no matches for kind \"VolumeSnapshotClass\" in version \"snapshot.storage.k8s.io/v1\"" backup=velero/backup-20240422112304 error="no matches for kind \"VolumeSnapshotClass\" in version \"snapshot.storage.k8s.io/v1\"" logSource="internal/volume/volumes_information.go:468"
external-snapshotterから CRD やら xx-controller やらをインストールする必要があるようです。
$ git clone git@github.com:kubernetes-csi/external-snapshotter.git
$ cd external-snapshotter
$ kubectl kustomize client/config/crd | kubectl create -f -
$ kubectl kustomize deploy/kubernetes/csi-snapshotter | kubectl create -f -
これを実行すると、無事「CRD がないよ」系のエラーが解消されました。
次に以下のようなエラーが発生しました。
Errors:
Velero: name: /postgres-cluster-0 message: /Error backing up item error: /error executing custom action (groupResource=persistentvolumeclaims, namespace=database, name=pgdata-postgres-cluster-0): rpc error: code = Unknown desc = failed to get volumesnapshotclass for storageclass longhorn: error getting volumesnapshotclass: failed to get volumesnapshotclass for provisioner driver.longhorn.io, ensure that the desired volumesnapshot class has the velero.io/csi-volumesnapshot-class label
name: /data-postgresql-0 message: /Error backing up item error: /error executing custom action (groupResource=persistentvolumeclaims, namespace=database, name=data-postgresql-0): rpc error: code = Unknown desc = failed to get volumesnapshotclass for storageclass longhorn: error getting volumesnapshotclass: failed to get volumesnapshotclass for provisioner driver.longhorn.io, ensure that the desired volumesnapshot class has the velero.io/csi-volumesnapshot-class label
VolumeSnapshotClass
がないよというエラーだったので、longhornとveleroのドキュメントを参考にVolumeSnapshotClass
を作成しました。
kind: VolumeSnapshotClass
apiVersion: snapshot.storage.k8s.io/v1
metadata:
name: longhorn-snapshot-vsc
labels:
velero.io/csi-volumesnapshot-class: "true"
driver: driver.longhorn.io
deletionPolicy: Delete
parameters:
type: snap
すると無事バックアップが作成されました。
$ velero backup describe backup-20240422225629 --details
Name: backup-20240422225629
Namespace: velero
Labels: velero.io/storage-location=default
Annotations: velero.io/resource-timeout=10m0s
velero.io/source-cluster-k8s-gitversion=v1.28.4
velero.io/source-cluster-k8s-major-version=1
velero.io/source-cluster-k8s-minor-version=28
Phase: Completed
Namespaces:
Included: database
Excluded: <none>
Resources:
Included: *
Excluded: <none>
Cluster-scoped: auto
Label selector: <none>
Or label selector: <none>
Storage Location: default
Velero-Native Snapshot PVs: auto
Snapshot Move Data: false
Data Mover: velero
TTL: 720h0m0s
CSISnapshotTimeout: 10m0s
ItemOperationTimeout: 4h0m0s
Hooks: <none>
Backup Format Version: 1.1.0
Started: 2024-04-22 13:57:11 +0000 UTC
Completed: 2024-04-22 13:57:40 +0000 UTC
Expiration: 2024-05-22 13:57:11 +0000 UTC
Total items to be backed up: 65
Items backed up: 65
Backup Item Operations:
Operation for volumesnapshots.snapshot.storage.k8s.io database/velero-pgdata-postgres-cluster-0-bzw78:
Backup Item Action Plugin: velero.io/csi-volumesnapshot-backupper
Operation ID: database/velero-pgdata-postgres-cluster-0-bzw78/2024-04-22T13:57:21Z
Items to Update:
volumesnapshots.snapshot.storage.k8s.io database/velero-pgdata-postgres-cluster-0-bzw78
Phase: Completed
Created: 2024-04-22 13:57:21 +0000 UTC
Started: 2024-04-22 13:57:21 +0000 UTC
Operation for volumesnapshotcontents.snapshot.storage.k8s.io /snapcontent-c8934130-f792-46ea-b03b-91028827145f:
Backup Item Action Plugin: velero.io/csi-volumesnapshotcontent-backupper
Operation ID: snapcontent-c8934130-f792-46ea-b03b-91028827145f/2024-04-22T13:57:21Z
Items to Update:
volumesnapshotcontents.snapshot.storage.k8s.io /snapcontent-c8934130-f792-46ea-b03b-91028827145f
Phase: Completed
Created: 2024-04-22 13:57:21 +0000 UTC
Started: 2024-04-22 13:57:21 +0000 UTC
Operation for volumesnapshots.snapshot.storage.k8s.io database/velero-data-postgresql-0-8p4rg:
Backup Item Action Plugin: velero.io/csi-volumesnapshot-backupper
Operation ID: database/velero-data-postgresql-0-8p4rg/2024-04-22T13:57:31Z
Items to Update:
volumesnapshots.snapshot.storage.k8s.io database/velero-data-postgresql-0-8p4rg
Phase: Completed
Created: 2024-04-22 13:57:31 +0000 UTC
Started: 2024-04-22 13:57:31 +0000 UTC
Operation for volumesnapshotcontents.snapshot.storage.k8s.io /snapcontent-3a9daaf4-180c-478a-98fb-170e0d307f6e:
Backup Item Action Plugin: velero.io/csi-volumesnapshotcontent-backupper
Operation ID: snapcontent-3a9daaf4-180c-478a-98fb-170e0d307f6e/2024-04-22T13:57:31Z
Items to Update:
volumesnapshotcontents.snapshot.storage.k8s.io /snapcontent-3a9daaf4-180c-478a-98fb-170e0d307f6e
Phase: Completed
Created: 2024-04-22 13:57:31 +0000 UTC
Started: 2024-04-22 13:57:31 +0000 UTC
Resource List:
acid.zalan.do/v1/OperatorConfiguration:
- database/postgres-operator
acid.zalan.do/v1/postgresql:
- database/postgres-cluster
apiextensions.k8s.io/v1/CustomResourceDefinition:
- externalsecrets.external-secrets.io
- helmcharts.source.toolkit.fluxcd.io
- helmreleases.helm.toolkit.fluxcd.io
- helmrepositories.source.toolkit.fluxcd.io
- operatorconfigurations.acid.zalan.do
- postgresqls.acid.zalan.do
apps/v1/ControllerRevision:
- database/cluster-db-6b79d5f59b
- database/cluster-db-ccc5c994
- database/postgres-cluster-5cb485c687
- database/postgres-cluster-6968f7b6f6
- database/postgres-cluster-745869b67f
- database/postgres-cluster-766df988cb
- database/postgres-cluster-79d58c54bd
- database/postgres-cluster-7ff9f7fd5b
- database/postgres-cluster-bdd5ddf64
apps/v1/Deployment:
- database/postgres-operator
apps/v1/ReplicaSet:
- database/postgres-operator-7f6b6fb948
- database/postgres-operator-8694bf465b
apps/v1/StatefulSet:
- database/postgres-cluster
discovery.k8s.io/v1/EndpointSlice:
- database/cluster-db-repl-68hjl
- database/postgres-cluster-repl-85mrq
- database/postgres-cluster-vpsvp
- database/postgres-operator-fcmgp
external-secrets.io/v1beta1/ExternalSecret:
- database/postgres-secret
helm.toolkit.fluxcd.io/v2beta2/HelmRelease:
- database/postgres-operator
policy/v1/PodDisruptionBudget:
- database/postgres-postgres-cluster-pdb
rbac.authorization.k8s.io/v1/ClusterRole:
- postgres-operator
rbac.authorization.k8s.io/v1/ClusterRoleBinding:
- postgres-operator
rbac.authorization.k8s.io/v1/RoleBinding:
- database/postgres-pod
snapshot.storage.k8s.io/v1/VolumeSnapshot:
- database/velero-data-postgresql-0-8p4rg
- database/velero-pgdata-postgres-cluster-0-bzw78
snapshot.storage.k8s.io/v1/VolumeSnapshotClass:
- longhorn-snapshot-vsc
snapshot.storage.k8s.io/v1/VolumeSnapshotContent:
- snapcontent-3a9daaf4-180c-478a-98fb-170e0d307f6e
- snapcontent-c8934130-f792-46ea-b03b-91028827145f
source.toolkit.fluxcd.io/v1beta2/HelmChart:
- database/database-postgres-operator
source.toolkit.fluxcd.io/v1beta2/HelmRepository:
- database/postgres-operator
v1/ConfigMap:
- database/kube-root-ca.crt
v1/Endpoints:
- database/postgres-cluster
- database/postgres-cluster-config
- database/postgres-cluster-repl
- database/postgres-operator
v1/Event:
- database/database-postgres-operator.17bcfc3029c627b4
- database/postgres-operator.17c0eda01d92b131
- database/postgres-secret.17c76139cfb06c55
v1/Namespace:
- database
v1/PersistentVolume:
- pvc-139d2fbd-6d0a-465c-bcbe-5acf54a0a246
- pvc-95bea64e-b0c6-4628-8eef-66b1e68aa2fe
v1/PersistentVolumeClaim:
- database/data-postgresql-0
- database/pgdata-postgres-cluster-0
v1/Pod:
- database/postgres-cluster-0
- database/postgres-operator-7f6b6fb948-l65qc
v1/Secret:
- database/postgres-secret
- database/postgres.postgres-cluster.credentials.postgresql.acid.zalan.do
- database/sh.helm.release.v1.postgres-operator.v1
- database/sh.helm.release.v1.postgres-operator.v2
- database/standby.postgres-cluster.credentials.postgresql.acid.zalan.do
v1/Service:
- database/postgres-cluster
- database/postgres-cluster-config
- database/postgres-cluster-repl
- database/postgres-operator
v1/ServiceAccount:
- database/default
- database/postgres-operator
- database/postgres-pod
Backup Volumes:
Velero-Native Snapshots: <none included>
CSI Snapshots:
database/data-postgresql-0:
Snapshot:
Operation ID: database/velero-data-postgresql-0-8p4rg/2024-04-22T13:57:31Z
Snapshot Content Name: snapcontent-3a9daaf4-180c-478a-98fb-170e0d307f6e
Storage Snapshot ID: snap://pvc-139d2fbd-6d0a-465c-bcbe-5acf54a0a246/snapshot-3a9daaf4-180c-478a-98fb-170e0d307f6e
Snapshot Size (bytes): 10737418240
CSI Driver: driver.longhorn.io
database/pgdata-postgres-cluster-0:
Snapshot:
Operation ID: database/velero-pgdata-postgres-cluster-0-bzw78/2024-04-22T13:57:21Z
Snapshot Content Name: snapcontent-c8934130-f792-46ea-b03b-91028827145f
Storage Snapshot ID: snap://pvc-95bea64e-b0c6-4628-8eef-66b1e68aa2fe/snapshot-c8934130-f792-46ea-b03b-91028827145f
Snapshot Size (bytes): 10737418240
CSI Driver: driver.longhorn.io
Pod Volume Backups: <none included>
HooksAttempted: 0
HooksFailed: 0
参考資料