mittwald Cloud Plattform Insights (III): Migration Recap
Recap: Was, warum, wieso?
In meinen letzten Blog-Artikeln stellte ich die grundlegende Architektur der mittwald Cloud-Plattform vor, und mit welchen Aspekten derselben wir unzufrieden waren. Insbesondere die Stabilität und der operative Overhead der Plattform entsprachen nicht unseren eigenen Ansprüchen, weshalb wir die Migration auf einen neuen infrastrukturellen Unterbau anstrebten (und in der letzten Woche auch durchführten und erfolgreich abschlossen. Derzeit laufen die letzten Nacharbeiten).
Ablauf einer Migration
Unter der Haube besteht die Cloud-Plattform aus mehreren einzelnen Kubernetes-Clustern, die wir über mehrere Tage schrittweise migrierten. Jede Migration bestand dabei aus zwei Schritten: Im ersten Schritt wurden die Workloads (also die laufenden Container) auf die neue Plattform migriert, und griffen zunächst weiter auf die Nutzdaten auf dem Ceph-Cluster zu, unserem bisherigen zentralen Storage-System der "alten” Plattform.
Da in diesen Kubernetes-Clustern auch zustandsbehaftete Workloads liefen (beispielsweise Datenbanken), und aufgrund der eng mit OpenStack verknüpften Netzwerkkonfiguration dieser Cluster, war während der Migration kein gleichzeitiger Parallelbetrieb eines Clusters auf beiden Plattformen möglich. Deshalb musste dieser Migrationsschritt jeweils im Rahmen einer angekündigten Wartung mit Downtime durchgeführt werden.
Im zweiten Migrationsschritt wurden die Nutzdaten der Projekte von den Ceph-Volumes auf den lokalen Storage der Kubernetes-Nodes verschoben. Hier konnten wir den Großteil der Nutzdaten asynchron verschieben, sodass die Projekte während dieser Zeit weiterhin erreichbar blieben. Lediglich der finale Datenabgleich erforderte eine kurze Downtime (die in aller Regel im Sekundenbereich lag), um die allzeitige Konsistenz der Daten gewährleisten zu können.
Für die Zeit zwischen diesen zwei Migrationsschritten konnten wir (aufgrund der Trennung von Cluster-Workload und Storage) nicht auf unsere gewohnten Backup-Mechanismen zugreifen. Wir sicherten die Daten daher vorübergehend über die eingebauten Mechanismen von Ceph selbst. Die so erstellten Backups waren nicht im mStudio sichtbar, konnten aber durch unseren Kundenservice auf Zuruf jederzeit eingespielt werden.
Lessons Learned
Da wir die neue Plattform im Vorfeld ausführlichen Lasttests unterzogen, verlief die Migration der Workloads im Großen und Ganzen reibungslos. Im Rahmen der Migration stießen unsere DevOps Engineers auf vereinzelte Fehler in den eingesetzten OpenSource-Komponenten, die wir jedoch zügig beheben konnten.
Beispielsweise stellten wir in vereinzelten Ceph Volumes einen Datenverlust fest, den wir auf eine Race Condition in dem eingesetzten CSI-Treiber zurückführen konnten. Anhand der vorliegenden Logs konnten wir den Fehler schnell lokalisieren. Eine Lösung für diesen Bug konnten wir in Zusammenarbeit mit der Entwickler-Community des Ceph-Projekts bereits in das Upstream-Projekt einbringen. Da wir unmittelbar vor der Migration Snapshots aller Volumes erstellten, konnten wir die durch diesen Bug verlorenen Daten zügig und ohne Verlust wiederherstellen.
Eine ähnliche Race Condition konnten wir im OpenEBS-Projekt feststellen, dass wir zur Bereitstellung des lokalen Speicherplatzes verwenden. Auch hier konnten wir direkt eine Lösung im Upstream-Projekt beitragen.
Im Anschluss an die Migration erreichten uns zudem Berichte, dass Benutzern eine höhere RAM-Auslastung ihrer Server im mStudio reported wurde. Dies konnten wir darauf zurückführen, dass einige Systemkomponenten der Kubernetes-Nodes einen höheren Speicherbedarf als vorher hatten. Wir lösten dies teilweise durch geeignete Limitierungen, und teilweise dadurch, dass wir die entsprechenden Komponenten in separate Control Groups verschoben, sodass diese nicht gegen die gebuchten Ressourcen gerechnet wurden. In der Zukunft werden wir auch mit den entsprechenden Entwickler-Communities der jeweiligen Projekte zusammenarbeiten, um die Ressourceneffizienz dieser Komponenten zu erhöhen.
Gleichermaßen stellten wir fest, dass die Kubernetes-seitige Node-Pressure Eviction auf der neuen Plattform deutlich präziser arbeitete als zuvor. Diese dient dazu, bei hohem RAM-Verbrauch den betriebssystemseitigen Mechanismen zuvorzukommen und speicherintensive Prozesse zu beenden (bzw. auf andere Nodes zu verschieben). Zuvor terminierte der Linux-OOM-Killer Prozesse mit hohem Speicherplatzverbrauch – darunter auch gelegentlich Datenbank-Workloads, was auf Instanzen mit hohem RAM-Verbrauch die Verfügbarkeit ungünstig beeinträchtigte. Diese Informationen ermöglichen uns eine höhere Sichtbarkeit im System. Das Verhalten der Eviction werden wir in der kommenden Zeit noch feintunen, um auch unter Situationen hoher RAM-Auslastung die Verfügbarkeit zu maximieren.
Beobachtungen im Nachhinein
Neben Verbesserungen in der allgemeinen Zuverlässigkeit der Plattform erhofften wir uns zudem spürbare Verbesserungen in der Performance — einerseits durch die verringerte Komplexität im Networking-Stack, und andererseits durch die Umstellung auf lokales Storage (über die jeweiligen Vor- und Nachteile der einzelnen Storage-Strategien berichtete ich bereits zuvor).
Exemplarisch an einem einzelnen Cluster beobachteten wir allein durch den ersten Migrationsschritt (bei zunächst gleichbleibendem Storage) in der clientseitig gemessenen Antwortzeit über alle Projekte eines Clusters hinweg eine durchschnittliche Reduktion von 239 ms auf 174 ms (also eine Verbesserung von 1−(172/239) = 28 %).
Exemplarisch folgen Details einer einzelnen WordPress-Seite eines Mitarbeiters, die bereits während der Migration auf lokales Storage umgestellt wurde. Die Seite wird auf einem Space-Server mit 2 vCPU und 4 GB RAM betrieben. Dieses Sizing wurde im Zuge der Migration nicht verändert. Für die beobachtete Seite hat sich nach der Migration die durchschnittliche Seitenantwortzeit von 420 ms auf 260 ms verringert:
Noch deutlichere Ergebnisse zeigen sich, wenn man auf die Core Web Vitals der Seite schaut. Bei der beobachteten WordPress-Seite konnte hier beispielsweise der First Contentful Paint von 1 s auf 0,42 s verbessert werden, die Time To Interact von 1,4 s auf 0,59 s (beides jeweils −58 %).
Diese Beobachtungen sind stichprobenartig und nicht zwangsläufig repräsentativ. Die tatsächlichen Performance-Vorteile, die sich durch die Umstellung auf einen einfacheren Networking Stack und lokales Storage ergeben, hängen davon ab, wie netzwerk- und storageintensiv das jeweilige Projekt tatsächlich ist. Insbesondere bei bereits hochoptimierten Projekten, die im Regelbetrieb nur wenig I/O-Last verursachen (beispielsweise ein TYPO3 CMS mit gut optimierten Bildern, dessen Seiten größtenteils aus dem Cache ausgeliefert werden können) werden sich nicht dieselben Verbesserungen einstellen wie bei I/O- oder datenbankintensiven Workloads (wie etwa in Onlineshops oder einem ungecachten WordPress).
Wie geht’s weiter?
Die Komplexität der unterliegenden Infrastruktur (insbesondere des Software Defined Networking Stacks) sowie die Abhängigkeit von einem zentralen Storage-System waren die Schmerzpunkte, die die Verlässlichkeit des Systems am meisten beeinträchtigt haben und auch in der Vergangenheit zu Ausfällen führten (vgl. Netzwerk und Storage). Beide Schmerzpunkte konnten wir durch die neue Plattform erfolgreich eliminieren.
Der Wechsel auf Local Storage geht natürlich mit Trade-Offs einher (ich verweise auf meinen letzten Artikel dazu) und wird zukünftig womöglich nicht den Anforderungen aller Projekte (beispielsweise hinsichtlich Skalierbarkeit und Verfügbarkeit) gerecht. Aus diesem Grund werden wir in der Plattform perspektivisch mehrere Storage-Mechanismen zur Auswahl anbieten (darunter auch hochverfügbare netzwerkbasierte Storage-Lösungen), und dem Anwender selbst die Auswahl überlassen, welcher Storage-Mechanismus für welches Projekt verwendet werden soll.
Das primäre Ziel dieser Re-Engineering-Maßnahme ist es, unsere definierten Service Level Objectives (insbesondere hinsichtlich Verlässlichkeit und Performance) langfristig einhalten zu können. Wir werden in diesem Sinne langfristig das Verhalten unserer Plattform beobachten, und unsere Learnings (im Sinne unserer gelebten Post Mortem-Kultur) hier im Blog weiterhin teilen.
Aufbauend auf meinen bisherigen Artikeln über die Architektur der Plattform werden wir auch zukünftig weitere technische Einblicke in die Details der Plattform teilen. Bleibt gespannt!
Häufige Kundenfragen
- Warum ist der Ressourcenverbrauch bei manchen Projekten nach der Migration gestiegen?
Die neue Plattform reagiert präziser auf Out-Of-Memory-Situationen. Infolgedessen wurde bei einigen Projekten sichtbar, dass der bisher gebuchte Tarif für die Anforderungen im Live-Betrieb in Wahrheit nicht ausreicht. Diese Projekte benötigten nach der Migration ein Upgrade auf den Tarif, der ihrem tatsächlichen Ressourcenverbrauch entspricht. Dieses Upgrade haben wir im ersten Monat nach der Migration kostenlos zur Verfügung gestellt, damit betroffene Kunden keine unerwarteten Kosten tragen müssen. - Wann wird die versprochene Gutschrift für das Serverupgrade durch mittwald erstellt? Die Gutschriften für die benötigten Serverupgrades werden unmittelbar nach der Rechnungserstellung ausgezahlt. Die betroffenen Kunden erhalten Rechnung und Gutschrift zum jeweiligen Rechnungsstichtag einen Monat nach dem Upgrade.
- Warum war mein /html-Verzeichnis leer?
Bei der Migration von zentralem auf lokalen Speicher kam es vereinzelt zu einem temporären Datenverlust. Mithilfe vorab erstellter Snapshots wurden alle Daten vollumfänglich wiederhergestellt. - Was mache ich, wenn ich ein Backup brauche?
Solltest du ein Backup aus dem Zeitraum zwischen Migration und Reaktivierung der Backupfunktion benötigen, schreibe uns bitte ein Ticket im mStudio. Wir legen dir das Backup im Anschluss in deinem Filesystem ab. - Wieso waren meine Projekte dauerhaft im Status "wird angelegt"?
Aufgrund eines Softwarefehlers wurde der Status neu erstellter Projekte im mStudio fälschlicherweise als 'wird angelegt' angezeigt; die betroffenen Projekte waren dabei zu jeder Zeit erreichbar.