Von Dennis Vinueza auf Mittwoch, 13. Januar 2021
Kategorie: Remote Service

PostgreSQL: Schöner Replizieren mit Log Shipping Standby Server

PostgreSQL verfügt per se über ein Hochverfügbarkeitsfeature, welches auf dem Prinzip der Datenreplikation über das Transaktionslog basiert. Beim Log Shipping Standby Server werden Daten, je nach gewählter Methode, über die WAL-Segmente bzw. die WAL-Buffer von einem Datenbankcluster auf einen anderen übertragen. Dabei ist zu beachten, dass immer der komplette Cluster repliziert wird, also mit allen Datenbanken, so wie man es schon beim Backup und Restore antrifft.

Die Umsetzung dieses Konzeptes ist, obwohl es das dokumentiere Standardverfahren zur Gewährleistung der Verfügbarkeit ist, eher „sperrig". Immer wieder müssen im Betrieb manuelle Eingriffe durchgeführt werden. Automatismen sind leider eher selten zu finden. So müssen beispielsweise beim Rollentausch in einem Cluster Konfigurationsdateien editiert werden, was umständlich und fehlerträchtig ist.

Hier empfehlen sich die Open Source-Tools repmgr und pgbouncer. Mit dem ersten lässt sich ein großer Teil der Replikationsadministration unter PostgreSQL übernehmen, während das zweite ein Connection Pooler für PostgreSQL ist, der Verbindungen umleiten, beenden, unterbinden und wieder zulassen kann. Beide Werkzeuge sind über das normale Linux-Repository erhältlich und auch nur unter Linux lauffähig.

Einige Voraussetzungen des repmgr (manche davon optional):


Und von pgbouncer:

Wir gehen von einem bereits existierenden und einem neu aufzusetzenden Datenbankcluster aus. Auf dem zukünftigen Standby-System bereiten wir das PGDATA-Verzeichnis sowie die Tablespace-Verzeichnisse vom Pfad identisch, aber leer, wie auf dem Primary vor.

Die Datei repmgr.conf wird auf beiden Seiten fast identisch eingerichtet. Über einen libpq-Connection-String wird eine Verbindung zum jeweiligen Replikations-Knoten angegeben, etwa:

bzw.

Weiterhin empfiehlt sich zum Überwachen des bald erfolgenden Klonungsprozesses der Parameter

Den bereits laufenden Cluster können wir zum Primary erklären

Auf dem Standby-Server können wir nun den Klonprozess starten. (Hinweis: Zum Prüfen des voraussichtlichen Erfolges bietet sich vorab die Option --dry-run an)

Nach Abschluss des Klonens wird schließlich auch die Standby-Seite registriert:

Um sich gegen den Ausfall eines kompletten Rechenzentrums abzusichern, sollten Primary- und Standby-Seite immer in verschiedenen Rechenzentren untergebracht sein. Aus Sicht des Standby-Systems kann ein Ausfall des Netzwerkes dazu führen, dass dieses System glaubt, selbst die führende Rolle übernehmen zu müssen, obwohl der Primary-Server weiter einwandfrei arbeitet. Dies kann zu einer fatalen Split-Brain-Situation führen, in der beide Seiten aktiv werden.

Hier kann ein zusätzlicher Witness-Server Abhilfe schaffen. Dabei handelt es sich um einen separaten Datenbankcluster, der noch Kontakt zum Primary-Server hat, aber nicht an der Replikation selbst teilnimmt, sondern dazu dient, mit beiden Replikationspartnern Kontakt zu halten.

Der Witness-Server wird über eine Verbindung zum Primary gestartet:

Status und Typ der beteiligten Server können über das folgende Kommando abgefragt werden:

Es gibt nun für das Umschalten auf den Standby mehrere Möglichkeiten:

Eine Wiedereingliederung des alten Primary als Standby kann auch erfolgen. Falls der Primary so unvermittelt beendet wurde, dass der Standby vor der Beförderung noch nicht aufholen konnte, muss der zukünftige Standby mit der Option --force-rewind "zurückgespult" werden, um beide wieder auf einen konsistenten Stand zu bringen.

Nun fehlt noch der Fall eines Failovers. Hierfür wird der systemd-Dienst repmgrd zwingend benötigt, da dieser den Clusterstatus überwacht. Weiterhin muss beidseitig in der repmgr.conf jeweils der folgende Parameter gesetzt sein:

Das erwähnte Skript promote.sh soll für eine Beförderung des Standbys, sowie für eine Neukonfiguration vom pgbouncer sorgen. Eine Grundkonfiguration vom pgbouncer existiert bereits in der Datei /etc/pgbouncer/pgbouncer.ini. U.a. sind diese Parameter zu prüfen:

In der letzten include-Datei legen wir die Verbindungsinformationen zu der momentanen DB auf dem Primary ab. Der Inhalt besteht wieder aus einem libpq-ähnlichen Connection-String, mit dem wir uns zu einer Datenbank ordix verbinden:

Das Skript promote12.sh kann folgenden Aufbau haben und muss auf beiden Seiten vorhanden sein:

Öffnet man jetzt eine Verbindung zu pgbouncer auf Port 6432, so leitet dieser auf den Primary unter Port 5432 weiter. Eine Ausnahme stellt die explizite Angabe des Namens pgbouncer anstelle des Datenbanknamens (statt z.B. ordix) dar. In so einem Fall landet man auf einer Admin-Konsole, von der aus man administrative Tasks wie z.B. pausedatabase absetzen kann. Dort lässt sich prüfen, auf welchem Server man gelandet ist:

Beim Switch- oder Failover wird nun das Skript promote12.sh aufgerufen, welches folgende Schritte ausführt:

Hinweis: Vor PostgreSQL 12 konnte man das Skript noch unter dem Parameter service_promote_command eintragen und promote_command wie ursprünglich belassen. Da sich die Methode zur Beförderung mit Version 12 aber geändert hat, ist das nun nicht mehr so möglich.

Wenn die Session aus dem oberen Abschnitt die ganze Zeit verbunden war, so lässt sich nun beobachten, dass sich die IP-Adresse des Servers ändert, weil in der include-Datei der Hostname ausgetauscht wurde.

Fazit

Das Repertoire vom repmgr umfasst Tools, mit denen das Einrichten, Überwachen und Umschalten zwischen verschiedenen Replikationskonten sehr komfortabel möglich ist: Die Nutzung der werkseitigen Tools ist wesentlich komplexer und aufwändiger

Die Replikation und die Anbindung an den pgbouncer funktioniert, und auch das Umschalten ist recht komfortabel. Die Anbindung erfordert jedoch mehr Aufwand bei der Verskriptung und kann dadurch anfälliger für Fehler sein.  

Glossar

RDBMS: Steht für Relationales Datenbankmanagementsystem.
Ein RDBMS verwaltet Datenbanken mitsamt ihren Objekten, sorgt u.a. für die Einhaltung von Constraints (Randbedingungen) und Isolation gleichzeitig stattfindender Datenabfragen.

(Datenbank-)Cluster: Stellt unter PostgreSQL das Äquivalent zu einer
Datenbankinstanz dar. In einem Cluster sind immer mehrere Datenbanken vorhanden, die voneinander unabhängige Daten besitzen, aber dieselben Tablespaces und User verwenden können.

WAL: "Write-Ahead Log" ist unter PostgreSQL die Entsprechung für Transaktionsprotokolle. Datenänderungen werden in WALs protokolliert, um sie im Fehlerfall wiederholbar zu machen und dienen bei der Replikation zur Datenübertragung zwischen einzelnen Datenbankclustern. Bei WAL-Segmenten handelt es sich um Dateien im Filesystem, bei WAL-Buffern um eine Memory-Struktur.

Primary: Der Clusterknoten, auf den schreibend zugegriffen werden kann. Nur ein solcher Knoten ist erlaubt.

Standby: Passiver Clusterknoten, der durch den Primary synchron gehalten wird und auch lesend zugreifbar sein kann. Es kann mehrere derartige Knoten geben.

Promoten / Demoten: Wenn ein Standby zum Primary erklärt wird, so wird er promotet („befördert"). Umgekehrt wird ein Primary, der zum Standby wird, demotet („degradiert").

Switchover: Ist der kontrollierte Tausch der Clusterrollen von Primary und Standby zum jeweils anderen Typ, also wechselseitiges Promoten und Demoten

Failover: Ist das automatische Promoten des Standbys, falls der Primary ausfällt. Ein automatisches Demoten des alten Primaries muss bzw. kann dabei nicht zwingend stattfinden.

libpq(-Connectionstring): Bei libpq handelt es ich um die C-Programmierschnittstelle für PostgreSQL. Die Datenbankverbindung wird dabei über eine Reihe von Schlüsselworten hergestellt, z.B. Datenbank-, Benutzername und Host.

Kommentare hinterlassen