CloudNativePG Restore
Dieses Runbook beschreibt die Wiederherstellung eines CloudNativePG-Clusters aus einem Barman-Cloud-Backup.
Die Wiederherstellung ersetzt den bestehenden Cluster einschließlich seiner Pods und PersistentVolumeClaims. Die im Cluster-Objekt konfigurierte Storage-Größe und Storage-Konfiguration müssen unverändert übernommen werden.
Voraussetzungen
-
Zugriff auf den Kubernetes-Cluster mit
kubectl -
Zugriff auf Flux mit der
fluxCLI -
Ein vorhandenes und lesbares CloudNativePG-Backup
-
Das zugehörige Barman-Object-Store-Objekt ist vorhanden
-
Das vom Object Store referenzierte Secret ist vorhanden
Die folgenden Variablen werden in den Beispielen verwendet:
export NAMESPACE=paperless-ngx
export CLUSTER=cnpg-paperless-ngx
export KUSTOMIZATION=paperless
export RECOVERY_FILE="${CLUSTER}-recovery.yaml"
Ablauf
1. Flux-Kustomization pausieren
Die verwaltende Flux-Kustomization pausieren, damit Flux den Cluster während der Wiederherstellung nicht auf den Git-Zustand zurücksetzt:
flux suspend kustomization "${KUSTOMIZATION}" \
--namespace flux-system
Status prüfen:
flux get kustomization "${KUSTOMIZATION}" \
--namespace flux-system
Die Kustomization muss als suspendiert angezeigt werden.
2. Cluster-Objekt exportieren
Das bestehende Cluster-Objekt als bereinigtes YAML exportieren:
kubectl -n "${NAMESPACE}" get cluster.postgresql.cnpg.io "${CLUSTER}" \
-o yaml |
kubectl neat > "${RECOVERY_FILE}"
Falls kubectl neat nicht verfügbar ist, das Objekt zunächst vollständig exportieren:
kubectl -n "${NAMESPACE}" get cluster.postgresql.cnpg.io "${CLUSTER}" \
-o yaml > "${RECOVERY_FILE}"
In diesem Fall vor dem erneuten Anwenden mindestens folgende serverseitig verwaltete Felder entfernen:
-
metadata.creationTimestamp -
metadata.generation -
metadata.resourceVersion -
metadata.uid -
metadata.managedFields -
status
Die exportierte Datei dient als Grundlage für den Recovery-Cluster. Insbesondere die folgenden Einstellungen müssen aus dem bestehenden Objekt erhalten bleiben:
-
spec.instances -
spec.imageName -
spec.storage -
Ressourcenanforderungen und Limits
-
Affinity und Scheduling
-
Monitoring
-
Backup-Plugins
-
weitere anwendungsspezifische Einstellungen
|
Die Storage-Konfiguration darf nicht aus einem generischen Beispiel übernommen werden. Größe, StorageClass und weitere Storage-Einstellungen müssen dem exportierten Cluster-Objekt entsprechen. |
3. Recovery-Konfiguration eintragen
In der Receovery-Datei unter spec.bootstrap den vorhandenen Abschnitt initdb durch recovery ersetzen.
Zusätzlich spec.externalClusters ergänzen. Beispiel:
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
name: cnpg-paperless-ngx
namespace: paperless-ngx
spec:
instances: 1
imageName: ghcr.io/cloudnative-pg/postgresql:18-standard-trixie
storage:
size: 50Gi
bootstrap:
recovery:
source: origin
database: paperless
owner: paperless
externalClusters:
- name: origin
plugin:
name: barman-cloud.cloudnative-pg.io
parameters:
barmanObjectName: cnpg-paperless-ngx
serverName: cnpg-paperless-ngx
plugins:
- name: barman-cloud.cloudnative-pg.io
isWALArchiver: true
parameters:
barmanObjectName: cnpg-paperless-ngx
Dabei gilt:
-
bootstrap.recovery.sourcemuss dem Namen unterexternalClustersentsprechen. -
databaseundownermüssen der ursprünglicheninitdb-Konfiguration entsprechen. -
barmanObjectNamemuss auf das vorhandene Object-Store-Objekt verweisen. -
serverNamemuss dem Namen entsprechen, unter dem die Sicherungen abgelegt wurden. -
spec.storagemuss vollständig aus dem ursprünglichen Cluster übernommen werden. -
Der bestehende Abschnitt
spec.pluginsfür die spätere Archivierung bleibt erhalten.
4. Cluster löschen
Das bestehende CloudNativePG-Cluster-Objekt löschen:
kubectl -n "${NAMESPACE}" delete cluster.postgresql.cnpg.io "${CLUSTER}"
Warten, bis alle zugehörigen Pods gelöscht wurden:
kubectl -n "${NAMESPACE}" wait \
--for=delete pod \
--selector="cnpg.io/cluster=${CLUSTER}" \
--timeout=10m
Prüfen, ob noch zugehörige Pods oder PersistentVolumeClaims vorhanden sind:
kubectl -n "${NAMESPACE}" get pods \
--selector="cnpg.io/cluster=${CLUSTER}"
kubectl -n "${NAMESPACE}" get pvc \
--selector="cnpg.io/cluster=${CLUSTER}"
Mit dem nächsten Schritt erst fortfahren, wenn keine zum Cluster gehörenden Pods und PersistentVolumeClaims mehr vorhanden sind.
Falls PVCs noch vorhanden sind, deren Status und Finalizer prüfen:
kubectl -n "${NAMESPACE}" get pvc \
--selector="cnpg.io/cluster=${CLUSTER}" \
-o wide
kubectl -n "${NAMESPACE}" describe pvc \
--selector="cnpg.io/cluster=${CLUSTER}"
Finalizer nicht ohne vorherige Prüfung der Ursache entfernen.
5. Recovery-Cluster anwenden
Die vorbereitete Cluster-Ressource anwenden:
kubectl apply -f "${RECOVERY_FILE}"
Cluster, Pods und PVCs beobachten:
kubectl -n "${NAMESPACE}" get \
cluster.postgresql.cnpg.io,pods,pvc \
--watch
Während der Wiederherstellung wird ein Full-Recovery-Pod gestartet. Dessen Logs können über das Cluster-Label verfolgt werden:
kubectl -n "${NAMESPACE}" logs \
--selector="cnpg.io/cluster=${CLUSTER}" \
--all-containers \
--follow \
--prefix
6. Recovery validieren
Warten, bis der Cluster den Status Ready erreicht:
kubectl -n "${NAMESPACE}" wait \
--for=condition=Ready \
cluster.postgresql.cnpg.io/"${CLUSTER}" \
--timeout=30m
Anschließend prüfen:
kubectl -n "${NAMESPACE}" get \
cluster.postgresql.cnpg.io "${CLUSTER}"
kubectl -n "${NAMESPACE}" get pods \
--selector="cnpg.io/cluster=${CLUSTER}" \
-o wide
kubectl -n "${NAMESPACE}" get pvc \
--selector="cnpg.io/cluster=${CLUSTER}" \
-o wide
Erwarteter Zustand:
-
Der CloudNativePG-Cluster ist
Ready. -
Die erwartete Anzahl Instanzen ist verfügbar.
-
Der primäre PostgreSQL-Pod ist
Ready. -
Alle benötigten PVCs sind
Bound. -
Die erwartete StorageClass und Storage-Größe werden verwendet.
-
In den Logs sind keine Recovery- oder PostgreSQL-Fehler vorhanden.
-
Die Anwendung kann auf die wiederhergestellte Datenbank zugreifen.
7. Bootstrap-Konfiguration zurücksetzen
Nach erfolgreicher Wiederherstellung das Cluster-Objekt bearbeiten:
kubectl -n "${NAMESPACE}" edit \
cluster.postgresql.cnpg.io "${CLUSTER}"
Unter spec.bootstrap den Abschnitt recovery wieder durch die ursprüngliche initdb-Konfiguration ersetzen:
spec:
bootstrap:
initdb:
database: paperless
owner: paperless
Den vollständigen Abschnitt spec.externalClusters entfernen.
Die Änderung beeinflusst den bereits initialisierten Datenbank-Cluster nicht. Sie stellt den normalen deklarativen Zustand für spätere GitOps-Abgleiche wieder her.
8. Flux-Kustomization fortsetzen
Vor dem Fortsetzen sicherstellen, dass die Cluster-Definition im Git-Repository der normalen Konfiguration mit bootstrap.initdb entspricht.
Flux anschließend fortsetzen:
flux resume kustomization "${KUSTOMIZATION}" \
--namespace flux-system
Der Restore ist abgeschlossen, wenn der CloudNativePG-Cluster und die verwaltende Flux-Kustomization den Status Ready besitzen.
Disaster Recovery
Bei einem Disaster Recovery kann der Namespace noch nicht vorhanden sein. In diesem Fall kann das bestehende Cluster-Objekt nicht exportiert werden.
Vor dem Erstellen des Recovery-Clusters müssen mindestens folgende Ressourcen vorhanden sein:
-
Ziel-Namespace
-
Barman-Object-Store-Objekt
-
vom Object Store referenziertes Secret
-
CloudNativePG- und Barman-Cloud-CRDs
-
erforderliche Operatoren und Plugins
Ressourcen prüfen:
kubectl get namespace "${NAMESPACE}"
kubectl -n "${NAMESPACE}" get objectstore
kubectl -n "${NAMESPACE}" get secret
Falls Namespace, Object Store oder Secret durch Flux bereitgestellt werden, zunächst die zuständige Kustomization abgleichen:
flux reconcile kustomization "${KUSTOMIZATION}" \
--namespace flux-system \
--with-source
Danach erneut prüfen:
kubectl get namespace "${NAMESPACE}"
kubectl -n "${NAMESPACE}" get objectstore
kubectl -n "${NAMESPACE}" get secret
Den Recovery-Cluster erst anwenden, wenn Object Store und Secret vorhanden sind.
Falls der ursprüngliche Cluster nicht mehr exportiert werden kann, die Cluster-Definition aus dem Git-Repository als Grundlage verwenden. Dort ausschließlich:
-
bootstrap.initdbdurchbootstrap.recoveryersetzen -
externalClustersergänzen
Alle übrigen Einstellungen, insbesondere spec.storage, unverändert übernehmen.
Fehleranalyse
Recovery-Pod startet nicht
Prüfen:
kubectl -n "${NAMESPACE}" get events \
--sort-by=.lastTimestamp
kubectl -n "${NAMESPACE}" describe \
cluster.postgresql.cnpg.io "${CLUSTER}"
kubectl -n "${NAMESPACE}" get pods \
--selector="cnpg.io/cluster=${CLUSTER}"
Typische Ursachen:
-
Object-Store-Objekt fehlt
-
referenziertes Secret fehlt
-
falscher
barmanObjectName -
falscher
serverName -
Backup ist nicht erreichbar
-
StorageClass ist nicht verfügbar
-
PVC kann nicht provisioniert werden
Abschlusskontrolle
kubectl -n "${NAMESPACE}" get \
cluster.postgresql.cnpg.io,pods,pvc
flux get kustomization "${KUSTOMIZATION}" \
--namespace flux-system
Der Restore gilt als erfolgreich, wenn:
-
der CloudNativePG-Cluster
Readyist -
der PostgreSQL-Pod betriebsbereit ist
-
alle PVCs
Boundsind -
die wiederhergestellten Daten verfügbar sind
-
bootstrap.initdbwieder konfiguriert ist -
externalClustersentfernt wurde -
Flux wieder aktiv und fehlerfrei ist