Hochverfügbare Datenbankumgebungen stellen die Grundlage für zuverlässig funktionierende und rasch skalierbare Applikationen dar. Wer Datenbanken auf Basis von MySQL oder MariaDB ausfallsicher betreiben möchte, wird immer wieder von Galera Cluster hören. Diese Lösung spielt eine entscheidende Rolle bei der häufig eingesetzten Multi-Master-Architektur.
Gemeint ist damit, dass mehrere Datenbankknoten synchron miteinander interagieren, um eine hochverfügbare und ausfallsichere Datenbankinfrastruktur zu schaffen. In diesem Ratgeber wirst du lernen, wie man ein Galera Cluster für MySQL konzipiert und schließlich auf Basis von Red Hat 9 aufsetzt. Wichtig ist mir hierbei eine praxisorientierte Vorgehensweise.
Schließlich soll es im späteren Betrieb nicht zu Dateninkonsistenzen, hohen Latenzen oder gar zu Konflikten kommen. Gemeinsam werden wir die Schlüsselkomponenten beleuchten, die eine erfolgreiche Konfiguration ausmachen, einschließlich Netzwerkeinstellungen, Sicherheitsaspekte, sowie Strategien zur Lastenverteilung und Ressourcenoptimierung.
Wie Galera Cluster funktionieren:
Ein Informatiker, der an Galera Cluster denkt, assoziiert unmittelbar Begriffe wie altbacken oder überholt mit dem Produkt. Dem ist aber gar nicht so. Ein solches Datenbank-Cluster kann man zum Beispiel über mehrere, entfernte Standorte hinweg betreiben. Wer möchte, kann die Kommunikation zwischen den einzelnen Nodes nämlich mithilfe von SSL-Zertifikaten verschlüsseln.
Des Weiteren erkennt der Cluster-Manager rasch, wenn bestimmte Nodes aufgrund hoher Latenzen die gesamte Performance des Datenbank-Clusters negativ beeinflussen. Solche Cluster-Knoten können dann automatisch entfernt werden. Doch das ist längst nicht alles, was man als Schlüsseleigenschaft von Galera bezeichnen könnte. Doch fangen wir bei den Grundlagen an.
Im Wesentlichen zusammengefasst, funktioniert ein Galera Cluster so:
- Clustering: Lese- und Schreibzugriffe auf jedem Knoten und zu jeder Zeit. Es existieren also keine unnützen Slaves und eine VIP wird auch nicht benötigt. Bei einem Failover kommt es natürlich auch nicht zu einer kurzen Downtime.
- Replikation: Die Datenbanken werden in Echtzeit synchronisiert. Daher gehen bei einem Knotenausfall keinerlei Daten verloren. Zudem ist der Datenbestand jederzeit auf allen Nodes identisch.
Galera Cluster ist der Branchenstandard für hochverfügbare MySQL oder MariaDB Deployments. Das liegt nicht zuletzt an der leichten Einrichtung und praktischen Administration. So können dem Cluster binnen kurzer Zeit weitere Server hinzugefügt werden. Und das ganz ohne das lästige Erstellen und Einspielen von Datenbank-Dumps.
Ausfallsicherheit & Datenreplikation:
Bevor es an die Installation und Konfiguration der Server gehen kann, müssen erstmal die Grundlagen des Galera Cluster Betriebs geklärt werden. Für ein ausfallsicheres Datenbank-Cluster sind mindestens drei Server erforderlich. Das liegt am eingesetzten Quorum-Prinzip, was bedeutet, dass ein Cluster-Knoten ausfallen kann, solange zwei Drittel der Cluster-Nodes weiterhin verfügbar sind.
Konkret bedeutet dies, dass bei fünf Nodes bereits zwei Instanzen ausfallen können, und bei sieben Cluster-Knoten können drei Nodes gleichzeitig wegbrechen, während der Galera Cluster weiterhin funktionsfähig bleibt. Nach einem solchen Szenario müssen die ausgefallenen und nun wieder lauffähigen Nodes noch ihren Datenbestand synchronisieren.
Dafür gibt es in Galera Clustern 2 Verfahrensweisen:
- State Snapshot Transfers (SST): Hierbei handelt es sich um eine Übertragung der gesamten Daten.
- Incremental State Transfer (IST): In so einem Fall werden nur die fehlenden Daten übertragen.
Bei einer kurzen Ausfalldauer können die fehlenden Daten via Incremental State Transfer von einem anderen Cluster-Knoten geholt werden. In der Praxis wird dafür meist die Software rsync genutzt. Sollte sich der Ausfall hingegen über längere Zeit hingezogen haben, muss ein State Snapshot Transfer ausgelöst werden. Und dieser hat es leider in sich.
Während dessen kann es nämlich zu Beeinträchtigungen bei Schreib- und Leseoperationen kommen. Zum Glück ist so ein SST nur ganz selten notwendig. Geschickte Datenbank-Administratoren erhöhen nämlich die Größe des Gcache, einer Art Journaling-Log. Damit kann man auch nach längeren Downtimes einen Incremental State Transfer nutzen.
Dies hilft, den Wiederherstellungsprozess zu beschleunigen und den Einfluss auf die laufenden Operationen zu minimieren. Im Gegensatz zum State Snapshot Transfer (SST) wird hier kein Cluster-Node für die Dauer des Daten-Rebuilds in den Read-Only-Modus versetzt. Ein gewaltiger Vorteil! An dieser Stelle möchte ich aber den Exkurs in den Bereich der State Transfers beenden.
Galera Cluster mit MySQL bauen:
In den folgenden Zeilen werde ich intensiv auf die Installation und Konfiguration von Galera Cluster in Kombination mit MySQL eingehen. Natürlich bringt so ein hochverfügbares Datenbank-Cluster aber wenig, wenn man davor nicht noch ein Loadbalancer-Pärchen einsetzt. Die Inbetriebnahme solch einer Lastverteilung ist aber nicht mehr Teil dieses Artikels. Dort findest du mehr Informationen.
Stattdessen möchte ich noch auf ein paar Basics eingehen, damit dem erfolgreichen Betrieb eines Galera Clusters nichts mehr im Wege steht. So sollte auf jedem Server ein NTP-Client, wie zum Beispiel Chronyd installiert sein. Zusätzlich ist es von großem Vorteil, wenn die Netzwerkverbindung eine Geschwindigkeit von 2,5 Gigabit oder sogar 10 Gigabit aufweist.
Wer will, kann zudem die Cluster-Kommunikation in eigenes VLan auslagern. Weiterhin ist viel RAM sinnvoll. Ein großer Buffer-Pool beschleunigt nämlich die Antwortzeiten bei Lesezugriffen ungemein. Außerdem kann der Gcache deutlich größer ausfallen. Und zu guter Letzt sei noch erwähnt, dass SELinux oder AppArmor korrekt konfiguriert werden müssen. Das behandle ich hier aber nicht.
Schritt 1 – Firewallkonfiguration:
Die korrekte Einrichtung der Firewall ist für ein Galera Cluster entscheidend, um die Kommunikation zwischen den Cluster-Nodes zu ermöglichen und sicherzustellen, dass der Datenbank-Cluster reibungslos funktioniert. Welche Ports das in der Praxis genau sind und welche Aufgabe sie im Galera Cluster exakt haben, erfährst du in den folgenden Zeilen:
- Port 3306 / TCP: Hierbei handelt es sich um den Standard-Port für MySQL. Genutzt wird er für Client-Verbindungen und den State Snapshot Transfer mittels des Tools mysqldump.
- Port 4567 / TCP & UDP: Hier rüber wird der gesamte Replikationsverkehr des Galera Cluster abgewickelt.
- Port 4568 / TCP: Sobald der Incremental State Transfer seinen Job verrichten möchte, baut er eine Verbindung zu diesem Port auf.
- Port 4444 / TCP: Alle Varianten des State Snapshot Transfer bis auf mysqldump stellen auf diesem Port eine Verbindung her.
Wie man die oben aufgeführten Ports in der Firewall korrekt öffnet, ist von Applikation zu Applikation unterschiedlich. Deshalb habe ich mich dazu entschieden, das Ganze anhand von IPtables sowie Firewalld zu demonstrieren.
IPtables korrekt einstellen:
# Regeln anlegen:
iptables -A INPUT -m state --state NEW -m tcp -p tcp --dport 3306 -m comment --comment "mysql port" -j ACCEPT
iptables -A INPUT -m state --state NEW -m tcp -p tcp --dport 4567 -m comment --comment "galera cluster communication TCP" -j ACCEPT
iptables -A INPUT -m state --state NEW -m udp -p udp --dport 4567 -m comment --comment "galera cluster communication UDP" -j ACCEPT
iptables -A INPUT -m state --state NEW -m tcp -p tcp --dport 4444 -m comment --comment "incremental state transfers" -j ACCEPT
iptables -A INPUT -m state --state NEW -m tcp -p tcp --dport 4568 -m comment --comment "state snapshot transfers" -j ACCEPT
# Regeln speichern:
service iptables save oder alternativ dazu kann man die obigen Regeln in die Datei /etc/sysconfig/iptables hineinschreiben.
# IPtables neu starten:
service iptables restart
# Alle Regeln anzeigen lassen:
iptables -L -v
Firewalld richtig einrichten:
# Firewalld-Zonen ausgeben lassen:
firewall-cmd --get-active-zones
# Regeln erstellen:
firewall-cmd --zone=public --add-port=3306/tcp --permanentfirewall-cmd --zone=public --add-rich-rule='rule family="ipv4" port port="3306" protocol="tcp" accept' --permanent --add-rich-rule comment="mysql-port"
firewall-cmd --zone=public --add-port=4567/tcp --permanentfirewall-cmd --zone=public --add-rich-rule='rule family="ipv4" port port="4567" protocol="tcp" accept' --permanent --add-rich-rule comment="galera cluster communication TCP"
firewall-cmd --zone=public --add-port=4567/udp --permanentfirewall-cmd --zone=public --add-rich-rule='rule family="ipv4" port port="4567" protocol="udp" accept' --permanent --add-rich-rule comment="galera cluster communication UDP"
firewall-cmd --zone=public --add-port=4444/tcp --permanentfirewall-cmd --zone=public --add-rich-rule='rule family="ipv4" port port="4444" protocol="tcp" accept' --permanent --add-rich-rule comment="incremental state transfers"
firewall-cmd --zone=public --add-port=4568/tcp --permanentfirewall-cmd --zone=public --add-rich-rule='rule family="ipv4" port port="4568" protocol="tcp" accept' --permanent --add-rich-rule comment="state snapshot transfers"
# Firewalld-Konfiguration speichern:
firewall-cmd --reload
# Alle Regeln anzeigen lassen:
firewall-cmd --zone=public --list-ports
Schritt 2 – Repository einbinden:
Für das Aufsetzen eines Galera Clusters benötigt man spezifische Software wie Galera 4.0 sowie deren eigene MySQL-Integration in Version 8.0. In den Standard-Paketquellen sucht man allerdings vergebens nach beiden Paketnamen. Red Hat 9 und dessen kostenlosen Klonen muss man also erstmal weitere Repository-Informationen hinzuzufügen. Dies geht zum Glück recht einfach.
Man muss lediglich eine Datei mit der Endung .repo im Ordner /etc/yum.repos.d/ hinterlegen. Selbstredend muss man darin noch ein paar Details festlegen, wie zum Beispiel die Paketquellenanmen. In unserem Fall sind das Galera sowie MySQL-wsrep. Ebenfalls muss das Betriebssystem noch wissen, wo es die benötigten Pakete findet. Dies gelingt mittels der Baseurl-Angabe.
Generell wären diese Informationen bereits ausreichend. Allerdings ist es ratsam, zusätzlich den Pfad zum GPG-Schlüssel anzugeben und mithilfe der Variable gpgcheck zu definieren, ob eine Prüfung bei der Software-Installation durchgeführt werden soll. 1 steht dabei für ja und 0 gibt an, dass die Überprüfung nicht durchgeführt werden soll. Am Ende kommt dabei die folgende Datei heraus:
cat <<EOF > /etc/yum.repos.d/galera.repo
[galera4]
name = Galera
baseurl = https://releases.galeracluster.com/galera-4/redhat/9/x86_64
gpgkey = https://releases.galeracluster.com/GPG-KEY-galeracluster.com
gpgcheck = 1
[mysql-wsrep8]
name = MySQL-wsrep
baseurl = https://releases.galeracluster.com/mysql-wsrep-8.0/redhat/9/x86_64
gpgkey = https://releases.galeracluster.com/GPG-KEY-galeracluster.com
gpgcheck = 1
EOF
Seit Red Hat 9 gibt es verschärfte Sicherheitsstandards und GPG-Schlüssel, die auf dem SHA-1-Algorithmus basieren, werden nicht mehr akzeptiert. Daher müssen wir an dieser Stelle die kryptografischen Richtlinien auf unserem System nach unten setzen oder die Prüfung für dieses Repository abschalten. Ich habe mich für Ersteres entschieden und daher folgenden Befehl im Terminal abgesetzt:
update-crypto-policies --set LEGACY
Wirksam wird das Ganze aber erst nach einem Reboot. Bedenken sollte man allerdings, dass das Herabsetzen der Sicherheitsstandards globale Auswirkungen hat. So werden zum Beispiel wieder kürzere Pub-Keys bei der SSH-Authentifizierung akzeptiert. Zum Abschluss dieses Abschnitts prüfe ich noch, ob ein neuer Yum-Cache gebildet werden kann und starte das System neu:
yum clean all && yum makecache && systemctl reboot
Schritt 3 – Galera & MySQL installieren:
Endlich ist es so weit und nach all den Vorbereitungen kann es mit der obligatorischen Software-Installation losgehen. Mithilfe von yum spielen wir die Pakete Rsync, Galera Cluster 4 und MySQL samt der benötigten WSREP-Unterstützung auf jedem Cluster-Knoten ein. Dank der Angabe der Option -y läuft der Befehl ohne Rückfrage auf den Systemen durch:
yum install rsync galera-4 mysql-wsrep-8.0 -y
Damit wäre die Grundlage für unser Galera Cluster mit MySQL gelegt. Doch wie es sich für meine Ratgeber gehört, möchte im Folgenden noch kurz auf die spätere Verwendung der installierten Pakete eingehen. Um einen erfolgreichen Clusterbetrieb gewährleisten zu können, ist es nämlich unerlässlich, sich bestens mit den installierten Komponenten auszukennen.
- Rsync: Hierbei handelt es sich um ein leistungsfähiges Werkzeug für die Dateisynchronisation und -übertragung. Genutzt wird es aufgrund der später vorgestellten Galera-Konfiguration für alle Incremental State Transfers.
- Galera-4: Mithilfe der Software Galera Cluster wird die Multi-Master-Synchronisation für unsere MySQL-Datenbanken umgesetzt. Und nur Version 4 ist kompatibel mit MySQL 8.0. Galera kann man sich grundsätzlich als vollumfänglichen Cluster-Manager vorstellen.
- Mysql-wsrep-8.0: Was ein MySQL-Server ist, muss man hier sicherlich keinem erklären. Doch den Passus WSREP-Unterstützung haben sicherlich einige Leser des Artikels noch nicht gehört. Dies ist die Version von MySQL, die das Write-Set-Replication-Protokoll (WSREP) von Galera Cluster integriert hat, um eine robuste und hochverfügbare Datenbankreplikation zu ermöglichen.
Optional können die gerade installierten Pakete nun von den automatischen Systemaktualisierungen ausgeschlossen werden. Dieser Schritt verhindert potenzielle Probleme bei automatisierten Routine-Updates. Die Ausschlüsse lassen sich leicht in den Konfigurationsdateien /etc/yum.conf oder /etc/dnf/dnf.conf vornehmen, indem die entsprechenden Pakete wie folgt eingetragen werden:
exclude=rsync galera-4 mysql-wsrep-8.0
Schritt 4 – MySQL & Galera konfigurieren:
Die Einstellung eines Galera Clusters erfordert einige Überlegungen und Anpassungen, um eine optimale Leistung, Zuverlässigkeit und Sicherheit zu gewährleisten. Ich gehe in meinem Beispiel von einem 3-Node-Cluster für kleinere Anwendungsszenarien aus. Die weiter unten vorgestellte Konfiguration kannst du mit ein paar kleinen Adaptationen unter /etc/my.cnf übernehmen.
Angepasst werden müssen der Hostname sowie die IP-Adressen. Weiterhin muss in der Konfiguration der Cluster-Name hinterlegt werden. Darüber hinaus sollte man noch die Größe des GCache, die Anzahl der Threads sowie die InnoDB-Bufferpool-Größe festlegen. Der GCache befindet sich standardmäßig im RAM und sollte mindestens 300 MB groß sein. Mehr schadet aber natürlich nicht.
Ich vergebe weiterhin 50 % meiner CPU-Kerne unter wsrep_slave_threads. Der InnoDB-Bufferpool darf ebenfalls groß ausfallen. Ich verteile hier mindestens 70 % des vorhandenen Arbeitsspeichers. So ist der Cache für Lese-Zugriffe angenehm groß und das Cluster schön performant. Wer die maximale Leistung herauskitzeln möchte, kann an dieser Stelle noch einen Blick in die Doku werfen.
[mysqld]
# Standard-Speicherort der MySQL-Daten:
datadir=/var/lib/mysql
# Standard-Pfad zum MySQL-Socket:
socket=/var/lib/mysql/mysql.sock
# MySQL lauscht auf allen verfügbaren Netzwerkschnittstellen:
bind-address=0.0.0.0
# Benutzerkontext, unter dem MySQL ausgeführt wird:
user=mysql
# Festlegen der Standard-Speicher-Engine für Tabellen:
default_storage_engine=InnoDB
#Verhindert Locking bei Auto-Increment-Operationen:
innodb_autoinc_lock_mode=2
# Änderungen an den Log-Dateien werden nur alle 10 Sekunden auf die Festplatte geschrieben:
innodb_flush_log_at_trx_commit=10
Größe des InnoDB-Bufferpools - muss angepasst werden:
innodb_buffer_pool_size=1G
# Verwendetes Format für die Binärprotokolle:
binlog_format=ROW
# Pfad zur MySQL-Fehlerprotokolldatei:
log-error=/var/log/mysqld.log
# Aktivierung des Galera-Cluster-Modus
wsrep_on=ON
# Pfad zur Galera-Bibliothek in Version 4.0:
wsrep_provider=/usr/lib64/galera-4/libgalera_smm.so
# Name des Galera-Knotens - muss anpasst werdem:
wsrep_node_name='mysql-galera-01'
# IP-Adresse des lokalen Galera-Knotens - muss anpasst werdem:
wsrep_node_address="10.10.10.220"
# Name des Galera-Clusters - muss anpasst werdem:
wsrep_cluster_name='galera-homelab'
# IP-Adressen der Clusterknoten - muss angepasst werden:
wsrep_cluster_address="gcomm://10.10.10.220,10.10.10.221,10.10.10.222"
# Einstellungen für den Galera-Cache:
wsrep_provider_options="gcache.size=1000M;gcache.page_size=1000M"
# Anzahl der Threads, die von den Knoten für die Replikation verwendet werden - muss angepasst werden:
wsrep_slave_threads=4
# Methode für den SST-Übertragungsprozess:
wsrep_sst_method=rsync
Nachdem die obige Konfiguration auf allen Knoten des Clusters verteilt wurde, kann man den MySQL-Daemon in den Autostart legen und ihn dabei gleich noch starten. Sollte die Konfiguration Fehler enthalten, würde der Dienst an dieser Stelle eine Fehlermeldung ausgeben. Ansonsten kann man direkt mit der Härtung des Datenbankservers fortfahren.
# MySQL-Service enablen und starten:
systemctl enable --now mysqld && systemctl status mysqld
# Root-Passwort ermitteln:
grep 'temporary password' /var/log/mysqld.log
# Datenbankserver absichern:
mysql_secure_installation
Dafür muss man aber zuerst das Root-Passwort für MySQL herausfinden. Es versteckt sich in den Logs und man ganz einfach danach filtern. Die eigentliche Härtung ist recht simpel. Man ruft dafür lediglich das Kommandozeilen-Programm mysql_secure_installation auf und beantwortet die gestellten Fragen. Grundsätzlich gesprochen, kann man hier stets mit Ja antworten.
Schritt 5 – Galera Cluster initialisieren:
Nun ist es fast geschafft. Das Cluster muss nur noch auf einem Node initialisiert werden. Dafür nutzt man einfach das CLI-Tool mysqld_bootstrap und zwar ohne weitere Parameter. Auf den verbliebenen Hosts des Clusters kann man jetzt noch den MySQL-Daemon neu starten und das war es dann auch schon. Die Nodes treten dem Cluster anschließend selbständig bei.
# Cluster auf dem Primary-Node initialisieren:
mysqld_bootstrap
# Auf den restlichen Cluster-Nodes Mysqld neu starten:
systemctl restart mysqld
# Anzahl der Nodes im Galera Cluster prüfen:
mysql -u root -p -e "SHOW STATUS LIKE 'wsrep_cluster_size'";
# Umfangreiche Informationen über das Cluster abrufen:
mysql -u root -p -e "SHOW STATUS LIKE 'wsrep%'";
Zu guter Letzt sollte man natürlich noch prüfen, ob der Cluster-Beitritt auch funktioniert hat. Dies gelingt ganz einfach mittels des Befehls mysql -u root -p -e „SHOW STATUS LIKE ‚wsrep_cluster_size'“; Wer hingegen noch ein paar mehr Daten zum Cluster haben möchte, kann auch gleich dieses Kommando im Terminal absetzen: mysql -u root -p -e „SHOW STATUS LIKE ‚wsrep%'“;