Der redundante Betrieb von Datenbanken gehört zu den anspruchsvollsten Aufgaben, die die IT der Gegenwart für Administratoren in petto hält. Viel hat sich auf diesem Gebiet in den letzten Jahren aber verändert: Gaben früher noch Cluster-Manager wie Pacemaker den Ton an, gilt heute als Königsweg, dass Datenbanken per se skalierbar sind und sich um das Thema HA selbst kümmern. Wir zeigen am Beispiel von Vitess für MySQL, wie das in der Praxis aussehen kann.
Wer beruflich bereits eine Weile als Administrator unterwegs ist, kennt ohne Zweifel das Problem: Datenbanken sind ein neuralgischer Punkt in jeder IT-Umgebung, weil ohne sie die meisten anderen Anwendungen nicht funktionieren. Deshalb müssen sie redundant sein. Das allerdings ist gar nicht so einfach zu erreichen. Denn Datenbanken gelten in Sachen High Availability (HA) als ausgesprochen anspruchsvoll. Etliche Garantien sind im Hinblick auf die Verfügbarkeit von Daten und ihre Konsistenz zu erfüllen. Die Konstruktion einer redundanten Datenbank gilt entsprechend als Königsdisziplin in Sachen Hochverfügbarkeit.
Datenbank-Cluster mit Herausforderungen
Lange Zeit war der einzige anerkannte und zuverlässige Weg, um Datenbank-Redundanz zu erreichen, der Einsatz eines Cluster-Managers wie Pacemaker (Bild 1) unter Linux. Mit entsprechender Erfahrung dürften die meisten Administratoren solch ein Setup schon einmal gesehen haben. Die Daten lagern dann auf repliziertem Speicher, etwa DRBD unter Linux, einer Art RAID 1 über das Netz. Von mehreren Knoten eines Clusters ist stets nur ein Knoten "aktiv"; auf ihm läuft einerseits die IP-Adresse, die Clients für die Verbindung nutzen, und andererseits die Datenbank selbst, die im Hintergrund auf die redundant gehaltenen Daten zugreift.
Ein Aufbau dieser Art hat aber mehrere offensichtliche Schwachstellen. Da ist zunächst der Cluster-Manager, der unter Linux wie beschrieben meist Pacemaker ist. Die Software gilt in Sachen Benutzbarkeit als garstig und hat – zum Teil aus historischen Gründen – nicht gede viele Fans unter Administratoren. Ein anderes Problem ist, dass es für einen Cluster dieser Art teurer, weil leistungsfähiger Hardware bedarf, die wegen der Aktiv-Passiv-Natur eines HA-Clusters aber stets halb brach liegt. Es geht hier eben nicht um das Skalieren in die Breite – sämtliche anliegende Last landet auf dem gerade aktiven Node des Clusters, während die andere Maschine sich langweilt.
Wer beruflich bereits eine Weile als Administrator unterwegs ist, kennt ohne Zweifel das Problem: Datenbanken sind ein neuralgischer Punkt in jeder IT-Umgebung, weil ohne sie die meisten anderen Anwendungen nicht funktionieren. Deshalb müssen sie redundant sein. Das allerdings ist gar nicht so einfach zu erreichen. Denn Datenbanken gelten in Sachen High Availability (HA) als ausgesprochen anspruchsvoll. Etliche Garantien sind im Hinblick auf die Verfügbarkeit von Daten und ihre Konsistenz zu erfüllen. Die Konstruktion einer redundanten Datenbank gilt entsprechend als Königsdisziplin in Sachen Hochverfügbarkeit.
Datenbank-Cluster mit Herausforderungen
Lange Zeit war der einzige anerkannte und zuverlässige Weg, um Datenbank-Redundanz zu erreichen, der Einsatz eines Cluster-Managers wie Pacemaker (Bild 1) unter Linux. Mit entsprechender Erfahrung dürften die meisten Administratoren solch ein Setup schon einmal gesehen haben. Die Daten lagern dann auf repliziertem Speicher, etwa DRBD unter Linux, einer Art RAID 1 über das Netz. Von mehreren Knoten eines Clusters ist stets nur ein Knoten "aktiv"; auf ihm läuft einerseits die IP-Adresse, die Clients für die Verbindung nutzen, und andererseits die Datenbank selbst, die im Hintergrund auf die redundant gehaltenen Daten zugreift.
Ein Aufbau dieser Art hat aber mehrere offensichtliche Schwachstellen. Da ist zunächst der Cluster-Manager, der unter Linux wie beschrieben meist Pacemaker ist. Die Software gilt in Sachen Benutzbarkeit als garstig und hat – zum Teil aus historischen Gründen – nicht gede viele Fans unter Administratoren. Ein anderes Problem ist, dass es für einen Cluster dieser Art teurer, weil leistungsfähiger Hardware bedarf, die wegen der Aktiv-Passiv-Natur eines HA-Clusters aber stets halb brach liegt. Es geht hier eben nicht um das Skalieren in die Breite – sämtliche anliegende Last landet auf dem gerade aktiven Node des Clusters, während die andere Maschine sich langweilt.
Zufall ist das nicht. Während in der Branche für andere Speicherarten wie Blockspeicher oder ReST-basierter HTTP-Speicher längst skalierbare Produkte vorlagen, tat die Datenbankbranche sich bei diesem Thema sehr schwer. Das liegt vor allem daran, dass eine in die Breite skalierbare Datenbank technisch ein sehr kniffliges Unterfangen ist. Denn die Nutzer von Datenbanken erwarten bestimmte Garantien im Hinblick auf die Konsistenz und die Sicherheit der gespeicherten Informationen. ACID (Atomicity, Consistency, Isolation, Durability) ist hier nur eines von etlichen Stichworten, "eventual consistency" spielt eine weitere Rolle.
Hinzu kommt, dass die meisten klassischen Protokolle für den Zugriff auf Datenbanken eine aus mehreren Instanzen bestehende DB gar nicht ermöglichen, sodass Workarounds per Loadbalancer nötig sind. Nicht aus Versehen gelten verteilte Systeme als eine der komplexesten Kategorien der gegenwärtigen IT, und wenn es um die Konsistenz von Daten geht, legt das die Latte in Sachen Schwierigkeit nochmal ein Stück höher.
Vitess: Netz aus MySQL-Instanzen
Mittlerweile hat sich der Innovationsstau in Sachen Redundanz bei Datenbanken aber weitgehend aufgelöst. Daran haben Werkzeuge wie Vitess [1] einen großen Anteil, denn sie haben das Redundanzkonzept vergangener Tage durch kluge Technologie quasi in den Ruhestand versetzt. Vitess nutzt im Hintergrund zwar noch echte Instanzen von MySQL und exponiert nach außen hin auch eine echte MySQL-Schnittstelle. Hinter den Kulissen übernimmt bei Vitess aber ein Konstrukt aus verschiedenen Zusatzdiensten die Regie, das sich um die Verteilung von Daten in einem Netz aus einzelnen MySQL-Instanzen kümmert.
Dieser Ansatz hat mehrere Vorteile: Er schafft echte Skalierbarkeit in die Breite für MySQL, ohne das MySQL-Protokoll mühsam nachbauen zu müssen. Letzteres ist insbesondere bei alternativen Ansätzen wie Yugabyte der Fall. Diese sehen von außen aus wie MySQL, sind unter der Haube aber eigentlich Key-Value-Stores mit MySQL-Frontend, das dann aber nicht alle MySQL-Features bietet. Gerade weil Vitess das native MySQL-Protokoll unterstützt, lassen sich damit beliebige, existierende MySQL-Clients nutzen.
Unser Artikel beschreibt im weiteren Verlauf beispielhaft das Deployment von Vitess; zuvor steht aber ein bisschen Theorie auf dem Plan. Denn die Inbetriebnahme ist gar nicht so schwierig, setzen die Entwickler heute doch verstärkt auf Kubernetes. Der Admin tut aber gut daran zu wissen, was da in Form von Kubernetes-Anweisungen überhaupt ausgerollt wird und wie die Datenbank grundsätzlich funktioniert. Denn andernfalls steht er im Fehlerfall wie der sprichwörtliche Ochse vor dem Berg und weiß nicht, wie er eine havarierte Database wieder flott bekommt. Die gute Nachricht ist, dass Vitess nicht so komplex ist wie manches Konkurrenzprodukt am Markt.
Komplexe Begrifflichkeiten
Durchaus komplex ist allerdings die Fachsprache, die die Entwickler verwenden, um Features in Vitess zu beschreiben. Das gilt zum Teil auch, weil Begriffe zum Einsatz kommen, die der Administrator in anderen Kontexten möglicherweise schon einmal mit subtil anderer Bedeutung gehört hat. Ein typisches Beispiel ist das Sharding. Dieser Begriff bezeichnet in der IT traditionellerweise den Akt, größere Datensätze in viele kleinere Datensätze aufzuteilen, um sie auf verschiedene Geräte zu verteilen. Kommt Sharding zum Einsatz, muss es eine Instanz geben, die weiß, welcher Teil des Datensatzes wo genau liegt. Diese kann entweder zentral konzipiert sein oder dezentral mit anderen Diensten mitlaufen. Eben diesen Ansatz verfolgt Vitess. Wie sieht das aber im Detail aus?
Zunächst gilt: Der gesamte Namespace einer Vitess-Datenbank unterteilt sich in sogenannte Keyspaces. (Bild 2). Ein Keyspace ist die logische Entsprechung zu einer Datenbank. "Datenbank" darf in Vitess ein Keyspace deshalb nicht heißen, weil der Begriff Datenbank auf lokale MySQL-Instanzen gemünzt ist und ein Keyspace in Vitess eben nicht auf eine einzelne lokale Datenbank im Hintergrund zurückgreift – zumindest nicht zwangsläufig. Denn die Inhalte eines Keyspace, insbesondere Tabellen, können in Vitess auf mehrere, miteinander verbundene MySQL-Instanzen aufgeteilt sein. Diese einzelnen Teile nennen die Entwickler dann "Shards", die wiederum innerhalb der Installation verteilt und repliziert werden. Für jeden Shard gibt es eine primäre Backend-Instanz und beliebig viele Replica-Instanzen.
Die Verwaltung von Shards, von Keyspaces sowie der eigentlichen Daten obliegt in Vitess einerseits den sogenannten VTTablets. Das sind die zu Vitess gehörenden Instanzen, die im Hintergrund auf konventionelle MySQL-Instanzen für das Speichern von Daten zugreifen. Die andere Komponente, die eine zentrale Rolle im Speicherprozess von Daten spielt, ist ein zentrales Zugriffsgateway namens VTGate. VTGate kennt die Topologie der Informationen im Hintergrund, skaliert bei Bedarf selbst in die Breite und weist eingehende Anfragen den jeweils zuständigen Instanzen von VTTablet für den jeweiligen Shard eines Keyspaces zu.
Zur Seite steht diesem Dreigestirn aus Diensten eine Control Plane, über die sich das gesamte Konstrukt steuern lässt. Zu diesem zählt neben einem Topology-Server, in dem die zu Vitess gehörenden Metadaten gespeichert sind, auch der VT-Control-Daemon (vtctld) und eine darauf fußendes GUI (VTAdmin). Jene nutzt der Administrator, um die Struktur von Keyspaces zu bearbeiten, also etwa um neue zu erstellen oder bestehende Keyspaces zu erweitern. Für die Hausmeistertätigkeiten im Hintergrund gibt es zudem den "VTOrc", der Inkonsistenzen und Fehler automatisch erkennt und repariert.
Selbst wer mit Vitess bisher keine Berührungspunkte hatte, merkt schnell: Die Komplexität des gesamten Konstruktes ist deutlich größer als die einer einfachen Single-Instanz von MySQL. Das gilt nicht nur wegen der vielen Dienste unter der Haube, sondern auch, weil das interne Design der Datenbank in Form von Keyspaces und Shards zwei Aspekte enthält, die im klassischen MySQL gar nicht vorkommen. Allerdings verstecken die Entwickler diese Komplexität zum größten Teil vor den Augen des Administrators. Denn wenn die Datenbank einmal eingerichtet ist, verhält sie sich aus Sicht eines Clients im Wesentlichen so wie ein normales MySQL.
Deployment setzt auf Kubernetes
Grau ist alle Theorie, große Freude bereitet die Praxis. Die gestaltet sich bei Vitess allerdings etwas anders, als manch Administrator es im ersten Augenblick möglicherweise erwartet. Denn wer auf der Website des Werkzeugs nach einer Installationsanleitung sucht, die klassische Faktoren wie Paketmanager oder die lokale Installation von Binärdateien vorsieht, merkt schnell, dass er sich auf dem Holzweg befindet. Warum das so ist, erschließt sich einem genaueren Blick auf das Deployment-Szenario von Vitess.
Wie beschrieben besteht die Datenbank aus etlichen einzelnen Komponenten. Obendrein ist ein zentrales Element des Designs die Hochverfügbarkeit, die Vitess durch seine Fähigkeit des Skalierens in die Breite realisiert. Damit ein verteiltes Setup sinnvoll funktionieren kann, sind drei Knoten das Minimum der benötigten Hardware. In Zeiten klassischer Cluster-Manager haben sich zwar auch Zwei-Knoten-Cluster einen Rang in der modernen IT erarbeitet.
Technisch betrachtet sind diese aber schon deshalb Nischenwege, weil sie kaum sinnvoll in der Lage sind, Split-Brain-Situationen zu vermeiden, die durch Netzwerkpartitionierungen entstehen. Bräche ein Zwei-Knoten-Cluster mit Vitess auseinander, ohne dass einer der Server stirbt, könnten beide Instanzen denken, sie wären der einzige Knoten, der noch übrig ist. Dann käme es zu eben jenem Split-Brain, bei dem beide Instanzen denselben Datensatz unabhängig voneinander schreibend bearbeiten.
Die Vitess-Entwickler haben von Anfang an größer gedacht und solche Aufbauten bei der Implementierung gar nicht beachtet. Wer eine skalierbare Datenbank will, so ist gewissermaßen die Ansage, sollte sich zumindest drei gleichwertige Systeme dafür leisten können. Das gilt umso mehr, da Vitess nicht zwangsläufig auf echtem Blech laufen muss – und das wohl in den meisten Fällen auch nicht tun wird.
Nun hätten die Macher freilich ein umfangreiches Deployment-Schema für das lokale Ausrollen der Datenbank konstruieren können. Wegen der Vielzahl der aufzusetzenden Dienste wäre das aber sowohl in Sachen Setup als auch in Sachen Betrieb ausgesprochen mühsam. Zumal es Produkte am Markt gibt, die viele dieser Probleme von vornherein sinnvoll lösen. Die Rede ist natürlich von Kubernetes, und auf eben dieses hat man sich bei Vitess als Standarszenario eingeschossen. Zwar weisen die Entwickler in ihrer Dokumentation darauf hin, dass ein lokales Deployment möglich ist. Sämtliche Formen des händischen und lokalen Ausbringens bewerten die Entwickler jedoch nur "für Testumgebungen" geeignet.
Wer Vitess also wie von seinen Autoren vorgesehen nutzen möchte, braucht Kubernetes. Ein großes Problem ist das aber eher nicht. Denn schließlich reichen drei Knoten auch aus, um ein hochverfügbares Kubernetes-Setup mit drei Zielsystemen für Container-Instanzen zu betreiben. Außerdem muss es nicht immer die gesamte Bandbreite an Features von OpenShift oder Rancher sein. Wer einen Kubernetes-Cluster spezifisch nur für Vitess bauen will, kommt mit Ansätzen wie Minikube oder K3s gut und schnell ans Ziel.
Installation: Vite Vite, Vitess!
Das folgende Beispiel geht entsprechend von drei leistungsstarken Servern für den Vitess-Betrieb aus, aus denen zunächst ein Kubernetes-Cluster wird. Als Distribution kommt dabei Ubuntu 22.04 zum Einsatz. Die drei Rechner verfügen über genügend lokalen Speicherplatz, 256 GByte RAM, duale Zwölf-Kern-CPUs mit viel Performance unter der Haube sowie eine redundante 10-GBit/s-Anbindung an das lokale Netz. Das sind natürlich nicht die Mindestanforderungen für Vitess, sondern eher Werte für eine große Installation im produktiven Umfeld. Wer das Szenario dieses Artikels nachspielen möchte, kann das auch in VMs tun.
So oder so steht im ersten Schritt des Vitess-Deployments die Inbetriebnahme von Kubernetes in Form von Minikube an. Dies würde an dieser Stelle einen eigenen Artikel rechtfertigen und die Grenzen dieses Artikels sprengen. Ausführliche How-Tos zur Installation von Minikube unter Ubuntu 22.04 finden sich aber im Netz etwa unter [2]. Das Setup umfasst dabei einige Schritte, zum Beispiel die Installation der Docker Community Edition, das Einrichten von Speicher und Netzwerk sowie das Deployment von Minikube selbst. Am Ende des Vorgangs sollte Ihnen eine vollständige Kubernetes-API zur Verfügung stehen, die Sie mittels "kubectl" mit Befehlen versorgen. Dann geht es mit dem Ausrollen von Vitess weiter.
Dieses haben die Entwickler sehr zum Vorteil des Admins perfekt vorbereitet. Klonen Sie mittels "git" zunächst den Vitess-Quelltext auf Ihr lokales System:
Im Unterordner "cd vitess/examples/operator" findet sich danach ein sogenannter Operator für Kubernetes. Das bedeutet im Kubernetes-Sprech eine Erweiterung der Kubernetes-API um verschiedene Elemente, die das Starten und das Betreiben von Diensten wie Vitess ganz erheblich erleichtert. Spielen Sie diese Definitionen mittels
kubectl apply -f operator.yaml
zunächst in Ihre lokale Minikube-Instanz ein. Danach starten Sie Vitess. Dazu verwenden Sie erneut die zuvor durch die Entwickler angelegten Definitionen von Kubernetes:
kubectl apply -f 101_initial_cluster.yaml
Ob der Plan erfolgreich war, zeigt Ihnen ein paar Minuten später die Ausgabe von kubectl get pods (Bild 3): Hier sollten sie drei Instanzen von Etcd sehen, zwei Instanzen von vttablet sowie eine Instanz von VTadmin, VTctld, VTGate und den Vitess-Operator selbst. Das Kubernetes-Setup erstellt übrigens nur die Vitess-Instanzen selbst, direkt nach dem Start fehlt also noch ein Datenbankschema. Das lässt sich allerdings schnell ändern. Im Ordner, aus dem heraus Sie auch den kubectl-Befehl eben ausgeführt haben, findet sich eine Datei namens "pf.sh". Das ist ein Skript, das Ihnen einen Port-Forward aus Kubernetes heraus auf Ihr lokales System ausführt, sodass Sie den "mysql"-Client nutzen können, als liefe die Datenbank lokal.
Anschließend funktioniert zudem auch das Kommando "vtctldclient", mit dem Sie direkte Änderungen an Vitess senden. Die Befehle
legen im Anschluss ein Schema so an, dass es sowohl für Vitess als auch aus einem MySQL-Client heraus nutzbar wird. Das erste Kommando erstellt dabei das eigentliche Datenbankschema, das zweite erzeugt das "Vitess-Schema", das Metadaten zum eigentlichen Schema enthält, etwa die Anzahl der Shards und die Verteilung dieser auf die VTTablet-Instanzen.
Schließlich rufen Sie mysql auf und landen in einer Vitess-Sitzung, die von außen von einer typischen MySQL-Sitzung nicht zu unterscheiden ist (Bild 4). Übrigens: Vitess unterstützt als Backend sowohl das "echte" MySQL von Oracle als auch ”Percone XtraDB Server” für MySQL.
Hochverfügbarkeit für das Gateway
Wer einen Blick auf den bis hierhin skizzierten Aufbau wirft, merkt schnell: Einen Schwachpunkt hat das Design, und zwar konkret in Form des VTGate. Zur Erinnerung: Jenes fungiert zur Außenwelt hin und auch für die Control-Plane von Vitess als Zugangspunkt. Die allermeisten Datenbankclients bieten für MySQL schon deshalb nicht die Option an, mehrere Zielserver zu konfigurieren, weil das MySQL-Protokoll das offiziell nicht vorsieht. Basteleien mit DNS & Co. haben sich in der Vergangenheit zudem als äußerst unzuverlässig herausgestellt.
Vitess hat das VTGate deshalb von Anfang an als zentrale Komponente des eigenen Konzepts betrachtet und als Single-Point-of-Contact implementiert. Genau hier liegt jedoch der Hase im Pfeffer. Denn nutzt eine Infrastruktur nur eine VTGate-Instanz, ist dieses automatisch ein Single-Point-of-Failure. Da hilft die schönste hochredundante Datenbank mit Skalierbarkeit hinten dran nichts, denn fällt das VTGate in so einer Umgebung aus, sind die VTTablet-Instanzen unerreichbar.
Auch dieses Problem lässt sich glücklicherweise relativ einfach aus dem Weg schaffen. Die Entwickler weisen darauf hin, dass Administratoren idealerweise mehrere Instanzen des VTGates parallel ausrollen. Auf der Vitess-Ebene ist das kein Problem: VTGate ist hier ein Dienst, von dem mehrere Instanzen zugleich laufen dürfen. Bleibt noch die Frage, wie Clients anschließend den Zugriff so gestalten, dass sie auch wirklich bei einem funktionierenden VTGate landen. Denn einfach mehrere Gateways als Zielsystem im Client einzutragen, geht aus den genannten Gründen nicht.
Des Rätsels Lösung ist wie so oft ein ganz altertümlicher Loadbalancer. In Kubernetes kann das beispielsweise darauf hinauslaufen, Istio für Ingress als Controller zu verwenden und zusammen mit Vitess entsprechend zu konfigurieren. Istio stellt dann automatisch sicher, dass eingehende Verbindungen für das VTGate stets bei einer funktionierenden Instanz dieses Dienstes ankommen. Fällt ein Gateway im Backend aus, entfernt Istio dieses automatisch aus der Rotation. Clients verlieren zwar möglicherweise ihre aufrechte Verbindung zur Datenbank, können die aber sofort wiederherstellen.
In vielen Unternehmen besteht möglicherweise die Gelegenheit, einen bereits bestehenden Loadbalancer zu verwenden. Das kann schnell aber zu mehr Arbeit führen, als es spart. Denn wenn Istio in Kubernetes als Loadbalancer läuft, kümmert dieses sich nicht zuletzt automatisch um die eigene High Availability. Eine Loadbalancer-Appliance oder ein selbst ausgerollter HAProxy tun das nicht. Hier muss der Administrator dann wieder mit klassischen Maßnahmen für Hochverfügbarkeit ausrücken und landet im ungünstigsten Fall doch wieder bei einem Cluster-Manager wie Pacemaker. Wer die Möglichkeit hat, sollte sich deshalb auf die Kubernetes-eigenen Wege und Mittel verlassen.
Fazit
Vitess ermöglicht eine neue Form der Hochverfügbarkeit auf Basis des erprobten MySQL-Protokolls sowie eine native Möglichkeit für MySQL, sinnvoll in die Breite zu skalieren. Administratoren bekommen ein ausgesprochen mächtiges Werkzeug an die Hand: Nicht länger steht nämlich die Frage im Raum, ob eine einzelne Instanz einer Datenbank läuft oder nicht. Weil Clients von außen auf das Konstrukt stehts durch das VTGateway hindurch zugreifen, das sich selbst durch einen Loadbalancer in die Breite skalieren lässt und dadurch ebenfalls hochverfügbar wird, ändert sich für sie nichts. Sie nutzen das reguläre MySQL-Protokoll und merken gar nicht, dass sie nicht mit einem reinen MySQL reden.
Wer Sorgen ob der Praxistauglichkeit von Vitess hat, sei übrigens beruhigt. Die Software hat bei YouTube über Jahre hinweg die internen MySQL-Datenbanken betrieben und sich dort als praxistauglich erwiesen. Datenbank-Traffic der Dimensionen von YouTube dürften die meisten anderen Unternehmen ohnehin nicht erreichen – und Installationen kleinerer Größe stellen die Database nicht vor ernsthafte Herausforderungen. Wer auf der Suche nach einer skalierbaren und dadurch implizit hochverfügbaren MySQL-Datenbank ist, sollte Vitess also unbedingt genauer unter die Lupe nehmen.