
Immer häufiger erreichen uns Anfragen von Kunden: „Wir möchten etwas wie Amazon RDS, aber günstiger“; „Wir möchten etwas wie RDS, aber überall, in jeder Infrastruktur“. Um eine ähnliche verwaltete Lösung auf Kubernetes zu realisieren, haben wir uns den aktuellen Stand der beliebtesten Operatoren für PostgreSQL (Stolon, Operatoren von Crunchy Data und Zalando) angesehen und unsere Wahl getroffen.
Dieser Artikel ist unsere gesammelte Erfahrung sowohl aus theoretischer Sicht (Überblick über die Lösungen) als auch aus praktischer Sicht (was gewählt wurde und was dabei herauskam). Aber zuerst lassen Sie uns klären, welche Anforderungen an einen potenziellen Ersatz für RDS gestellt werden...
Was ist RDS?
Wenn Menschen von RDS sprechen, meinen sie aus unserer Erfahrung in der Regel einen verwalteten (managed) DB-Service, der:
- einfach konfiguriert werden kann;
- die Möglichkeit bietet, mit Snapshots zu arbeiten und aus diesen wiederherzustellen (vorzugsweise mit Unterstützung von );
- die Erstellung von Master-Slave-Topologien ermöglicht;
- eine umfangreiche Liste von Erweiterungen besitzt;
- Audit und Benutzer-/Zugangsverwaltung bereitstellt.
Generell können die Ansätze zur Realisierung der gestellten Aufgabe sehr unterschiedlich sein, jedoch distanziert sich unser Weg mit dem bedingten Ansible. (Ein ähnliches Fazit zogen auch unsere Kollegen von 2GIS infolge ihrer ein „Werkzeug zum schnellen Bereitstellen eines ausfallsicheren Clusters auf Basis von Postgres“ zu erstellen.)
Operatoren sind der allgemein akzeptierte Ansatz zur Lösung solcher Aufgaben im Kubernetes-Ökosystem. Mehr dazu in Bezug auf Datenbanken, die innerhalb von Kubernetes betrieben werden, berichtete der technische Direktor von „Flanta“ , in .
NB: Für die schnelle Erstellung einfacher Operatoren empfehlen wir unsere Open Source-Utility . Damit lässt sich dies ohne Kenntnisse in Go und auf für Systemadministratoren vertrauten Wegen umsetzen: mit Bash, Python etc.
Für PostgreSQL gibt es mehrere beliebte K8s-Operatoren:
- Stolon;
- Crunchy Data PostgreSQL Operator;
- Zalando Postgres Operator.
Schauen wir uns diese genauer an.
Die Wahl des Operators
Neben den bereits genannten wichtigen Funktionen erwarteten wir – als Ingenieure für Infrastrukturmanagement in Kubernetes – auch Folgendes von den Operatoren:
- Deployment aus Git und mit ;
- Unterstützung von Pod-Anti-Affinität;
- Festlegung von Node-Affinität oder Node-Selector;
- Festlegung von Toleranzen;
- mögliche Tuning-Optionen;
- verständliche Technologien und sogar Befehle.
Ohne auf die Details jedes Punktes einzugehen (fragen Sie in den Kommentaren, wenn Sie nach dem Lesen des gesamten Artikels Fragen dazu haben), möchte ich insgesamt anmerken, dass diese Parameter nötig sind, um die Spezialisierung der Clusterknoten feiner zu beschreiben, damit wir sie für bestimmte Anwendungen anfordern können. So können wir ein optimales Gleichgewicht zwischen Leistung und Kosten erzielen.
Jetzt kommen wir zu den PostgreSQL-Operatoren.
1. Stolon
von der italienischen Firma Sorint.lab in wurde als gewisser Maßstab unter den Operatoren für Datenbanken betrachtet. Es handelt sich um ein ziemlich altes Projekt: Die erste öffentliche Version erschien bereits im November 2015 (!), und das GitHub-Repository kann mit fast 3000 Sternen und über 40 Mitwirkenden aufwarten.
Und tatsächlich ist Stolon ein hervorragendes Beispiel für durchdachte Architektur:

Die Details dieses Operators sind im Bericht zu finden oder . Insgesamt lässt sich sagen, dass er alles kann, was beschrieben wurde: Failover, Proxy für transparenten Zugriff von Clients, Backups … Dabei bieten die Proxys Zugriff über einen einzigen Service-Endpunkt — im Gegensatz zu den beiden anderen Lösungen, die weiter unten behandelt werden (bei denen es zwei Services für den Zugriff auf die Datenbank gibt).
Allerdings hat Stolon , weshalb er nicht so bereitgestellt werden kann, dass man einfach und schnell — „wie frische Brötchen“ — Datenbankinstanzen in Kubernetes erstellen kann. Das Management erfolgt über das Tool stolonctl, die Bereitstellung erfolgt über ein Helm-Chart, und benutzerdefinierte Einstellungen werden im ConfigMap definiert.
Einerseits ist es so, dass der Operator nicht wirklich ein Operator ist (da er keine CRDs verwendet). Andererseits ist es ein flexibles System, das es ermöglicht, Ressourcen in K8s so anzupassen, wie es Ihnen gefällt.
Zusammenfassend erschien es uns nicht optimal, einen separaten Chart für jede DB zu erstellen. Daher begannen wir, nach Alternativen zu suchen.
2. Crunchy Data PostgreSQL Operator
, einem jungen amerikanischen Start-up, erschien als logische Alternative. Seine öffentliche Geschichte begann mit dem ersten Release im März 2017. Seitdem hat das GitHub-Repository etwas weniger als 1300 Sterne und über 50 Mitwirkende erhalten. Das letzte Release von September wurde auf die Nutzung mit Kubernetes 1.15—1.18, OpenShift 3.11+ und 4.4+, GKE und VMware Enterprise PKS 1.3+ getestet.
Die Architektur des Crunchy Data PostgreSQL Operators erfüllt ebenfalls die angegebenen Anforderungen:

Das Management erfolgt über das Tool pgo, jedoch generiert sie im Gegenzug benutzerdefinierte Ressourcen für Kubernetes. Deshalb haben wir als potenzielle Nutzer eine erfreuliche Nachricht vom Operator erhalten:
- es gibt eine Verwaltung über CRD;
- benutzerfreundliche Verwaltung von Benutzern (auch über CRD);
- Integration mit anderen Komponenten — eine spezialisierte Sammlung von Container-Images für PostgreSQL und Werkzeugen zur Arbeit damit (einschließlich pgBackRest, pgAudit, Erweiterungen aus contrib usw.).
Allerdings haben die Versuche, den Operator von Crunchy Data zu nutzen, einige Probleme aufgezeigt:
- Es gab keine Möglichkeit für tolerations — es war nur nodeSelector vorgesehen.
- Die erstellten Pods waren Teil des Deployments, obwohl wir eine Statefull-Anwendung bereitgestellt haben. Im Gegensatz zu StatefulSets können Deployments keine Festplatten erstellen.
Dieser letzte Nachteil führt zu amüsanten Momenten: In der Testumgebung konnten wir 3 Replikate mit einer Festplatte starten, lokaler Speicher, was dazu führte, dass der Operator meldete, dass 3 Replikate laufen (obwohl das nicht der Fall war).
Ein weiteres Merkmal dieses Operators ist seine fertige Integration mit verschiedenen Hilfssystemen. Beispielsweise ist es einfach, pgAdmin und pgBounce zu installieren, während vorgestellt werden vorkonfigurierte Grafana und Prometheus. Im jüngsten wird besonders die verbesserte Integration mit dem Projekt , wodurch der Operator eine anschauliche Visualisierung von Metriken für PgSQL "out of the box" anbietet.
Dennoch hat die seltsame Auswahl an generierten Kubernetes-Ressourcen uns dazu gebracht, nach einer anderen Lösung zu suchen.
3. Zalando Postgres Operator
Die Produkte von Zalando sind uns seit langem bekannt: Wir haben Erfahrung mit Zalenium und natürlich haben wir versucht — ihrer beliebten HA-Lösung für PostgreSQL. Über den Ansatz des Unternehmens zur Erstellung des hat einer seiner Autoren — Alexey Klyukin — im Rahmen von , und wir fanden es interessant.
Dies ist die jüngste Lösung in dem Artikel: Die erste Veröffentlichung fand im August 2018 statt. Dennoch hat das Projekt, trotz der wenigen formellen Releases, einen langen Weg zurückgelegt und hat bereits das Lösung von Crunchy Data mit über 1300 Sternen auf GitHub und der höchsten Anzahl an Mitwirkenden (über 70) überholt.
„Unter der Haube“ dieses Operators werden zeitbewährte Lösungen verwendet:
- Patroni und für das Management,
- — für Backups,
- — als Verbindungspool.
So wird die Architektur des Zalando-Operators dargestellt:

Der Operator wird vollständig über Custom Resources verwaltet, erstellt automatisch ein StatefulSet aus Containern, die dann durch das Hinzufügen verschiedener Sidecar-Container in das Pod angepasst werden können. All dies ist ein erheblicher Vorteil im Vergleich zum Operator von Crunchy Data.
Da wir uns für die Lösung von Zalando aus 3 in Betracht gezogenen Optionen entschieden haben, werden unten die Möglichkeiten beschrieben, zusammen mit der praktischen Anwendung.
Praxis mit dem Postgres-Operator von Zalando
Der Deployment des Operators erfolgt sehr einfach: Es genügt, die aktuelle Version von GitHub herunterzuladen und die YAML-Dateien aus dem Verzeichnis . Alternativ können Sie auch .
Nach der Installation sollten Sie die Konfiguration in Betracht ziehen. Diese erfolgt über ConfigMap postgres-operator im Namensraum, in dem Sie den Operator installiert haben. Wenn die Speicher konfiguriert sind, kann der erste PostgreSQL-Cluster bereitgestellt werden.
Zum Beispiel sieht unser Standard-Deployment folgendermaßen aus:
apiVersion: acid.zalan.do/v1
kind: postgresql
metadata:
name: staging-db
spec:
numberOfInstances: 3
patroni:
synchronous_mode: true
postgresql:
version: "12"
resources:
limits:
cpu: 100m
memory: 1Gi
requests:
cpu: 100m
memory: 1Gi
sidecars:
- env:
- name: DATA_SOURCE_URI
value: 127.0.0.1:5432
- name: DATA_SOURCE_PASS
valueFrom:
secretKeyRef:
key: password
name: postgres.staging-db.credentials
- name: DATA_SOURCE_USER
value: postgres
image: wrouesnel/postgres_exporter
name: prometheus-exporter
resources:
limits:
cpu: 500m
memory: 100Mi
requests:
cpu: 100m
memory: 100Mi
teamId: staging
volume:
size: 2Gi
Dieses Manifest stellt einen Cluster aus 3 Instanzen mit einem Sidecar zum Abrufen von Metriken der Anwendung bereit. Wie Sie sehen, ist alles sehr einfach, und wenn gewünscht, können Sie buchstäblich unbegrenzt viele Cluster erstellen.
Es ist auch erwähnenswert, dass es eine Weboberfläche zur Verwaltung — . Diese wird zusammen mit dem Operator bereitgestellt und ermöglicht das Erstellen und Löschen von Clustern sowie das Arbeiten mit Backups, die der Operator erstellt.

Liste der PostgreSQL-Cluster

Backup-Verwaltung
Eine weitere interessante Funktion ist die Unterstützung . Dieses System erstellt automatisch Rollen in PostgreSQL, basierend auf der erhaltenen Liste von Benutzernamen. Danach ermöglicht die API die Rückgabe einer Liste von Benutzern, für die automatisch Rollen erstellt werden.
Probleme und deren Lösung
Die Verwendung des Operators hat jedoch bald mehrere erhebliche Nachteile aufgezeigt:
- fehlende Unterstützung für nodeSelector;
- Unmöglichkeit, Backups abzuschalten;
- bei der Verwendung der Funktion zur Erstellung von Datenbanken erscheinen keine Standardberechtigungen;
- gelegentlich fehlt die Dokumentation oder sie ist nicht aktuell.
Glücklicherweise können viele dieser Probleme gelöst werden. Fangen wir am Ende an – Probleme mit Dokumentation.
Wahrscheinlich werden Sie feststellen, dass es nicht immer klar ist, wie man ein Backup definiert und wie man den Backup-Bucket mit der Operator UI verbindet. Dies wird in der Dokumentation nur am Rande erwähnt, aber eine konkrete Beschreibung gibt es in :
- es muss ein Geheimnis erstellt werden;
- dieses an den Operator im Parameter
pod_environment_secret_nameim CRD mit den Einstellungen des Operators oder im ConfigMap (je nachdem, wie Sie sich entschieden haben, den Operator zu installieren).
Allerdings stellte sich heraus, dass dies derzeit nicht möglich ist. Aus diesem Grund haben wir unsere mit einigen zusätzlichen externen Funktionen gesammelt. Näheres dazu siehe unten.
Wenn Sie dem Operator Parameter für Backups übergeben, insbesondere – wal_s3_bucket und Zugriffsschlüssel für AWS S3, dann wird er alles sichern: nicht nur Datenbanken in der Produktion, sondern auch in der Staging-Umgebung. Das war für uns nicht akzeptabel.
In der Beschreibung der Parameter für Spilo, das die grundlegende Docker-Hülle für PgSQL bei Verwendung des Operators ist, stellte sich heraus: Man kann den Parameter WAL_S3_BUCKET leer übergeben, wodurch Backups deaktiviert werden. Darüber hinaus fand sich zu großer Freude auch ein , den wir sofort in unser Fork akzeptiert haben. Jetzt reicht es, einfach enableWALArchiving: false zur Ressource des PostgreSQL-Clusters hinzuzufügen.
Ja, es gab die Möglichkeit, es anders zu machen, indem man 2 Operatoren startete: einen für Staging (ohne Backups) und einen für Produktion. Aber so konnten wir mit einem auskommen.
Okay, wir haben gelernt, wie man den Datenbanken Zugriff auf S3 gibt und die Backups beginnen im Speicher zu landen. Wie lassen sich die Backup-Seiten in der Operator UI zum Laufen bringen?

In der Operator UI müssen 3 Variablen hinzugefügt werden:
-
SPILO_S3_BACKUP_BUCKET -
AWS_ACCESS_KEY_ID -
AWS_SECRET_ACCESS_KEY
Nach dieser Änderung wird die Verwaltung der Backups verfügbar, was in unserem Fall die Arbeit mit Staging erleichtert und es ermöglicht, Schnappschüsse aus der Produktion dort ohne zusätzliche Skripte zu übertragen.
Ein weiterer Pluspunkt war die Arbeit mit der Teams API und die umfangreichen Möglichkeiten zur Erstellung von Datenbanken und Rollen mit Hilfe des Operators. Allerdings hatten die erstellten Rollen keine Standardrechte. Dementsprechend konnte ein Benutzer mit Leserechten keine neuen Tabellen lesen.
Warum ist das so? Obwohl im Code benötigte GRANT, werden sie bei Weitem nicht immer angewendet. Es gibt 2 Methoden: syncPreparedDatabases und syncDatabases. In syncPreparedDatabases — obwohl es in der Sektion preparedDatabases eine Bedingung gibt defaultRoles und defaultUsers für die Erstellung von Rollen — standardmäßige Berechtigungen werden nicht angewendet. Wir arbeiten an einem Patch, um diese Berechtigungen automatisch anzuwenden.
Und der letzte Punkt in unseren aktuellen Verbesserungen — , der Node Affinity zu dem erstellten StatefulSet hinzufügt. Unsere Kunden ziehen es oft vor, Kosten zu sparen, indem sie Spot-Instanzen verwenden, auf denen deutlich keine DB-Dienste platziert werden sollten. Dieses Problem könnte auch durch Toleranzen gelöst werden, aber die Verfügbarkeit von Node Affinity gibt mehr Sicherheit.
Was ist herausgekommen?
Infolge der Lösung der genannten Probleme haben wir den Postgres Operator von Zalando in , wo er mit so nützlichen Patches gebaut wird. Und zur Erleichterung haben wir auch .
Liste der PRs, die in den Fork aufgenommen wurden:
- ;
- ;
- ;
- .
Es wäre großartig, wenn die Community diese PRs unterstützen würde, damit sie mit der nächsten Version des Operators (1.6) in den Upstream gelangen.
Bonus! Erfolgsgeschichte zur Migration von Produktion
Wenn Sie Patroni verwenden, können Sie live Produktion mit minimalen Ausfallzeiten zum Operator migrieren.
Spilo ermöglicht die Erstellung von Standby-Clustern über S3-Speicher mit , wobei das binäre Log PgSQL zuerst in S3 gespeichert und dann von einem Replica heruntergeladen wird. Aber was ist, wenn Sie nicht Wal-E in einer alten Infrastruktur verwenden? Die Lösung dieses Problems wurde bereits auf Habré.
Hier kommt die logische Replikation von PostgreSQL ins Spiel. Lassen Sie uns jedoch nicht ins Detail gehen, wie man Publikationen und Abonnements erstellt, denn... unser Plan ist gescheitert.
Das Problem ist, dass es in der DB mehrere stark genutzte Tabellen mit Millionen von Zeilen gab, die zudem ständig ergänzt und gelöscht wurden. c copy_data, bei dem eine neue Replica den gesamten Inhalt vom Master kopiert, konnte einfach nicht mit dem Master Schritt halten. Das Kopieren des Inhalts hat eine Woche gedauert, aber es hat den Master nie eingeholt. Letztendlich hat uns die Klärung des Problems Kollegen von Avito geholfen: Man kann die Daten mit pg_dumpverschieben. Ich werde unsere (ein wenig angepasste) Variante dieses Algorithmus beschreiben.
Die Idee besteht darin, ein deaktiviertes Abonnement, das an einen bestimmten Replikationsslot gebunden ist, zu erstellen und dann die Transaktionsnummer zu korrigieren. Es gab Replikate für den Betrieb der Produktion. Das ist wichtig, weil das Replikat helfen wird, ein konsistentes Dump zu erstellen und weiterhin Änderungen vom Master zu empfangen.
In den folgenden Befehlen, die den Migrationsprozess beschreiben, werden die folgenden Bezeichnungen für die Hosts verwendet:
- master — Ursprungsserver;
- replica1 — Streaming-Replikat auf dem alten Produktionssystem;
- replica2 — neues logisches Replikat.
Migrationsplan
1. Erstellen wir auf dem Master ein Abonnement für alle Tabellen im Schema public der Datenbank dbname:
psql -h master -d dbname -c "CREATE PUBLICATION dbname FOR ALL TABLES;"
2. Erstellen wir einen Replikationsslot auf dem Master:
psql -h master -c "select pg_create_logical_replication_slot('repl', 'pgoutput');"
3. Stoppen wir die Replikation auf der alten Replik:
psql -h replica1 -c "select pg_wal_replay_pause();"
4. Erhalten wir die Transaktionsnummer vom Master:
psql -h master -c "select replay_lsn from pg_stat_replication where client_addr = 'replica1';"
5. Machen wir ein Dump von der alten Replik. Wir werden dies in mehreren Threads tun, was den Prozess beschleunigt:
pg_dump -h replica1 --no-publications --no-subscriptions -O -C -F d -j 8 -f dump/ dbname
6. Laden wir das Dump auf den neuen Server:
pg_restore -h replica2 -F d -j 8 -d dbname dump/
7. Nach dem Laden des Dumps können wir die Replikation auf der Streaming-Replik starten:
psql -h replica1 -c "select pg_wal_replay_resume();"
7. Erstellen wir ein Abonnement auf der neuen logischen Replik:
psql -h replica2 -c "create subscription oldprod connection 'host=replica1 port=5432 user=postgres password=secret dbname=dbname' publication dbname with (enabled = false, create_slot = false, copy_data = false, slot_name='repl');"
8. Erhalten wir oid des Abonnements:
psql -h replica2 -d dbname -c "select oid, * from pg_subscription;"
9. Angenommen, wir haben erhalten oid=1000. Wenden wir die Transaktionsnummer auf das Abonnement an:
psql -h replica2 -d dbname -c "select pg_replication_origin_advance('pg_1000', 'AA/AAAAAAAA');"
10. Starten wir die Replikation:
psql -h replica2 -d dbname -c "alter subscription oldprod enable;"
11. Überprüfen wir den Status des Abonnements, die Replikation sollte funktionieren:
psql -h replica2 -d dbname -c "select * from pg_replication_origin_status;"
psql -h master -d dbname -c "select slot_name, restart_lsn, confirmed_flush_lsn from pg_replication_slots;"
12. Nachdem die Replikation gestartet wurde und die Datenbanken synchronisiert sind, kann der Umschaltvorgang durchgeführt werden.
13. Nach der Deaktivierung der Replikation müssen die Sequenzen korrigiert werden. Dies ist gut beschrieben .
Dank dieses Plans verlief der Umschaltvorgang mit minimalen Verzögerungen.
Fazit
Kubernetes-Operatoren ermöglichen es, verschiedene Aktionen zu vereinfachen, indem sie sie auf die Erstellung von K8s-Ressourcen reduzieren. Allerdings sollte man, nachdem man eine bemerkenswerte Automatisierung mit ihrer Hilfe erreicht hat, beachten, dass sie auch eine Reihe unerwarteter Nuancen mit sich bringen kann. Daher sollte man bei der Auswahl der Operatoren weise vorgehen.
Nach der Betrachtung der drei beliebtesten Kubernetes-Operatoren für PostgreSQL haben wir uns für das Projekt von Zalando entschieden. Es gab einige Schwierigkeiten, aber das Ergebnis hat uns wirklich erfreut, weshalb wir planen, diese Erfahrung auch auf einige andere PgSQL-Installationen auszuweiten. Wenn Sie Erfahrungen mit ähnlichen Lösungen haben, würden wir uns freuen, Details in den Kommentaren zu sehen!
P.S.
Lesen Sie auch in unserem Blog:
- «»;
- «»;
- «».
Quelle: habr.com
