Der Zusammenbruch eines verteilten Systems kann mit einem scheinbar begrenzten Fehler beginnen, sich jedoch schnell zu einer Kette von Ausfällen entwickeln, wenn viele Komponenten voneinander abhängen. In einem Vortrag erläutert Sam Newman, wie der unabhängige Berater für Softwareentwicklung das Konzept des kaskadierenden Zusammenbruchs (Progressive Collapse) aus dem Bauwesen mit Problemen der Resilienz in digitalen Systemen verknüpft. Er kommt zu dem Schluss, dass sich nicht jeder Fehler verhindern lässt, dass sich jedoch die Wahrscheinlichkeit seiner Ausbreitung und seine Auswirkungen verringern lassen.
Vom Gebäude Ronan Point zu Cloud-Diensten
Newman blickt auf den teilweisen Einsturz des Hochhauses Ronan Point im Londoner Stadtteil Canning Town im Jahr 1968 zurück. Eine begrenzte Gasexplosion in der Wohnung von Mrs. Ivy Hodge riss eine Außenwand heraus, die einen Teil des Gebäudes trug. Die vier Stockwerke oberhalb des Explosionsortes stürzten ein; anschließend führte dies in einer Kettenreaktion zum Einsturz eines Teils der Gebäudeecke. Vier Menschen starben. Der Zeitpunkt des Unglücks kurz vor sechs Uhr morgens trug dazu bei, die Zahl der Opfer zu begrenzen.
Die Bedeutung für Software liegt nicht in der materiellen Ähnlichkeit zwischen einem Gebäude und einem digitalen Dienst, sondern im Fehlermuster: Ein kleiner anfänglicher Ausfall beeinträchtigt eine Komponente, von der andere Komponenten abhängen, sodass sich der Schaden ausweitet. In verteilten Systemen ist diese Kette schwer zu verstehen, weil die Beziehungen zwischen Diensten, Datenbanken, Load Balancern und DNS-Systemen nicht immer wie eine Reihe von Dominosteinen sichtbar sind.
Digitale Beispiele für kaskadierende Ausfälle
Beim Ausfall der AWS-Region us-east-1 im Oktober hatte eine Unterkomponente von DynamoDB Probleme bei der Aktualisierung von DNS-Routen innerhalb der AWS-Infrastruktur. Ein Fehler beim Aktualisieren der Pläne führte dazu, dass Routen in Route 53 gelöscht wurden. Anschließend begannen Dienste auszufallen, die von diesen Routen abhingen, darunter Network Load Balancer, Computing, Warteschlangen und EKS. Da diese grundlegenden Dienste von anderen Diensten genutzt werden, griff das Problem auf Produkte und Unternehmen mit direktem Nutzerkontakt über, darunter Alexa, Ring, Slack, Snapchat, Zoom und Shopify. Einige waren teilweise, andere vollständig betroffen.
Nach Newmans Darstellung, die auf einem AWS-Bericht beruht, umfasste das System einen Planer, der DNS-Änderungspläne erstellte, sowie mehrere Ausführer, die diese anwendeten. Einer der Pläne benötigte länger als gewöhnlich. Danach wurde ein weiterer Plan erstellt, den ein anderer Ausführer schnell umsetzte. Als die Ausführung des alten Plans später abgeschlossen wurde, entfernte er die Routen, die der neue Plan angelegt hatte. Das Ergebnis war eine Race Condition, die zum Löschen von DNS-Einträgen führte.
Das zweite Beispiel betraf eine Website für den Verkauf gebrauchter Autos, Motorräder und Anhänger. Sie lief über eine Anwendung mit dem Codenamen Sauron auf zehn Servern. Die Anwendung war gewöhnlich für 30 bis 60 gleichzeitige Anfragen ausgelegt, sah sich jedoch mit mehr als 800 Anfragen konfrontiert. Eine der abhängigen Websites nahm Verbindungen an und blieb anschließend ohne Antwort hängen, während die Anwendung 30 Sekunden wartete, bevor sie die Anfrage beendete. Der Verbindungspool wurde erschöpft. Danach stauten sich die Threads, und die Prozessoren verbrachten ihre Zeit mit deren Verwaltung, sodass das System vollständig ausfiel. Die Nutzer erhöhten die Belastung zusätzlich, indem sie wiederholt auf die Aktualisierungsschaltfläche klickten.
Drei Wege zur Begrenzung des Zusammenbruchs
Newman ist der Ansicht, dass die Konzentration auf eine einzige „Grundursache“ zu einer unzulässigen Vereinfachung führt. Die Verhinderung des Funkens kann zwar hilfreich sein, beseitigt jedoch nicht alle Bedingungen, unter denen sich ein Feuer ausbreiten kann. Daher konzentriert sich die Resilienztechnik darauf, die Möglichkeit von Ausfällen zu akzeptieren und sich darauf vorzubereiten, ihre Auswirkungen durch drei miteinander verbundene Kategorien zu begrenzen:
- Risiken reduzieren: Gefahrenquellen beseitigen oder ihre Fähigkeit begrenzen, Ressourcen zu erschöpfen. Im Fall von AWS gehörte dazu, die automatische DNS-Verwaltung vorübergehend zu stoppen, bis das Problem behoben war, und bessere Tests für die Komponente hinzuzufügen. In der Sauron-Anwendung hätte Load Shedding eingesetzt werden können, um eine bestimmte Anzahl von Anfragen anzunehmen und darüber hinausgehende Anfragen abzulehnen, statt sie so lange anwachsen zu lassen, bis das System zusammenbricht.
- Komponenten stärken: Die Fähigkeit eines Dienstes erhöhen, den Ausfall eines Teils zu verkraften, etwa durch Redundanz, Überwachung, Tests und eine verbesserte Ausführung. Dies kann bedeuten, mehrere Instanzen des Dienstes hinter einem Load Balancer zu betreiben. Die Entscheidung hängt jedoch von der Bedeutung und den Kosten der Komponente ab. Die Sauron-Anwendung befand sich in einer Ausmusterungsphase und machte nur einen Teil der Einnahmen aus, weshalb der Betrieb zusätzlicher Backup-Instanzen zu diesem Zeitpunkt wirtschaftlich unattraktiv war.
- Kopplung reduzieren: Verhindern, dass der Ausfall einer einzelnen Komponente auf den übrigen Teil des Systems übergreift. Dazu gehören der Einsatz von Bulkheads, Zeitüberschreitungen, alternativen Pfaden und, wann immer möglich, lokale Designs. Je geringer die Abhängigkeit eines Systemteils von einem anderen ist, desto eher lässt sich ein Ausfall eingrenzen, statt ihn weiterzuverbreiten.
Was ändert sich praktisch für Technologieteams?
Resilienz bedeutet nicht automatisch, ein System in zwei Regionen oder zwei Clouds zu betreiben. Newman erklärt, dass die Möglichkeiten von Backup und Wiederherstellung über eine Pilot-Light-Architektur, bei der die Daten repliziert werden, ohne die gesamte Infrastruktur zu betreiben, und Warm Recovery bis hin zum gleichzeitigen Betrieb zweier aktiver Standorte reichen. Diese Optionen verringern Ausfallzeiten und Datenverlust schrittweise, erhöhen jedoch Kosten und Komplexität.
Er warnt außerdem davor, die bidirektionale Synchronisierung zwischen Standorten als einfach zu betrachten, insbesondere wenn sie zu einer bestehenden Anwendung hinzugefügt wird, die nicht dafür konzipiert wurde. Dasselbe gilt für Multi-Cloud-Umgebungen. Sie können die Abhängigkeit von einem einzigen Anbieter verringern, erfordern jedoch für jede Plattform andere Fähigkeiten und Betriebsabläufe. Es reicht nicht aus, denselben Code auf AWS und Azure bereitzustellen, um Unabhängigkeit zu gewährleisten, da derselbe Softwarefehler beide Umgebungen außer Betrieb setzen kann.
Fazit
Die zentrale Lehre lautet, dass Resilienz nicht nach einer Umgebung sucht, die niemals ausfällt, sondern das System so gestaltet, dass ein Teil funktionsfähig bleibt, wenn ein anderer Teil ausfällt. Daher sollten Risiken, Kapazitätsgrenzen, Engpässe und Abhängigkeitspfade bewertet und anschließend Redundanz, Isolation und Kosten gegeneinander abgewogen werden. Entscheidungen wie der Betrieb über mehrere Regionen oder mehrere Clouds bleiben technische und geschäftliche Optionen, die von der Bedeutung des Dienstes abhängen, und sind kein allgemeingültiges Rezept für jedes System.