Heutzutage sind Hochverfügbarkeit und Datenintegrität die wichtigsten Aspekte in der Welt der Datenbanken. Ausfallzeiten und Datenverluste können für jedes Unternehmen sehr kostspielig sein. Eine Möglichkeit, dies zu vermeiden, ist die Implementierung eines Failover-Mechanismus. Failover ist ein Mechanismus, der es einem System ermöglicht, weiter zu funktionieren – möglicherweise auf einem reduzierten Niveau – anstatt bei einem Ausfall vollständig zu versagen. In diesem Artikel werden wir besprechen, wie Patroni mit Failover umgeht.
Voraussetzungen
Ein vollständig funktionsfähiger PostgreSQL-Cluster auf Basis von Patroni mit Backups. Falls Sie keinen haben, können Sie unserem früheren Blogbeitrag folgen, um einen PostgreSQL-Cluster auf Basis von Patroni einzurichten.
Patroni Failover
Patroni verwendet einen verteilten Konsensalgorithmus wie etcd, ZooKeeper oder Consul, um unter den Knoten des Datenbankclusters einen Leader-Knoten zu wählen. Der Leader-Knoten ist für das Bearbeiten von Schreibanforderungen verantwortlich, während die Standby-Knoten Daten vom Leader replizieren, um Datenredundanz sicherzustellen. Fällt der Leader-Knoten aus, wählen die Standby-Knoten einen neuen Leader und übernehmen weiterhin die Schreibanforderungen.
Fall 1: Ausfall des Leader-Knotens
In diesem Abschnitt simulieren wir den Ausfall eines Leader-Knotens und sehen, wie Patroni damit umgeht. In einem unserer vorherigen Blogposts haben wir einen 3-Knoten-PostgreSQL-Cluster auf AWS EC2-Instanzen bereitgestellt. Zunächst sollten wir prüfen, ob alle Knoten derzeit laufen und gesund sind. Das können wir tun, indem wir uns auf einem der Knoten anmelden und den folgenden Befehl ausführen:
podman exec -it patroni-container patronictl list
Die Ausgabe sollte ähnlich der folgenden aussehen:
+ Cluster: superman (101010101010101010) ---+----+-----------+
| Member | Host | Role | State | TL | Lag in MB |
+----------+-------------+---------+----------+----+-----------+
| ec2-id-1 | 1.x.x.x | Leader | running | 1 | |
| ec2-id-2 | 2.x.x.x | Replica | running | 1 | 0 |
| ec2-id-3 | 3.x.x.x | Replica | running | 1 | 0 |
+----------+-------------+---------+----------+----+-----------+
Wenn alle Knoten im Zustand running
sind, können wir mit dem nächsten Schritt fortfahren.
Nun simulieren wir einen Ausfall des Leader-Knotens, indem wir den PostgreSQL-Dienst auf dem Leader-Knoten stoppen. Wir können die EC2-Instanz, auf der der Leader-Knoten läuft, einfach beenden. In der Spalte member
sehen wir, dass der Leader-Knoten ec2-id-1
ist. Wir beenden also die EC2-Instanz mit der ID ec2-id-1
.
Wenn wir den Status des Clusters überprüfen, sehen wir, dass der Cluster keinen Leader-Knoten mehr hat. Das liegt daran, dass der Leader ausgefallen ist und die Standby-Knoten noch versuchen, einen neuen Leader zu wählen. Wir können den Status des Clusters überprüfen, indem wir erneut den folgenden Befehl ausführen:
podman exec -it patroni-container patronictl list
Die Ausgabe sollte ähnlich der folgenden sein:
+ Cluster: superman (101010101010101010) ---+----+-----------+
| Member | Host | Role | State | TL | Lag in MB |
+----------+-------------+---------+----------+----+-----------+
| ec2-id-2 | 2.x.x.x | Replica | running | 1 | 0 |
| ec2-id-3 | 3.x.x.x | Replica | running | 1 | 0 |
+----------+-------------+---------+----------+----+-----------+
Nach einigen Momenten wird ein neuer Leader-Knoten gewählt. Wir können den Status des Clusters erneut mit demselben Befehl überprüfen. Die Ausgabe sollte ähnlich der folgenden sein, falls der Leader-Knoten gewählt wurde:
+ Cluster: superman (101010101010101010) ---+----+-----------+
| Member | Host | Role | State | TL | Lag in MB |
+----------+-------------+---------+----------+----+-----------+
| ec2-id-2 | 2.x.x.x | Replica | running | 2 | 0 |
| ec2-id-3 | 3.x.x.x | Leader | running | 2 | |
+----------+-------------+---------+----------+----+-----------+
Fall 2: Ausfall des gesamten Clusters
In diesem Abschnitt simulieren wir den Ausfall eines gesamten Clusters und sehen, wie Patroni damit umgeht. Dies wäre der Extremfall, bei dem alle Knoten im Cluster ausfallen. Wie zuvor benötigen wir einen vollständig funktionsfähigen PostgreSQL-Cluster auf Basis von Patroni. Wir können denselben Cluster wie zuvor verwenden. Denken Sie auch daran, dass der Cluster ein Backup haben sollte. Spilo bietet einen WAL-E/WAL-G-Backup-Mechanismus, den wir in diesem Beispiel verwenden werden. Wenn Sie kein Backup haben, können Sie einem unserer früheren Blogbeiträge folgen, um ein Backup mit WAL-G im Spilo-Container-Image einzurichten.
Nun simulieren wir den Ausfall des gesamten Clusters, indem wir alle PostgreSQL-Dienste stoppen. Wir können einfach alle EC2-Instanzen beenden, die den PostgreSQL-Dienst ausführen. In der Spalte member
sehen wir, dass noch 2 Mitglieder übrig sind, nämlich ec2-id-2
und ec2-id-3
. Also beenden wir die EC2-Instanzen mit den IDs ec2-id-2
und ec2-id-3
.
Zu diesem Zeitpunkt sollten nur noch die EC2-Instanzen übrig sein, die den etcd-Dienst ausführen.
Nun werden wir 3 Knoten mit derselben Patroni/Spilo-Konfiguration wie zuvor bereitstellen. Dies können wir tun, indem wir das Ansible-Playbook ausführen, das wir zuvor verwendet haben. Der Befehl sollte folgendermaßen aussehen:
ansible-playbook init-patroni-cluster.yml
Nachdem das Playbook ausgeführt wurde, können wir uns auf einem der Knoten anmelden und den Status des Clusters erneut mit demselben Befehl überprüfen:
podman exec -it patroni-container patronictl list
Wenn wir zu schnell sind, werden wir feststellen, dass der Cluster noch keinen Leader-Knoten hat. Dies liegt daran, dass die Standby-Knoten noch versuchen, einen neuen Leader zu wählen. Nach einigen Momenten können wir den Status des Clusters erneut prüfen. Die Ausgabe sollte ähnlich der folgenden sein, wenn der Leader-Knoten gewählt wurde:
+ Cluster: superman (101010101010101010) ---+----+-----------+
| Member | Host | Role | State | TL | Lag in MB |
+-----------+-------------+---------+----------+----+-----------+
| new-ec2-1 | 2.x.x.x | Leader | running | 3 | |
| new-ec2-2 | 3.x.x.x | Replica | running | 3 | 0 |
| new-ec2-3 | 4.x.x.x | Replica | running | 3 | 0 |
+-----------+-------------+---------+----------+----+-----------+
Beachten Sie, dass sich die TL (Timeline) von 2 auf 3 erhöht hat. Dies liegt daran, dass der Cluster aus dem Backup wiederhergestellt wurde und ein neuer Leader-Knoten gewählt wurde.
Fazit
In diesem Blogpost haben wir besprochen, wie Patroni mit Failover umgeht. Wir haben zwei Fälle simuliert: den Ausfall eines Leader-Knotens und den Ausfall des gesamten Clusters. Wir haben auch gesehen, wie Patroni auf diese Fälle reagiert. Das Beste daran ist, dass Patroni diese Situationen automatisch bewältigen kann, ohne menschliches Eingreifen! Dies ist besonders nützlich in Produktionsumgebungen, in denen Ausfallzeiten und Datenverluste sehr teuer sein können. Wir hoffen, dass dieser Blogpost Ihnen hilft, das Failover-Mechanismus von Patroni besser zu verstehen.

Dirk Aumüller
Dirk Aumueller arbeitet als Associate Partner für die Proventa AG. Sein technologischer Schwerpunkt liegt bei Datenbankarchitekturen mit PostgreSQL sowie Data Management Lösungen mit Pentaho. Zusätzlich zu seinen Datenbanktransformations-Projekteinsätzen ist er regelmäßig als PostgreSQL Trainer unterwegs und betreut Studenten bei ihren Abschlussarbeiten. Seine fachlichen Erfahrungen erstrecken sich über die Branchen Telco und Financial Services.