27 Februar 2019

Integration von Patroni in Debian

Kategorien: HowTos PostgreSQL
Tags: Ansible Debian Patroni PostgreSQL

Patroni ist eine Hochverfügbarkeitslösung für PostgreSQL mit einem Fokus auf Container-Technologie und Kubernetes. Die bisher vorhandenen Debian-Pakete mussten bislang aufwendig von Hand konfiguriert werden und haben sich nicht in die Distribution integriert. Für das bald erscheinende Debian 10 „Buster“ wurde Patroni nun von credativ in das Debian Standard PostgreSQL-Framework integriert und erlaubt einen einfachen Aufbau von Patroni-Clustern unter Debian.

Aufgrund der Verwendung eines externen „Distributed Consensus Store“ (DCS) wie Etcd, Consul oder Zookeeper kann Patroni zuverlässig Leader-Election und automatisierte Failover durchführen. Dazu kommen planbare Switchover und eine einfache Änderung der Cluster-weiten Konfiguration. Es bietet außerdem eine REST-Schnittstelle, mit der z.B. via HAProxy ein Load-Balancing aufgebaut werden kann. Auf Grund dieser Vorteile hat Patroni in letzter Zeit das früher häufig verwendete Pacemaker als Open Source Projekt der Wahl für die Herstellung einer PostgreSQL-Hochverfügbarkeit abgelöst.

Viele unserer Kunden verwenden allerdings PostgreSQL auf Debian- oder Ubuntu-Systemen. Hier hat sich Patroni bisher nicht gut in das System integriert. So verwendete es nicht das postgresql-common Framework und wird nicht wie übliche Instanzen in pg_lsclusters angezeigt.

Integration in Debian

In Zusammenarbeit mit dem Patroni-Hauptentwickler Alexander Kukushkin von Zalando ist es nun gelungen, das Debian Patroni-Paket weitgehend in das postgresql-common-Framework zu integrieren. Dies geschah sowohl durch Änderungen in Patroni, als auch durch zusätzliche Programme im Debian-Paket. Die aktuelle Version 1.5.5 von Patroni, die alle diese Änderungen enthält, ist nun auch in Debian „Buster“ (testing) verfügbar und kann für den Aufbau von Patroni-Clustern unter Debian verwendet werden.

Zur Verfügung stehen die Pakete auch auf apt.postgresql.org und sind damit auch unter Debian 9 „Stretch“ und Ubuntu 18.04 „Bionic Beaver“ LTS benutzbar. Außerdem kann so jede beliebige PostgreSQL-Version von 9.4 bis 11 verwendet werden.

Wichtigster Punkt ist hierbei die automatische Erstellung einer geeigneten Patroni-Konfiguration mit dem Befehl pg_createconfig_patroni. Der Aufruf erfolgt analog zu pg_createcluster mit der gewünschten Major-Version und dem Instanz-Namen als Parameter:

pg_createconfig_patroni 11 test

Dieser Aufruf erstellt eine Datei /etc/patroni/11-test.yml, wobei die Konfiguration für das DCS aus der Datei /etc/patroni/dcs.yml verwendet wird, die entsprechend dem lokalen Setup angepasst werden muss. Der Rest der Konfiguration entstammt dem Template /etc/patroni/config.yml.in, welches von sich aus lauffähig ist, vom Nutzer aber auch an die eigenen Bedürfnisse angepasst werden kann. Anschließend kann die Patroni-Instanz analog zu regulären PostgreSQL-Instanzen via systemd gestartet werden:

systemctl start patroni@11-test

Cluster-Aufbau in wenigen Schritten

Ein einfacher 3-Knoten Patroni-Cluster kann also mit den wenigen folgenden Befehlen erstellt und gestartet werden, wobei die drei Knoten pg1, pg2 und pg3 als Hostnamen angenommen werden, sowie dass es eine lokale Datei dcs.yml für die DCS-Konfiguration gibt:

for i in pg1 pg2 pg3; do ssh $i 'apt -y install postgresql-common'; done
for i in pg1 pg2 pg3; do ssh $i 'sed -i "s/^#create_main_cluster = true/create_main_cluster = false/" /etc/postgresql-common/createcluster.conf'; done
for i in pg1 pg2 pg3; do ssh $i 'apt -y install patroni postgresql'; done
for i in pg1 pg2 pg3; do scp ./dcs.yml $i:/etc/patroni; done
for i in pg1 pg2 pg3; do ssh @$i 'pg_createconfig_patroni 11 test' && systemctl start patroni@11-test'; done

Danach kann man den Status des Patroni-Clusters folgendermaßen ansehen:

ssh pg1 'patronictl -c /etc/patroni/11-patroni.yml list'
+---------+--------+------------+--------+---------+----+-----------+
| Cluster | Member |    Host    |  Role  |  State  | TL | Lag in MB |
+---------+--------+------------+--------+---------+----+-----------+
| 11-test |  pg1   | 10.0.3.111 | Leader | running |  1 |           |
| 11-test |  pg2   | 10.0.3.41  |        | stopped |    |   unknown |
| 11-test |  pg3   | 10.0.3.46  |        | stopped |    |   unknown |
+---------+--------+------------+--------+---------+----+-----------+

Man sieht, dass eine Leader Election durchgeführt wurde und pg1 der Primary wurde. Dieser hat seine Instanz mit dem Debian-spezifischen pg_createcluster_patroni Programm erstellt, welches im Hintergrund pg_createcluster aufruft. Darauf klonen sich die anderen beiden Instanzen vom Primary mit dem pg_clonecluster_patroni Programm, welches eine Instanz mit pg_createcluster erstellt und dann einen Standby via pg_basebackup vom Primary erstellt. Danach sind alle Knoten im Status running:

+---------+--------+------------+--------+---------+----+-----------+
| Cluster | Member |    Host    |  Role  |  State  | TL | Lag in MB |
+---------+--------+------------+--------+---------+----+-----------+
| 11-test |  pg1   | 10.0.3.111 | Leader | running |  1 |         0 |
| 11-test |  pg2   | 10.0.3.41  |        | running |  1 |         0 |
| 11-test |  pg3   | 10.0.3.46  |        | running |  1 |         0 |
+---------+--------+------------+--------+---------+----+-----------+

Die altbekannten Debian postgresql-common Befehle funktionieren ebenfalls:

ssh pg1 'pg_lsclusters'
Ver Cluster Port Status Owner    Data directory                 Log file
11  test    5432 online postgres /var/lib/postgresql/11/test    /var/log/postgresql/postgresql-11-test.log

Failover-Verhalten

Wenn der Primary Knoten abrupt abgeschaltet wird, wird sein Leader Token nach einiger Zeit auslaufen und Patroni dann einen Failover mit anschließender erneuter Leader Election durchführen:

+---------+--------+-----------+------+---------+----+-----------+
| Cluster | Member |    Host   | Role |  State  | TL | Lag in MB |
+---------+--------+-----------+------+---------+----+-----------+
| 11-test |  pg2   | 10.0.3.41 |      | running |  1 |         0 |
| 11-test |  pg3   | 10.0.3.46 |      | running |  1 |         0 |
+---------+--------+-----------+------+---------+----+-----------+
[...]
+---------+--------+-----------+--------+---------+----+-----------+
| Cluster | Member |    Host   |  Role  |  State  | TL | Lag in MB |
+---------+--------+-----------+--------+---------+----+-----------+
| 11-test |  pg2   | 10.0.3.41 | Leader | running |  2 |         0 |
| 11-test |  pg3   | 10.0.3.46 |        | running |  1 |         0 |
+---------+--------+-----------+--------+---------+----+-----------+
[...]
+---------+--------+-----------+--------+---------+----+-----------+
| Cluster | Member |    Host   |  Role  |  State  | TL | Lag in MB |
+---------+--------+-----------+--------+---------+----+-----------+
| 11-test |  pg2   | 10.0.3.41 | Leader | running |  2 |         0 |
| 11-test |  pg3   | 10.0.3.46 |        | running |  2 |         0 |
+---------+--------+-----------+--------+---------+----+-----------+

Sobald der alte Primary erneut gestartet wird, kehrt er als Standby in den Cluster-Verbund zurück:

+---------+--------+------------+--------+---------+----+-----------+
| Cluster | Member |    Host    |  Role  |  State  | TL | Lag in MB |
+---------+--------+------------+--------+---------+----+-----------+
| 11-test |  pg1   | 10.0.3.111 |        | running |    |   unknown |
| 11-test |  pg2   | 10.0.3.41  | Leader | running |  2 |         0 |
| 11-test |  pg3   | 10.0.3.46  |        | running |  2 |         0 |
+---------+--------+------------+--------+---------+----+-----------+
[...]
+---------+--------+------------+--------+---------+----+-----------+
| Cluster | Member |    Host    |  Role  |  State  | TL | Lag in MB |
+---------+--------+------------+--------+---------+----+-----------+
| 11-test |  pg1   | 10.0.3.111 |        | running |  2 |         0 |
| 11-test |  pg2   | 10.0.3.41  | Leader | running |  2 |         0 |
| 11-test |  pg3   | 10.0.3.46  |        | running |  2 |         0 |
+---------+--------+------------+--------+---------+----+-----------+

Falls dies aufgrund von zusätzlichen Transaktionen in seiner alten Zeitleiste nicht möglich ist, wird er neu erstellt. Im Falle von sehr großen Datenmengen kann auch pg_rewind verwendet werden, hierfür muss allerdings ein Passwort für den postgres-Nutzer gesetzt und reguläre Datenbank-Verbindungen (im Gegensatz zu Replikations-Verbindungen) zwischen den Cluster-Knoten erlaubt werden.

Weitere Instanzen erstellen

Es ist ferner möglich weitere Instanzen mit pg_createconfig_patroni zu erstellen, dabei kann man entweder einen PostgreSQL Port explizit mit der --port-Option angeben oder pg_createconfig_patroni den nächsten freien Port (wie von pg_createcluster bekannt) nehmen lassen:

for i in pg1 pg2 pg3; do ssh $i 'pg_createconfig_patroni 11 test2 && systemctl start patroni@11-test2'; done
ssh pg1 'patronictl -c /etc/patroni/11-test2.yml list'
+----------+--------+-----------------+--------+---------+----+-----------+
| Cluster  | Member |       Host      |  Role  |  State  | TL | Lag in MB |
+----------+--------+-----------------+--------+---------+----+-----------+
| 11-test2 |  pg1   | 10.0.3.111:5433 | Leader | running |  1 |         0 |
| 11-test2 |  pg2   |  10.0.3.41:5433 |        | running |  1 |         0 |
| 11-test2 |  pg3   |  10.0.3.46:5433 |        | running |  1 |         0 |
+----------+--------+-----------------+--------+---------+----+-----------+

Ansible Playbook zum Download

Zur einfachen Erstellung eines 3-Wege Patroni Clusters haben wir auch ein Ansible-Playbook auf Github erstellt. Dieses automatisiert die Installation und Einrichtung von PostgreSQL und Patroni auf den drei Knoten, sowie eines DCS-Servers auf einem vierten Knoten.

Unterstützung

Falls Sie Unterstützung bei PostgreSQL, Patroni, PostgreSQL auf Debian oder anderer Aspekte von Hochverfügbarkeit benötigen, steht Ihnen unser PostgreSQL Competence Center zur Verfügung – Falls gewünscht auch 24 Stunden am Tag, an 365 Tagen im Jahr.

Wir freuen uns über Ihre Kontaktaufnahme.

Kategorien: HowTos PostgreSQL
Tags: Ansible Debian Patroni PostgreSQL


Beitrag teilen: