Datenbanken
Datenbanken legst du als Custom Resource in deinem Namespace an. Die Operatoren laufen bereits im Cluster, du musst nichts installieren.
PostgreSQL (CloudNativePG)
Gruppe und Version: postgresql.cnpg.io/v1, Kind Cluster.
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
name: app-db
spec:
instances: 3
storage:
size: 10Gi
storageClass: hcloud-volumesEine Instanz ohne Backup ist kein Produktionsbetrieb
Ein Cluster mit instances: 1 und ohne konfiguriertes Backup ist ein Ausgangspunkt zum Ausprobieren. Für den Produktivbetrieb nimm instances: 3 und richte ein Backup-Ziel ein. Das Volume auf hcloud-volumes ist über das Netz angebunden und übersteht den Ausfall eines Knotens, aber mit einer Instanz ist die Datenbank nicht erreichbar, bis das Volume an einem anderen Knoten hängt und der Pod dort gestartet ist. Ohne Backup-Ziel gibt es keine Wiederherstellung auf einen bestimmten Zeitpunkt und nichts Konsistentes, aus dem du zurückholen kannst, wenn Daten gelöscht oder beschädigt werden oder das Volume selbst verloren geht.
Wird sein Knoten ersetzt, startet ein Cluster mit instances: 1 samt Volume auf einem anderen Knoten neu und ist bis dahin nicht erreichbar. Behält der Cluster sein PodDisruptionBudget (die Voreinstellung), setzt die Plattform für diese Zeit spec.nodeMaintenanceWindow am Cluster und entfernt das Feld danach wieder. Mit zwei oder mehr Instanzen wechselt der Primary vorher auf eine andere Instanz.
In einen PostgreSQL-Pod kommst du nicht per Shell
kubectl exec in einen CloudNativePG-Pod wird abgelehnt:
Error from server: admission webhook denied the request:
Exec/attach is only allowed into gVisor-sandboxed pods.Deine eigenen Workloads laufen sandboxed und akzeptieren exec ganz normal. PostgreSQL-Pods sind die Ausnahme, das betrifft also nur PostgreSQL. In MariaDB- und Dragonfly-Pods kommst du wie überall sonst hinein.
kubectl port-forward ist davon nicht betroffen. Der übliche Weg, SQL gegen deine eigene Datenbank auszuführen, ist deshalb: Port weiterleiten und mit einem lokalen Client verbinden, mit den Zugangsdaten, die der Operator erzeugt hat. Ein kurzlebiger psql-Pod im Namespace funktioniert genauso.
MariaDB (mariadb-operator)
Gruppe: k8s.mariadb.com, Kind MariaDB.
apiVersion: k8s.mariadb.com/v1alpha1
kind: MariaDB
metadata:
name: app-db
spec:
rootPasswordSecretKeyRef:
name: app-db-root
key: password
storage:
size: 10Gi
storageClassName: hcloud-volumesDragonfly
Gruppe und Version: dragonflydb.io/v1alpha1, Kind Dragonfly.
apiVersion: dragonflydb.io/v1alpha1
kind: Dragonfly
metadata:
name: cache
spec:
replicas: 2Erreichbar ist die Instanz unter redis://<name>:6379, im Beispiel oben also redis://cache:6379.
Dragonfly spricht das Redis-Wire-Protokoll, die meisten Clients funktionieren deshalb ohne Anpassung. Es gibt allerdings dokumentierte Unterschiede im Verhalten einzelner Befehle. Teste deine Anwendung, bevor du eine bestehende Redis-Instanz ablöst.
Backups
PostgreSQL und MariaDB können sich beide planmäßig sichern, in einen Bucket, der dir gehört. Ein Bucket wird nicht gestellt, das hier ist also etwas, das du einrichtest, und nichts, was du geerbt bekommst.
Wohin Backups gehen
Überallhin, wo S3 gesprochen wird. ITSH Object Storage funktioniert und ist der einfachste Weg: Leg einen Bucket und einen Zugangsschlüssel an und pack den Schlüssel in ein Secret in deinem Namespace.
Gib dem Schlüssel Lesen und Schreiben auf diesen Bucket. CloudNativePG listet den Bucket für seinen Backup-Katalog und löscht alte Backups, um die retentionPolicy durchzusetzen, und beides darf Nur Schreiben nicht.
kubectl create secret generic backup-creds \
--from-literal=ACCESS_KEY_ID='<access-key>' \
--from-literal=ACCESS_SECRET_KEY='<secret-key>'PostgreSQL
Trag ein Backup-Ziel am Cluster ein und plane es dann:
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
name: app-db
spec:
instances: 3
storage:
size: 10Gi
storageClass: hcloud-volumes
backup:
barmanObjectStore:
destinationPath: "s3://my-backups/app-db"
endpointURL: "https://storage.itsh.dev"
s3Credentials:
accessKeyId:
name: backup-creds
key: ACCESS_KEY_ID
secretAccessKey:
name: backup-creds
key: ACCESS_SECRET_KEY
retentionPolicy: "30d"
---
apiVersion: postgresql.cnpg.io/v1
kind: ScheduledBackup
metadata:
name: app-db-daily
spec:
schedule: "0 0 3 * * *"
cluster:
name: app-dbDer Zeitplan ist ein sechsstelliger Cron-Ausdruck, Sekunden zuerst. Das Beispiel läuft also täglich um 03:00 Uhr.
barmanObjectStore gibt eine Deprecation-Warnung aus
Beim Anwenden erfährst du, dass das Feld veraltet ist. CloudNativePG hat es in 1.26 so markiert, entfernt werden soll es in 1.31. Das ist erwartet: Es ist der Weg, auf dieser Plattform Backups zu konfigurieren, und das Barman Cloud Plugin, das es upstream ablöst, ist hier nicht installiert. Nutz es. Sobald das Plugin verfügbar ist, ist die Migration eine Änderung am laufenden Cluster, und deine bestehenden Backups bleiben lesbar.
MariaDB
Backup- und Restore-Ressourcen funktionieren genauso und nehmen entweder ein S3-Ziel oder ein PVC. Der Feldaufbau steht in der Dokumentation des mariadb-operator.
Zwei Grenzen, die du kennen solltest
Object Versioning, Lifecycle-Regeln und Object-Lock gibt es bei ITSH Object Storage nicht. Backups lassen sich hier also nicht unveränderlich machen: Wer in den Bucket schreiben darf, kann sie auch löschen.
Gib Backups einen eigenen Bucket und einen darauf beschränkten Zugangsschlüssel, und halt diesen Schlüssel aus Workloads heraus, die ihn nicht brauchen. Sind unveränderliche Backups für dich zwingend, sprich vorher mit dem Support, bevor du dich auf dieses Setup verlässt.
Volume-Snapshots und Point-in-Time-Wiederherstellung von Volumes gibt es nicht. Backups laufen auf Datenbankebene und werden vom Operator erstellt. Für ein PVC, das keine verwaltete Datenbank ist, gibt es kein Äquivalent. Was dir in einem einfachen Volume wichtig ist, braucht also eine eigene Kopie woanders.
Teste die Wiederherstellung
Ein Backup, das nie jemand zurückgespielt hat, ist eine Vermutung. Spiel es einmal in einen Wegwerf-Cluster zurück, bevor du es brauchst, und prüf, ob die Daten wirklich da sind.
Wie es weitergeht
- Storage für die Klassen, auf denen sie laufen
- Abrechnung und Kontingente, was eine Datenbank kostet