ADMIN

2023

11

2023-10-30T12:00:00

Backup und Recovery

SCHWERPUNKT

080

Datensicherheit

Backup

Recovery

Kubernetes

Kubernetes-Backups mit Velero

Immer Wind in den Segeln

von Dr. Guido Söldner

Veröffentlicht in Ausgabe 11/2023 - SCHWERPUNKT

Einst von VMware entwickelt und nunmehr Open Source in den Händen der Cloud Native Computing Foundation, leistet Velero Backup, Disaster Recovery und Datenmigration im Kubernetes-Umfeld. Wir zeigen, wie Sie das Tool aufsetzen und die drei erwähnten Aufgaben in Ihrem Cluster erledigen. So stellen Sie sicher, dass Ihre Apps immer Rückenwind haben.

Backups innerhalb eines Kubernetes-Clusters umfassen üblicherweise verschiedene Elemente wie die Master-Knoten, die Worker-Knoten und die etcd-Datenbank. Administratoren sind bei Datensicherungen aber zumeist an Kubernetes-Objekten interessiert, also zum Beispiel Namespaces, Persistent Disks oder Deployments.
Genau in diese Bresche springt Velero [1]. Die Software läuft sowohl in Cloudumgebungen als auch im eigenen Rechenzentrum und kommt mit diesen zentralen Funktionalitäten daher:
- Erstellen von Backups und deren Einspielen im Falle eines Datenverlustes.
Backups innerhalb eines Kubernetes-Clusters umfassen üblicherweise verschiedene Elemente wie die Master-Knoten, die Worker-Knoten und die etcd-Datenbank. Administratoren sind bei Datensicherungen aber zumeist an Kubernetes-Objekten interessiert, also zum Beispiel Namespaces, Persistent Disks oder Deployments.
Genau in diese Bresche springt Velero [1]. Die Software läuft sowohl in Cloudumgebungen als auch im eigenen Rechenzentrum und kommt mit diesen zentralen Funktionalitäten daher:
- Erstellen von Backups und deren Einspielen im Falle eines Datenverlustes.
- Migration von Cluster-Ressourcen auf andere Cluster.
- Replizieren von Inhalten eines Clusters auf andere Umgebungen.
Infrastrukur für Velero
Die Velero-Serverkomponenten müssen auf dem Kubernetes-Cluster installiert werden. Dies erfolgt entweder über ein Helm Chart oder über die Velero CLI. Diese CLI bildet die Basis für Arbeiten mit dem Tool, kommt also bei Sicherungen und Recovery zum Einsatz. Schließlich sind die Storage-Provider-Plug-ins im Quellspeicher der Datensicherung einzuspielen.
Darüber hinaus benötigen Sie noch Platz zum Ablegen der Backups. Velero nutzt dafür S3-kompatiblen Objektspeicher, den Sie beispielsweise in der Cloud in Form von AWS S3, Azure Storage oder Google Cloud Storage bereitstellen. Falls Sie lokal unterwegs sind, gibt es dafür Produkte wie Swarm Object Storage von Datacore, NtApp Storage Grid oder auch das Open-Source-Projekt MinIO [2].
Velero via CLI in Betrieb nehmen
Am einfachsten installieren Sie Velero über dessen CLI. Voraussetzung dafür ist, dass Sie Zugriff auf einen Kubernetes-Cluster haben. Dafür müssen Sie im ersten Schritt die CLI installieren, was wir beispielhaft für ein Linux-System zeigen. Zunächst laden Sie also die CLI herunter:
wget https://github.com/vmwaretanzu/velero/releases/download/v1.11.1/velero-v1.11.1-linuxamd64.tar.gz
Jetzt entpacken Sie das Archiv:
tar xzf velero-v1.11.1-linuxamd64.tar.gz
Das enthaltene Binary verschieben Sie in den Ordner "/usr/bin":
sudo mv velero-v1.11.1-linuxamd64/velero /usr/bin
Die Installation überprüfen Sie, indemSie die Version abfragen:
velero version
Nun geht es an die Installation der Serverkomponenten. Zuvor sind jedoch einige Voraussetzungen zu erfüllen, angefangen mit der notwendigen Kubernetes-Minimal-Version. Dies ist allerdings einfach – Version 1.12 ist schon seit einigen Jahren erhältlich. Beim Einrichten des Objektspeichers gibt es mehr Arbeit. Dieser muss nicht nur vorhanden sein, Sie brauchen auch entsprechende Berechtigungen. Die Konfiguration ist je nach verwendetem Objektspeicher beziehungsweise Clouddienst unterschiedlich. Wir zeigen im Folgenden die Konfiguration in der Google-Cloud.
Dafür wechseln Sie in der Google Cloud Console in das Projekt, in dem der Objektspeicher sein Zuhause haben soll und geben oben mittig "Cloud Storage" im Suchfeld ein. Auf der Seite "Cloud Storage" angekommen, klicken Sie oben links auf "Buckets auswählen" und dann auf "Create". Jetzt hinterlegen Sie den Namen des Cloud Storage Buckets – dieser muss weltweit eindeutig sein. Anschließend wählen Sie eine Region aus – für Deutschland empfiehlt sich "europe-west3", also Frankfurt. Den Rest der Einstellungen können Sie übernehmen und klicken auf "Create".
Bild 1: Um Sicherungen zu speichern, ist das Anlegen eines Storage Buckets erforderlich.
Notwendige Berechtigungen zuteilen
Die anschließende Vergabe der notwendigen Berechtigungen ist etwas kniffliger. Diese müssen sowohl den Zugriff auf den Bucket als auch die Rechte für die Installation im Kubernetes-Cluster umfassen. Für den Cluster sind Admin-Rechte für denjenigen notwendig, der die Installation durchführt.
Die Velero-Installation legt innerhalb des Kubernetes-Clusters RBAC-Objekte (Role Based Access Control) an. Daher benötigen Sie die entsprechende Cluster-Admin-Rolle. Beim Zugriff auf den Bucket können Sie es sich leicht machen und einfach die "Object-Admin"-Rolle im Projekt vergeben. Für das Erzeugen von Snap-shots und diversen anderen Objekten sind weitere Rechte notwendig, dafür legen wir im Folgenden eine Custom-Rolle an.
Zuerst müssen wir aber einen Google-Service-Account erzeugen, der diese Rechte erhalten soll. Dies ist über die Cloudkonsole oder über die Bash möglich. Haben Sie die Google gcloud-CLI noch nicht aktiviert, erledigen Sie dies in der Konsole, indem Sie die Cloud Shell über den Knopf oben rechts starten. Dort gehen Sie auch die weiteren Arbeiten an, zuerst schauen Sie Ihre aktuellen Projekteinstellungen nach:
gcloud config list
Anschließend setzen Sie "PROJECT_ID" auf den gewünschten Wert:
PROJECT_ID=$(gcloud config get-value project)
Nun erzeugen Sie den Service-Account:
GSA_NAME=velero
gcloud iam service-accounts create $GSA_NAME \ --display-name "Velero service account"
Um mit den Service-Account arbeiten zu können, ist noch dessen E-Mail-Adresse erforderlich. Diese bekommen wir wie folgt heraus:
SERVICE_ACCOUNT_EMAIL=$(gcloud iam service-accounts list \ --filter="displayName:Velero service account" \ --format 'value(email)')
Nun legen Sie die Custom-Role für Velero an. Die notwendigen Befehle zeigt Listing 1. Dabei definieren Sie zuerst ein Array mit den entsprechend benötigten Einzelrechten und legen anschließend eine Rolle damit an. Im dritten Schritt verknüpfen Sie die Rolle mit dem zuvor angelegten Service-Account. Als Letztes geben Sie dem Service-Account noch die Rechte, mit dem Bucket zu arbeiten.
Listing 1: Custom-Role für Velero erzeugen
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}
Nun müssen wir dafür sorgen, dass Velero im Betrieb die ihm zugeteilten Berechtigungen auch nutzen kann. Dafür gibt es in der Google-Cloud verschiedene Ansätze:
- Sie erzeugen einen Service-Account-Key und geben diesen bei der Installation an.
- Sie konfigurieren "Workforce Identity Federation". Dies hat jedoch den Nachteil, dass Sie die velero-Befehle "velero backup logs", "velero backup download", "velero backup describe" und "velero re-store describe" nicht nutzen können.
- Sie richten "GKE Workload Identity" ein und können innerhalb des Kubernetes-Clusters mittels Annotationen ein Mapping zwischen Kubernetes- und Google-Service-Accounts definieren.
Wir entscheiden uns für die erste Variante und erzeugen einen Service-Account-Key:
gcloud iam service-accounts keys create credentials-velero \ --iam-account $SERVICE_ACCOUNT_ EMAIL
Nun kann die Installation beginnen. Dies gelingt uns wie folgt:
velero install \
--provider gcp \
--plugins velero/velero-plugin-for-gcp:v1.6.0 \
--bucket $BUCKET \
--secret-file ./credentials-velero
Nach der Installation checken Sie im Kubernetes-Cluster, ob Velero läuft:
$ kubectl get pods -n velero
Das Innenleben von Velero verstehen
Für die Arbeit mit Velero ist ein grundsätzliches Verständnis der Architektur der Software notwendig. Dessen Installation erzeugt im Kubernetes-Cluster einen Backup-Controller. Dieser kommuniziert sowohl mit dem Kubernetes-API- Server, der etcd-Datenbank als auch mit den konfigurierten Storage-Locations.
Die Arbeitsweise des Tools am Beispiel eines Backup-Workflows ist in Bild 2 ersichtlich. Diesen initiieren Sie durch den Befehl velero backup create test-backup:
1. Der Velero-Befehl setzt einen API-Aufruf an den Kubernetes-API-Server ab, um innerhalb von Kubernetes ein Backupobjekt zu erzeugen.
2. Der Backup-Controller bemerkt das neu erstellte Objekt und überprüft dessen Werte.
3. Der Backup-Controller beginnt mit der Sicherung. Dafür sammelt er vom API-Server die notwendigen Daten.
4. Anschließend ruft er die API des Objektspeichers auf – in unserem Beispiel Google Cloud Storage – und lädt die Backupdatei hoch.
Velero unterstützt sowohl das einmalige Anlegen eines Backups (One-Time) als auch wiederkehrende Sicherungen (recurring). Dabei ist es möglich, einzelne Objekte als auch den ganzen Cluster zu sichern.
Bild 2: Der Ablauf des Backupprozesses in Velero.
Ausführen einer One-Time-Sicherung
Beim Erzeugen eines initialen Backups ist es oft sinnvoll, den ganzen Cluster samt aller Namespaces zu sichern. Starten Sie das Backup ohne dedizierte Flags, sichert Velero den gesamten Cluster mit allen Namespaces und Objekten. Ein einmaliges Backup starten Sie über
velero backup create initial-backup
Sie haben dabei die Option, mittels velero backup describe initial-backup zu überprüfen, ob die Sicherung geklappt hat. Die Antwort auf diese Anfrage ist relativ lang und sieht wie Listing 2 aus. Dabei liefert Ihnen die describe-Option alle Einstellungen des Backupjobs. Wichtig dabei ist, ob der Job abgeschlossen wurde, aber auch die Anzahl der gesicherten Objekte. Auch die Start- und die Endzeit des Backup-Jobs sind von Relevanz.
Listing 2: Velero antwortet auf Frage nach erfolgreichem Backup
Name:               initial-backup
Namespace:      velero
Labels:              velero.io/storagelocation=default
Annotations:     velero.io/source-clusterk8s-gitversion=v1.26.5-gke.2700
                         velero.io/source-clusterk8s-major-version=1
                         velero.io/source-clusterk8s-minor-version=26
Phase:    Completed
Namespaces:
    Included:     *
    Excluded:     <none>
Resources:
    Included:            *
    Excluded:           <none>
    Cluster-scoped:   auto
Label selector:   <none>
Storage Location:   default
Velero-Native Snapshot PVs:   auto
TTL:   720h0m0s
CSISnapshotTimeout:     10m0s
ItemOperationTimeout:   1h0m0s
Hooks:   <none>
Backup Format Version:   1.1.0
Started:         2023-09-04 21:39:22 +0300 EEST
Completed:   2023-09-04 21:39:31 +0300 EEST
Expiration:   2023-10-04 21:39:22 +0300 EEST
Total items to be backed up:   581
Items backed up:                     581
Velero-Native Snapshots:   <none included>
Für den Produktiveinsatz ist es entsprechend eine Option, beispielsweise über Prometheus Warnmeldungen zu generieren, falls ein Backup nicht funktioniert. Wenn Sie überprüfen wollen, ob die Backupdateien tatsächlich existieren, können Sie sich zudem in der Cloud Console den Inhalt des entsprechenden Storage-Buckets ansehen. Wie im Bild ersichtlich, erzeugt Velero für jede Sicherung einen Ordner und legt dort die Dateien ab.
Backups nach Zeitplan
In der zweiten Option fahren wir ein Backup zeitgesteuert. Die Velero-CLI stellt dazu die Option "Schedule" bereit, mit deren Hilfe Sie die Sicherung entsprechend steuern und CRON-Expressions übergeben können. Um jede Nacht um 1 Uhr ein Backup durchzuführen, nutzen Sie diesen Befehl:
velero schedule create cluster-daily --schedule="0 1 * * *"
Die CRON-Expressions lassen sich mit Kurzbefehlen vereinfachen. Dabei sichert "@yearly" einmal pro Jahr um Mitternacht des 1. Januars, "@monthly" einmal pro Monat am ersten Tag im Monat um Mitternacht, "@weekly" einmal pro Woche (Sonntags um Mitternacht), "@daily" jeden Tag um 0:00 Uhr und schließlich "@hourly" zu jeder vollen Stunde. Der Befehl für eine solche Sicherung schaut dann wie folgt aus:
velero schedule create cluster-daily --schedule="@daily"
Individuelle Backups
In vielen Fällen gilt es, nur ausgewählte Elemente in einem Cluster oder verschiedene Einstellungen zu sichern. Velero bietet dafür eine Reihe von Flags (denen Sie jeweils ein doppeltes Minuszeichen voranstellen müssen):
- exclude-namespaces: Komma-separierte Liste von Namespaces, die nicht Teil des Backups sein sollen.
- exclude-resources: Komma-separierte Liste von Ressourcen, die nicht gesichert werden.
- include-namespaces: Komma-separierte Liste von Namespaces, die enthalten sein sollen.
- selector: Backup nur für Objekte, die ein entsprechendes Label aufweisen.
- ttl: Definiert, wie lange eine Sicherung aufgehoben werden soll.
Um also beispielsweise ein tägliches Backup auf einen Namespace durchzuführen, erledigen Sie dies mit diesem Befehl:
velero schedule create backstage-daily-11 --schedule="0 11 * * *" --include-namespaces=backstage
Verwalten von Velero mit der CLI
Bislang bietet Velero keine grafische Benutzeroberfläche, sodass Sie alle Aufgaben mithilfe von Kubernetes-Manifesten oder der CLI erledigen müssen. Die CLI ist jedoch sehr intuitiv, sodass die Einarbeitung schnell gelingen sollte. So können Sie beispielweise relativ einfach Objekte auflisten lassen, wie zum Beispiel: Backup-Locations, Backups, Plug-ins, Restores, Schedules und Snapshot-Locations. Alle vorhandenen Sicherung zeigt Ihnen also velero get backups.
Über die CLI sind Sie auch in der Lage, Backups manuell zu löschen: velero delete backup tag2. Aber auch anspruchsvollere Aufgaben wie das Zurückspielen von Sicherungen gehen leicht von der Hand. Hier am Beispiel "initial-backup":
velero restore create --from-backup initial-backup
Auch hier ist es möglich, den aktuellen Stand des Vorgangs zu überprüfen:
velero restore describe initial-backup-20230905110339
Das beim Disaster Recovery notwendige Zurückspielen eines Deployments wollen wir an einem Beispiel demonstrieren. Dafür legen wir zunächst ein Namespace und ein NGINX-Deployment an:
kubectl create ns velero-test
kubectl create deployment nginx --image=nginx --namespace=velero-test
Anschließend erzeugen wir ein Backup:
velero create backup velero-test --include-namespaces=velero-test
Nun simulieren wir den Fehlerfall, im Beispiel durch das Löschen des Namespaces:
kubectl delete ns velero-test
An dieser Stelle wurden mit dem Namespace alle Objekte gelöscht, das heißt, auch das NGINX-Deployment ist nicht mehr existent. Die Rücksicherung muss nun so aussehen:
velero create restore --from-backup velero-test
Eine anschließende Überprüfung ergibt Gewissheit, dass das Deployment wieder da ist:
kubectl get deployments -n velero-test
NAME   READY   UP-TO-DATE   AVAILABLE   AGE
nginx     1/1              1                 1             64s
Bild 3: Unser Storage-Bucket nach erfolgreichem Backup.
Daten migrieren
Bei einer Datenmigration kann Velero auf einfache Art und Weise Objekte von einem Cluster auf einen anderen übertragen. Technisch basiert dies auf Veleros Backup- und Restore-Funktionalitäten und der Tatsache, dass der Zustand von Kubernetes-Objekten mit dem angebundenen Objektspeicher synchron gehalten wird.
Dementsprechend ist es notwendig, sowohl den Cluster, von dem Objekte kopiert werden sollen, als auch den Ziel-Cluster auf den gleichen Bucket zeigen zu lassen. Allerdings gibt hier es einige Einschränkungen:
- Eine Datenmigration funktioniert nicht zwischen verschiedenen Public-Cloud-Anbietern. So können Sie beispielsweise einen AWS-EKS-Cluster nicht mit einem Azure-Kubernetes-Service-Cluster synchron halten.
- Die Kubernetes-Version darf auf dem Ziel-Cluster nicht kleiner sein als auf dem Quell-Cluster. Eine hundertprozentige Kompatibilität liegt nur vor, wenn auf beiden Clustern die gleiche Version eingespielt ist.
- Bei AWS und Azure gibt es keine Unterstützung für eine regionsübergreifende Datenmigration. In einem solchen Fall muss ein dateibasiertes Systembackup zum Einsatz kommen.
Damit die Synchronisierung funktionieren kann, müssen Sie auf den Ziel-Cluster Velero installieren. Wie bereits oben beschrieben, können Sie dies wie folgt bewerkstelligen:
velero install \ --provider gcp \
--plugins velero/velero-plugin-for-gcp:v1.6.0 \
--bucket $BUCKET \
--secret-file ./credentials-velero
Sobald die Installation erfolgreich war, können Sie sich via velero get backups auf dem zweiten Cluster überzeugen, dass alle Backupobjekte aus dem Objektspeicher gelesen wurden. Anschließend lässt sich auf dem zweiten Cluster die Sicherung einspielen.
Fazit
Velero ist schnell zu installieren und einfach zu bedienen. Das Projekt existiert seit rund sechs Jahren und hat im Kubernetes-Ökosystem mittlerweile weite Verbreitung erlangt. An dem Projekt wird aktiv weitergearbeitet und neue Versionen erfreuen durch immer mehr Features.
(jp)
Link-Codes