Post Mortem: Ausfall der Cronjobs im mStudio

|
Was war der Grund der Störung? Wie konnten wir sie beheben? Das alles liest du in diesem Artikel.

“Die Cronjobs im mStudio können nicht ausgeführt werden” – eine Nachricht, auf die wir am frühen Donnerstagmorgen, 7. September 2023, lieber verzichtet hätten. Alle Kunden unseres Cloud-Hostings waren betroffen. Woran lag es? Wie konnten wir den Fehler beheben? Dieser Artikel bringt Licht ins Dunkel.

Was war passiert?

Am Donnerstagmorgen war ab etwa 03:00 Uhr die Funktionsweise unserer Cronjob Infrastruktur des mStudio von einer Störung betroffen. Das sorgte dafür, dass die Cronjobs sämtlicher in unserer Cloud gehosteter Projekte nicht mehr ausgeführt werden konnten. Die Erreichbarkeit der Webseiten war davon nicht betroffen. Gegen  12:00 Uhr war die Störung behoben.

Störungsursache

In der Nacht auf Donnerstag haben wir einen Change in unserer Cloud-Infrastruktur ausgerollt, der die Art und Weise verändert, wie unsere Cloud-Plattform Apps bereitstellt. Eine App im Kontext des mStudios ist eine Webanwendung, die in einem spezifischen Verzeichnis installiert ist. Schlussendlich muss diese App jedoch auch erreichbar sein. In unserer Kubernetes Umgebung bedeutet das, dass ein Pod, der die App enthält, mit einem spezifischen Image gestartet werden muss, das die benötigte System Software (z.B. PHP) enthält.

Vor dem Rollout dieses Changes hat der App-Service, der unsere Cloud Infrastruktur bedient, sowohl die Apps erstellt, als auch die jeweiligen Pods mit den entsprechenden Images gestartet. Das bedeutet, dass jede App in ihrem eigenen Pod lebt. Jeder dieser Pods enthält einen eigenen Container mit seinem eigenen Container-Image.

Jeder Pod enthält einen eigenen Container mit eigenem Container-Image
Vor dem Rollout: Jede App lebt in ihrem eigenen Pod.

Warum ist das so gewesen? Damit wir unseren Kunden etwa anbieten können, für jede App die jeweils benötigte PHP-Version zu installieren. Um Ressourcen zu schonen, indem weniger Pods und somit weniger Overhead im Sinne von RAM und CPU bereitgestellt werden müssen, haben wir im Rahmen dieses Rollouts aufgehört, die Pods im App-Service zu verwalten und für jede App einen separaten Pod zu starten. Stattdessen werden die Images implizit mit dem Ziel maximaler Kompatibilität erstellt und die Apps auf Pods mit diesen Images verteilt. Wenn die Systemanforderungen zweier (oder mehrerer) Apps zueinander kompatibel sind, also bspw. beide PHP 8.2.10 benötigen, dann werden diese in einem Pod zusammengefasst. Das bedeutet, dass wir nun nicht mehr einen Pod pro App haben, sondern nur noch genau so viele, wie benötigt werden. Damit zusammenhängend haben wir die durch den App-Service erstellten und nicht mehr benötigten Pods (und Images) gelöscht.

Nach dem Rollout: Haben 2 Apps die selben Systemanforderungen, werden sie in einem Pod zusammengefasst.
Nach dem Rollout: Haben 2 Apps die selben Systemanforderungen, werden sie in einem Pod zusammengefasst.

Und hier lag die Ursache der Störung begraben. Damit Cronjobs exakt die System Software nutzen können, die für die jeweils zugeordnete App definiert sind, müssen diese mit dem gleichen Image wie die App laufen. Um eine geeignete Abstraktionsschicht für den Kunden zu schaffen, ordnet der Kunde jeden Cronjob im mStudio einer App zu.  Unter der Haube wird anschließend das richtige Image ausgewählt. Dies funktionierte, da der Name des Images aus der ID der App abgeleitet werden kann. Durch den Verlust der 1:1 Relation zwischen App und Image galt diese Prämisse nicht mehr – ein Umstand, den wir übersahen: Wir gingen davon aus, dass Cronjobs bereits auf Apps (und nicht Images) verweisen, und die Cloud-Plattform im Hintergrund auf Zuordnung von App zu Container-Image übernahm. Das bedeutet, dass die Cronjobs, die seit dem Rollout ausgeführt werden sollten, auf Images verwiesen, die nicht mehr existierten. Die Cronjobs konnten aus diesem Grund nicht mehr ausgeführt werden.

Schadensbegrenzung und Lösung

Nachdem wir die Ursache des Problems identifiziert hatten, eröffneten sich zwei Lösungsoptionen:

  • Wir lassen die Cronjobs auf Apps verweisen und erweitern die unterliegende Cloud-Plattform dahingehend, dass automatisch das richtige Image ausgewählt wird.
  • Wir rollen die Änderungen zurück. Dann führen wir die erste Option aus und führen den Rollout zu einem späteren Zeitpunkt erneut durch.

Maßgeblich für die Entscheidung war, den Impact auf unsere Kunden so gering wie möglich zu halten. Aufgrund der Erfahrung des nächtlichen Rollouts, der über alle Projekte hinweg in etwa 3,5 Stunden in Anspruch nahm, entschieden wir uns für die erste Option. Es war davon auszugehen, dass dies nicht länger dauern würde, als die Änderungen zurückzurollen.

Lessons Learned

Qualitätssicherung in der Softwareentwicklung ist uns wichtig; bei der Entwicklung von Softwarekomponenten folgen wir den etablierten Best Practices und verifizieren die Funktion unserer Software durch eine durchmischte Teststrategie, die aus Unit-, Integration-, Regression- und End-zu-End-Tests besteht. Durch Methoden der kontinuierlichen Integration stellen wir sicher, dass jede Code-Änderung diesen Testplan durchläuft, bevor sie zunächst in ein Staging-System, und schließlich in die Produktivumgebung ausgeliefert wird. Auch über unseren Qualitätssicherungsprozess haben wir schon zuvor berichtet, etwa über unsere Test- und Fehlerbehandlungsstrategien oder unsere CI-Mechanismen.

Der Ausfall von Cronjob Ausführungen ist im Vorfeld des Rollouts nicht aufgefallen, weil die Grenzen unserer End-to-End-Tests bisher an der API zur Plattform definiert waren. Prozesse, die abseits dieser API stattfinden, waren davon bisher ausgeschlossen. Deshalb konnte der Fehler in der Integration zwischen mStudio und Cloud Plattform nicht festgestellt werden. Das werden wir nun ändern. Es laufen bereits erste Prozesse, um geeignete Wege zu finden, ganzheitlich End-to-End-Tests "zu Ende" zu denken. Denkbar wären hier bspw. Smoke Tests für die Kernbestandteile mit dem höchsten Kunden Impact. Für Cronjobs könnte das bedeuten, in einem Monitoring Project in unserer mStudio Staging Umgebung regelmäßig Cronjobs anzulegen. So könnten wir die erfolgreiche Ausführung auf der Cloud Infrastruktur überwachen.

Des Weiteren haben wir festgestellt, dass die Fehlerbehebung durch eine unzureichende Skalierung der Kubernetes Kontrollschicht verlangsamt wurde. Auch hier werden bereits erste Maßnahmen unternommen, um kritische Komponenten der Kubernetes Cluster zu skalieren.

Tipp!

Nimm unser Managed Cloud Hosting unter die Lupe. Einfach den proSpace 10 Tage kostenlos testen. Gib deinem Projekt die Ressourcen die es benötigt, packe Node.js & Redis fully managed drauf und los geht's!

Ähnliche Artikel:

Managed Cloud Hosting von mittwald
Hosting

Architektur der Managed Private Cloud

Performance, Skalierbarkeit, Zuverlässigkeit - darauf ist unsere Managed Private Cloud optimiert. Lies hier, wie wir dabei vorgegangen sind.

Node.js multithreaded
Webentwicklung

High Computational Load Performance mit Node.JS Multithreading optimieren

Node.JS läuft nur single threaded? Falsch! Wir erklären dir Node.JS Multithreading anhand eines Beispiels aus der Praxis.

Automatisiere deine Hosting-Prozesse
Hosting

mStudio API – Automatisiere deine Prozesse

Mit der API kannst du alle Prozesse des mStudios in deine individuelle Umgebung integrieren. Für Infos für Tipps geht's hier lang.

Kommentare

Okay, wow ... ja, trotz Tests ist eben doch nicht immer alles garantiert in Ordnung und der harte Realitäts-Check gibt dann das entsprechende Feedback und den nötigen Druck, um die vorher unbekannten Problem zu lösen.
Danke für den Einblick – das schafft Vertrauen :)
Antworten

Kommentar hinzufügen