Istio Circuit Breaker: Deaktivierung defekter Container

Die Feiertage sind vorbei, und wir kehren mit unserem zweiten Beitrag aus der Reihe über Istio Service Mesh zurück.

Istio Circuit Breaker: Deaktivierung defekter Container

Das heutige Thema ist der Circuit Breaker, der im elektrotechnischen Sinne ins Deutsche als „automatischer Schalter“ übersetzt wird, umgangssprachlich als „Schutzschalter“. Nur dass dieser Schalter in Istio nicht einen kurzgeschlossenen oder überlasteten Stromkreis abschaltet, sondern defekte Container.

So sollte es idealerweise funktionieren

Wenn Mikrodienste von Kubernetes verwaltet werden, zum Beispiel innerhalb der OpenShift-Plattform, skalieren sie automatisch je nach Last nach oben oder unten. Da Mikrodienste in Pods arbeiten, können mehrere Instanzen eines containerisierten Mikrodienstes an einem Endpunkt vorhanden sein, und Kubernetes routet die Anfragen und lastet diese zwischen ihnen aus. Und - idealerweise - sollte das alles bestens funktionieren.

Wir denken daran, dass Mikrodienste klein und flüchtig sind. Diese Flüchtigkeit, die hier die Einfachheit des Entstehens und Verschwindens bedeutet, wird oft unterschätzt. Die Geburt und der Tod einer neuen Instanz des Mikrodienstes in einem Pod sind ganz normale Vorkommen, OpenShift und Kubernetes haben dies gut im Griff, und alles funktioniert großartig – aber wieder einmal nur in der Theorie.

Wie funktioniert es tatsächlich

Stellen Sie sich nun vor, dass eine bestimmte Instanz eines Mikrodienstes, also ein Container, ausgefallen ist: entweder antwortet er nicht (Fehler 503) oder - was unangenehmer ist - er reagiert, aber viel zu langsam. Mit anderen Worten, er hat kleine Aussetzer oder antwortet nicht auf Anfragen, wird aber dabei nicht automatisch aus dem Pool entfernt. Was soll in diesem Fall getan werden? Eine erneute Anfrage versuchen? Ihn aus dem Routing-Schema entfernen? Und was bedeutet „zu langsam“ – wie viel ist das in Zahlen, und wer legt diese fest? Vielleicht einfach eine Pause geben und es später erneut versuchen? Wenn ja, wie viel später?

Was ist Pool Ejection in Istio

Und hier kommt Istio mit seinen Circuit Breakern ins Spiel, die defekte Container vorübergehend aus dem Ressourcenpool für Routing und Lastenausgleich entfernen und das Verfahren der Pool Ejection umsetzen.

Durch die Verwendung einer Ausreißererkennung erkennt Istio fehlerhafte Pods, die aus der Allgemeinen Reihe herausfallen, und entfernt sie für eine bestimmte Zeit aus dem Ressourcenpool, die als „Schlafzeit“ (sleep window) bezeichnet wird.

Um zu zeigen, wie es in Kubernetes auf der OpenShift-Plattform funktioniert, beginnen wir mit einem Screenshot von ordnungsgemäß funktionierenden Microdiensten aus dem Beispiel im Repository. Red Hat Developer DemosHier haben wir zwei Pods, v1 und v2, in denen jeweils ein Container läuft. Wenn die Istio-Routing-Regeln nicht verwendet werden, wendet Kubernetes standardmäßig eine gleichmäßig verteilte zyklische Weiterleitung an:

Istio Circuit Breaker: Deaktivierung defekter Container

Vorbereiten auf den Ausfall

Bevor wir Pool-Ejection durchführen, müssen wir eine Istio-Routing-Regel erstellen. Angenommen, wir möchten die Anfragen zu je 50/50 zwischen den Pods verteilen. Darüber hinaus werden wir die Anzahl der Container v2 von eins auf zwei erhöhen, so:

oc scale deployment recommendation-v2 --replicas=2 -n tutorial

Jetzt legen wir eine Routing-Regel fest, um den Traffic zu je 50/50 zwischen den Pods zu verteilen.

Istio Circuit Breaker: Deaktivierung defekter Container
So sieht das Ergebnis dieser Regel aus:

Istio Circuit Breaker: Deaktivierung defekter Container
Man könnte bemängeln, dass auf diesem Screenshot nicht 50/50, sondern 14:9 zu sehen ist, aber im Laufe der Zeit wird sich die Situation ausgleichen.

Einen Ausfall herbeiführen

Jetzt nehmen wir einen der beiden Container v2 offline, sodass wir einen funktionierenden Container v1, einen funktionierenden Container v2 und einen defekten Container v2 haben:

Istio Circuit Breaker: Deaktivierung defekter Container

Einen Ausfall beheben

Also haben wir einen defekten Container, und es ist Zeit für Pool-Ejection. Mit einer sehr einfachen Konfiguration werden wir diesen defekten Container für 15 Sekunden aus allen Routing-Schemata ausschließen, in der Hoffnung, dass er selbst wieder funktionsfähig wird (entweder durch einen Neustart oder durch Wiederherstellung der Leistung). So sieht diese Konfiguration aus und die Ergebnisse ihrer Anwendung:

Istio Circuit Breaker: Deaktivierung defekter Container
Istio Circuit Breaker: Deaktivierung defekter Container
Wie zu sehen ist, wird der defekte Container v2 bei der Weiterleitung von Anfragen nicht mehr verwendet, da er aus dem Pool entfernt wurde. Nach 15 Sekunden kehrt er jedoch automatisch in den Pool zurück. Tatsächlich haben wir gerade gezeigt, wie Pool-Ejection funktioniert.

Beginnen mit dem Aufbau der Architektur

Pool-Ejection in Kombination mit den Überwachungsmöglichkeiten von Istio ermöglicht es, ein Framework für die automatische Ersetzung defekter Container zu schaffen, um Ausfallzeiten und Fehler zu minimieren oder sogar ganz zu beseitigen.

NASA hat einen einprägsamen Slogan – Failure Is Not an Option, der von dem Missionsleiter stammt. Gene Kranz. Auf Deutsch könnte man sagen: „Niederlage ist keine Option“. Die Bedeutung hier ist, dass alles zum Funktionieren gebracht werden kann, wenn genug Wille vorhanden ist. In der realen Welt jedoch sind Ausfälle nicht nur gelegentlich, sie sind unvermeidlich, überall und in allem. Wie geht man also mit ihnen um, wenn es um Mikrodienste geht? Unserer Meinung nach sollte man sich nicht auf den Willen, sondern auf die Möglichkeiten von Containern verlassen. Kubernetes, -Plattform bereitstellt. Weitere Informationen über die Funktionsweise finden Sie, und Istio.

Istio, wie bereits zuvor erwähnt, implementiert ein bewährtes Konzept aus der physischen Welt: die automatischen Sicherungen. So wie eine elektrische Sicherung einen problematischen Abschnitt des Stromkreises trennt, unterbricht der programmatische Circuit Breaker in Istio die Verbindung zwischen dem Anfragefluss und dem problematischen Container, wenn mit dem Endpunkt etwas nicht stimmt, zum Beispiel wenn der Server ausgefallen ist oder langsam arbeitet.

Im zweiten Fall sind die Probleme sogar noch größer, da die Verzögerungen eines Containers nicht nur Kaskadeneffekte in den darauf zugreifenden Diensten verursachen und somit die Gesamteffizienz des Systems mindern, sondern auch zu Wiederholungen von Anfragen an den ohnehin schon langsamen Dienst führen, was die Situation nur verschärft.

Circuit Breaker in der Theorie

Circuit Breaker ist ein Proxy, der den Anfragefluss zum Endpunkt kontrolliert. Wenn dieser Endpunkt nicht mehr funktioniert oder – abhängig von den Einstellungen – anfängt, langsam zu werden, trennt der Proxy die Verbindung zum Container. Der Datenverkehr wird anschließend auf andere Container umgeleitet, einfach aus Gründen der Lastverteilung. Die Verbindung bleibt für ein festgelegtes Schlafintervall, sagen wir zwei Minuten, geöffnet (open) und wird danach als halb geöffnet (half-open) betrachtet. Der Versuch, die nächste Anfrage zu senden, bestimmt den weiteren Zustand der Verbindung. Wenn alles mit dem Dienst in Ordnung ist, wird die Verbindung wieder in den Normalbetrieb überführt und geschlossen (closed). Wenn jedoch weiterhin Probleme mit dem Dienst bestehen, wird die Verbindung unterbrochen und das Schlafintervall wird erneut aktiviert. So sieht ein vereinfachtes Diagramm der Zustandsänderungen eines Circuit Breakers aus:

Istio Circuit Breaker: Deaktivierung defekter Container
Es ist wichtig zu beachten, dass dies alles auf einer sogenannten Systemarchitekturebene geschieht. Daher müssen Sie irgendwann Ihre Anwendungen darauf trainieren, mit Circuit Breaker zu arbeiten, indem Sie beispielsweise im Antwortwert einen Standardwert bereitstellen oder, wenn möglich, die Existenz des Dienstes ignorieren. Dafür wird das Bulkhead-Muster verwendet, aber das geht über den Rahmen dieses Artikels hinaus.

Circuit Breaker in der Praxis

Wir werden auf OpenShift zwei Versionen unseres Mikrodienstes für Empfehlungen starten. Version 1 wird normal funktionieren, während wir in v2 eine Verzögerung einbauen, um Verzögerungen auf dem Server zu simulieren. Zum Anzeigen der Ergebnisse wird das Tool verwendet siege:

siege -r 2 -c 20 -v customer-tutorial.$(minishift ip).nip.io

Istio Circuit Breaker: Deaktivierung defekter Container
Es scheint alles zu funktionieren, aber zu welchem Preis? Auf den ersten Blick haben wir 100 % Verfügbarkeit, aber schauen Sie genauer hin – die maximale Transaktionsdauer beträgt ganze 12 Sekunden. Das ist eindeutig ein Engpass und muss aufgebrochen werden.

Dafür werden wir mit Istio die Zugriff auf langsame Container ausschließen. So sieht die entsprechende Konfiguration mit Circuit Breaker aus:

Istio Circuit Breaker: Deaktivierung defekter Container
Die letzte Zeile mit dem Parameter httpMaxRequestsPerConnection signalisiert, dass die Verbindung unterbrochen werden muss, wenn versucht wird, eine weitere – zweite – Verbindung zusätzlich zur bereits bestehenden herzustellen. Da unser Container einen Bremservice simuliert, werden solche Situationen gelegentlich auftreten, und dann wird Istio einen Fehler 503 zurückgeben, und das zeigt siege an:

Istio Circuit Breaker: Deaktivierung defekter Container

Okay, wir haben einen Circuit Breaker, was nun?

So haben wir eine automatische Abschaltung implementiert, ohne den Code der Dienste selbst zu berühren. Mit Circuit Breaker und dem oben beschriebenen Verfahren zur Pool-Ausschluss können wir langsame Container aus dem Ressourcenpool entfernen, bis sie wieder in Ordnung sind, und ihren Zustand in festgelegten Zeitabständen überprüfen – in unserem Beispiel sind das zwei Minuten (Parameter sleepWindow).

Beachten Sie, dass die Fähigkeit der Anwendung, auf Fehler 503 zu reagieren, immer noch im Quellcode der Anwendung selbst festgelegt wird. Es gibt viele Strategien zur Arbeit mit Circuit Breaker, die je nach Situation angewendet werden.

Im nächsten Beitrag: werden wir über Tracing und Monitoring sprechen, die bereits in Istio integriert sind oder einfach hinzugefügt werden können, sowie über die absichtliche Fehlererzeugung im System.

Quelle: habr.com

60GB SSD 8Gb DDR4