LoginSignup
0
0

VeleroでKubernetesのバックアップを定期的に取る方法

Posted at

はじめに

本記事では Kubernetes クラスタのバックアップを取る方法を紹介します。

普段運用している Kubernetes クラスタでは fluxCD を使用しているため、単にオブジェクトを復元するだけであれば fluxCD の機能を使えばよかったのですが、Volume のバックアップも取りたいという要望があったため、バックアップツールを導入することにしました。

技術選定

使用するツールの条件として以下のようなものを考えました。

  • 定期的に自動でバックアップがされる
  • PV (PVC)もバックアップできる
  • リストアが 1~2 個のコマンドで手軽にできる
  • メンテナンスがされていて、ドキュメントが豊富

これを踏まえて次の 3 つを候補として考えました。

ツール メリット デメリット
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 点です。

  1. initContainersvelero-plugin-for-csivelero-plugin-for-gcpを追加
  2. configuration.featuresEnableCSIを追加
  3. nodeAgentを設定・deployNodeAgenttrueにする
  4. schedulessnapshotVolumetrueにする
  5. 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がないよというエラーだったので、longhornveleroのドキュメントを参考に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

参考資料

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0