Das Heisenbergsche UnschÀrfeprinzip besagt, dass man die Position eines Objekts und seine Geschwindigkeit nicht gleichzeitig messen kann. Bewegt sich das Objekt, hat es keinen festen Standort. Ist ein Standort vorhanden, bedeutet das, dass es keine Geschwindigkeit hat.

In Bezug auf Microservices auf der Red Hat OpenShift-Plattform (und verwaltet von Kubernetes) können sie dank entsprechender Open-Source-Software gleichzeitig ihre Leistung und FunktionsfĂ€higkeit melden. Das widerlegt zwar nicht Heisenberg, beseitigt jedoch die Unsicherheit im Umgang mit Cloud-Anwendungen. Istio ermöglicht eine einfache Organisation von Trace- und Monitoring-Funktionen fĂŒr solche Anwendungen, um alles im Blick zu behalten.
Lass uns ĂŒber Terminologie entscheiden
Unter Tracing (Tracing) Wir verstehen die Protokollierung systemischer AktivitĂ€ten. Das klingt zwar recht allgemein, aber die wichtigste Regel hier ist, dass die Trace-Daten in das entsprechende Speicherformat zurĂŒckgegeben werden, ohne sich um deren Formatierung zu kĂŒmmern. Die gesamte Arbeit der Datensuche und -analyse obliegt ihren Nutzern. In Istio wird das Tracing-System Jaeger verwendet, das das OpenTracing-Datenmodell implementiert.
Traces (Traces, und das Wort âTracesâ wird hier im Sinne von âSpurenâ verwendet, Ă€hnlich wie in der ballistischen Analyse) nennen wir die Daten, die den Verlauf einer Anfrage oder einer Arbeitseinheit vollstĂ€ndig beschreiben, wie man so schön sagt, âvon Anfang bis Endeâ. Zum Beispiel alles, was passiert, ab dem Moment, in dem ein Benutzer auf eine SchaltflĂ€che auf der Webseite klickt, bis zur RĂŒckgabe der Daten, einschlieĂlich aller beteiligten Mikrodienste. Man kann sagen, dass ein Trace den gesamten Verlauf einer Anfrage hin und zurĂŒck vollstĂ€ndig beschreibt (oder modelliert). Im Jaeger-Interface werden die Traces zeitlich aufgeschlĂŒsselt, Ă€hnlich wie man eine Kette in ihre einzelnen Glieder zerlegen kann. Nur dass anstelle der Glieder ein Trace aus sogenannten Spans besteht.
Span â ist der Zeitraum vom Beginn der AusfĂŒhrung einer Arbeitseinheit bis zu ihrem Abschluss. In dieser Analogie kann man sagen, dass jeder Span ein einzelnes Glied in der Kette darstellt. Ein Span kann (oder kann nicht) einen oder mehrere untergeordnete Spans haben. Folglich wird der oberste Span (Root Span) die gleiche Gesamtdauer haben wie der Trace, auf den er sich bezieht.
Ăberwachung â ist eigentlich die Ăberwachung Ihres Systems â mit eigenen Augen, ĂŒber die UI oder durch Automatisierungstools. Dem Monitoring liegen Trace-Daten zugrunde. In Istio wird das Monitoring durch Prometheus realisiert und hat eine entsprechende UI. Prometheus unterstĂŒtzt die automatische Ăberwachung mithilfe von Alerts und Alert Managern.
Wir machen Striche
Um die Tracing-FunktionalitĂ€t zu ermöglichen, muss die Anwendung eine Sammlung von Spans erstellen. Diese mĂŒssen dann an Jaeger exportiert werden, damit ein visuelles Tracing-Diagramm erstellt werden kann. Unter anderem kennzeichnen diese Spans den Namen der Operation sowie die Zeitstempel fĂŒr ihren Beginn und Abschluss. Der Transfer der Spans erfolgt durch die Umleitung der fĂŒr Jaeger bestimmten HTTP-Header von eingehenden Anfragen zu ausgehenden Anfragen. Je nach verwendeter Programmiersprache kann dies geringfĂŒgige Anpassungen des Quellcodes der Anwendungen erfordern. Im Folgenden ist ein Beispielcode in Java (unter Verwendung des Spring Boot-Frameworks) angegeben, der B3-Header (Zipkin-Stil) zu Ihrer Anfrage im Konfigurationsklasse von Spring hinzufĂŒgt:

Dabei werden die folgenden Header-Einstellungen verwendet:

Wenn Sie Java verwenden, mĂŒssen Sie den Code nicht Ă€ndern, sondern lediglich einige Zeilen zur POM-Datei von Maven hinzufĂŒgen und Umgebungsvariablen festlegen. Hier sind die Zeilen, die in die POM.XML-Datei eingefĂŒgt werden mĂŒssen, um den Jaeger Tracer Resolver zu integrieren:

Die entsprechenden Umgebungsvariablen werden im Dockerfile festgelegt:

Alles klar, jetzt ist alles eingerichtet und unsere Mikrodienste beginnen, Tracedaten zu generieren.
Wir schauen uns das im GroĂen und Ganzen an
Istio beinhaltet ein einfaches Dashboard auf Basis von Grafana. Wenn alles konfiguriert ist und auf der Red Hat OpenShift PaaS-Plattform lÀuft (in unserem Beispiel sind Red Hat OpenShift und Kubernetes auf Minishift bereitgestellt), wird dieses Dashboard mit folgendem Befehl gestartet:
open "$(minishift openshift service grafana -u)/d/1/istio-dashboard?refresh=5⩝Id=1"
Das Grafana-Dashboard ermöglicht eine schnelle Bewertung der Systemleistung. Ein Ausschnitt dieses Dashboards ist in der Abbildung unten dargestellt:

Hier sieht man, dass der Mikrodienst customer den Mikrodienst preference v1 aufruft, und dieser wiederum ruft die Mikrodienste recommendation v1 und v2 auf. Im Grafana-Dashboard gibt es einen Bereich Dashboard Row fĂŒr hochrangige Metriken wie das Gesamtanfragevolumen (Global Request Volume), die Erfolgsquote (success rates) und 4xx-Fehler. DarĂŒber hinaus gibt es eine Ansicht Server Mesh mit Grafiken fĂŒr jeden Dienst und einen Bereich Services Row zur Anzeige detaillierter Informationen zu jedem Container fĂŒr jeden Dienst.
Jetzt tauchen wir tiefer ein
Mit einer korrekt konfigurierten Istio-Tracierung kann man direkt out of the box tiefgehende Leistungsanalysen des Systems durchfĂŒhren. Im Jaeger-UI können Tracierungen betrachtet werden, um zu sehen, wie weit und tief sie reichen, sowie um EngpĂ€sse in der Leistung visuell zu identifizieren. Bei der Verwendung von Red Hat OpenShift auf der Plattform minishift starten Sie die Jaeger-UI mit folgendem Befehl:
minishift openshift service jaeger-query --in-browser

Was kann man ĂŒber die Tracierung auf diesem Screenshot sagen:
- Sie besteht aus 7 Spans.
- Die Gesamtzeit betrÀgt 6,99 ms.
- Der Microservice recommendation, der der letzte in der Kette ist, benötigt 0,69 ms.
Diagramme dieser Art ermöglichen es, schnell zu erkennen, wenn die Leistung des gesamten Systems aufgrund eines nicht einwandfrei funktionierenden Dienstes leidet.
Und jetzt erschweren wir die Aufgabe, indem wir zwei Instanzen des Microservices recommendation:v2 mit dem Befehl oc scale --replicas=2 deployment/recommendation-v2 starten. So sehen unsere Pods danach aus:

Wenn wir jetzt zu Jaeger zurĂŒckwechseln und den Span fĂŒr den Service recommendation aufklappen, sehen wir, welcher Pod die Anfragen verarbeitet. So können wir problemlos die Verzögerungen auf der Ebene eines bestimmten Pods lokalisieren. Dabei sollten wir auf das Feld node_id achten:

Wohin und wie alles lÀuft
Jetzt gehen wir in die BenutzeroberflĂ€che von Prometheus und sehen erwartungsgemĂ€Ă, dass die Anfragen zwischen der zweiten und der ersten Version des Services recommendation im VerhĂ€ltnis 2:1 aufgeteilt sind, genau nach der Anzahl der aktiven Pods. Dieser Graph wird sich dynamisch Ă€ndern, wenn die Pods nach oben oder unten skaliert werden, was besonders nĂŒtzlich beim Canary Deployment sein wird (wir werden dieses Bereitstellungsschema beim nĂ€chsten Mal ausfĂŒhrlicher betrachten).

Alles fÀngt gerade erst an
TatsĂ€chlich haben wir heute, sozusagen, nur einen kleinen Einblick in den reichen Fundus an Informationen zu Jaeger, Grafana und Prometheus gegeben. Das war im Grunde auch unser Ziel â Sie in die richtige Richtung zu leiten und die Perspektiven von Istio zu eröffnen.
Und denken Sie daran, dass all dies bereits in Istio integriert ist. Bei der Verwendung bestimmter Programmiersprachen (wie Java) und Frameworks (wie Spring Boot) kann all dies umgesetzt werden, ohne den Anwendungscode berĂŒhren zu mĂŒssen. Ja, der Code muss leicht modifiziert werden, wenn Sie andere Sprachen verwenden, insbesondere Node.js oder C#. Aber da Nachverfolgbarkeit (lesen Sie "Tracing") eine der Voraussetzungen fĂŒr den Aufbau zuverlĂ€ssiger Cloud-Systeme ist, mĂŒssen Sie den Code in jedem Fall anpassen, ob Sie Istio nutzen oder nicht. Warum also nicht die Anstrengungen sinnvoller nutzen?
Mindestens um immer die Fragen âwo?â und âwie schnell?â mit 100%iger Sicherheit zu beantworten.
Chaos-Engineering in Istio: So war es gedacht
Die FĂ€higkeit, Dinge kaputt zu machen, hilft dabei, sicherzustellen, dass sie nicht kaputtgehen.
Die Software-Testung ist nicht nur eine komplizierte, sondern auch eine wichtige Aufgabe. Gleichzeitig ist die ĂberprĂŒfung auf Korrektheit (zum Beispiel ob eine Funktion das richtige Ergebnis zurĂŒckgibt) das eine, wĂ€hrend das Testen unter Bedingungen eines unzuverlĂ€ssigen Netzwerks eine ganz andere Herausforderung darstellt (oft wird angenommen, dass das Netzwerk immer ohne Störungen funktioniert, und das ist die hĂ€ufigste von acht FehleinschĂ€tzungen im Bereich der verteilten Berechnungen). Eine der Schwierigkeiten bei der Lösung dieser Problematik liegt darin, wie man SystemausfĂ€lle simuliert oder absichtlich einfĂŒhrt, was als Fault Injection bezeichnet wird. Dies kann durch die Modifikation des Quellcodes der Anwendung erfolgen. Doch dann testen Sie nicht Ihren ursprĂŒnglichen Code, sondern eine Version, die speziell AusfĂ€lle simuliert. Infolgedessen riskieren Sie, in die tödlichen Umarmungen der Fault Injection zu geraten und auf Geisterfehler zu stoĂen â Fehler, die beim Versuch, sie zu erkennen, verschwinden.
Nun werden wir zeigen, wie Istio hilft, diese Herausforderungen schnell zu bewÀltigen.
So sieht alles aus, wenn alles perfekt lÀuft.
Betrachten wir folgendes Szenario: Wir haben zwei Pods fĂŒr unseren Microservice Recommendation, den wir aus einem Istio-Lehrbuch entnommen haben. Ein Pod ist als v1 gekennzeichnet, der andere als v2. Wie zu sehen ist, funktioniert alles hervorragend.

(Ăbrigens: Die Zahl rechts ist einfach ein ZĂ€hler fĂŒr jeden Pod.)
Aber das ist nicht das, was wir wollen, oder? Lassen Sie uns versuchen, alles kaputt zu machen, ohne den Quellcode zu berĂŒhren.
Wir erzeugen AusfÀlle im Microservice
Nachfolgend finden Sie die YAML-Datei fĂŒr die Istio-Routingregel, die in der HĂ€lfte der FĂ€lle einen Fehler erzeugt. Server 503):

Bitte beachten Sie, dass wir explizit festlegen, dass in der HĂ€lfte der FĂ€lle ein Fehler 503 zurĂŒckgegeben werden soll.
So wĂŒrde ein Screenshot des wiederholt ausgefĂŒhrten curl-Befehls aussehen, nachdem wir diese Regel aktiviert haben, um Fehler zu simulieren. Wie zu sehen ist, gibt die HĂ€lfte der Anfragen den Fehler 503 zurĂŒck, unabhĂ€ngig davon, an welchen Pod â v1 oder v2 â sie gesendet werden:

Um den normalen Betrieb wiederherzustellen, reicht es aus, diese Regel zu löschen, in unserem Fall mit dem Kommando istioctl delete routerule recommendation-503 -n tutorial. Hierbei ist Tutorial der Name des Red Hat OpenShift-Projekts, in dem unser Istio-Lehrbuch lÀuft.
Wir fĂŒgen kĂŒnstliche Verzögerungen hinzu.
KĂŒnstliche Fehler 503 helfen dabei, das System auf Ausfallsicherheit zu testen, aber die FĂ€higkeit, Verzögerungen vorherzusagen und zu bewĂ€ltigen, sollte Sie noch mehr beeindrucken. TatsĂ€chlich treten Verzögerungen im echten Leben hĂ€ufiger auf als AusfĂ€lle. Ein langsam arbeitender Mikroservice ist ein Gift, unter dem das gesamte System leidet. Dank Istio können Sie den Code zur Verarbeitung von Verzögerungen testen, ohne ihn dabei zu Ă€ndern. ZunĂ€chst zeigen wir Ihnen, wie Sie dies im Fall kĂŒnstlich erzeugter Netzwerkverzögerungen tun können.
Bitte beachten Sie, dass Sie nach solch einem Test eventuell (oder möglicherweise) Ihren Code ĂŒberarbeiten mĂŒssen (oder möchten). Die gute Nachricht ist, dass Sie in diesem Fall proaktiv und nicht reaktiv handeln werden. So sollte der Entwicklungszyklus aufgebaut werden: Programmieren-Testen-Feedback-Programmierenn-TestenâŠ
So sieht die Regel aus, die⊠Obwohl wissen Sie was? Istio ist so einfach und diese yaml-Datei ist so verstĂ€ndlich, dass alles in diesem Beispiel fĂŒr sich selbst spricht, schauen Sie einfach einmal hin:

In der HĂ€lfte der FĂ€lle wird es zu einer 7-sekĂŒndigen Verzögerung kommen. Das ist keineswegs das gleiche, als wĂŒrden wir im Quellcode einen sleep-Befehl einfĂŒgen, denn Istio verzögert die Anfrage tatsĂ€chlich um 7 Sekunden. Da Istio Jaeger-Tracing unterstĂŒtzt, ist diese Verzögerung im Jaeger-UI gut erkennbar, wie im Screenshot unten gezeigt. Beachten Sie die lange Anfrage in der oberen rechten Ecke des Diagramms â ihre Dauer betrĂ€gt 7,02 Sekunden:

Dieses Szenario ermöglicht es, den Code unter Bedingungen mit Netzwerkverzögerungen zu testen. Und es ist klar, dass wir durch das Entfernen dieser Regel die kĂŒnstliche Verzögerung beseitigen werden. Um es zu wiederholen, wir haben all dies erneut getan, ohne den Quellcode zu verĂ€ndern.
Nicht zurĂŒckweichen und nicht aufgeben
Eine weitere nĂŒtzliche Funktion von Istio fĂŒr Chaos Engineering ist die Wiederholung von Anfragen an einen Dienst eine bestimmte Anzahl von Malen. Der Sinn dahinter ist, die Versuche nicht abzubrechen, wenn die erste Anfrage mit einem Fehler 503 endet â und vielleicht haben wir beim N-ten Mal GlĂŒck. Vielleicht hat der Dienst aus irgendeinem Grund nur kurz pausiert. Ja, diesen Grund sollten wir ergrĂŒnden und beheben. Aber das können wir spĂ€ter klĂ€ren; vorerst versuchen wir, das System am Laufen zu halten.
Also, wir wollen, dass der Dienst von Zeit zu Zeit einen Fehler 503 gibt, und Istio sollte danach versuchen, ihn erneut zu kontaktieren. Hier benötigen wir eindeutig eine Möglichkeit, einen Fehler 503 zu erzeugen, ohne den Code selbst zu berĂŒhren...
Halt, wartet! Das haben wir gerade gemacht.
Diese Datei sorgt dafĂŒr, dass der Dienst recommendation-v2 in 50 % der FĂ€lle einen Fehler 503 zurĂŒckgibt:

Offensichtlich werden einige Anfragen fehlschlagen:

Jetzt aktivieren wir die Istio-Funktion Retry:

Diese Routing-Regel fĂŒhrt drei Wiederholungen mit einem Intervall von zwei Sekunden durch und sollte die Fehler 503 reduzieren (ideal wĂ€re es, sie ganz zu entfernen):

Zusammenfassend haben wir es so eingerichtet, dass Istio erstens fĂŒr die HĂ€lfte der Anfragen einen 503-Fehler generiert. Und zweitens fĂŒhrt dasselbe Istio bei einem auftreten Fehler 503 drei Versuche durch, um die Verbindung zum Dienst wiederherzustellen. Das Ergebnis ist einfach ausgezeichnet. Durch die Nutzung der Retry-Funktion haben wir unser Versprechen eingehalten, nicht aufzugeben und durchzuhalten.
Ja, und wir haben es wieder getan, ohne den Code ĂŒberhaupt zu berĂŒhren. Alles, was wir benötigten, waren zwei Istio-Routing-Regeln:

Wie man den Benutzer nicht enttÀuscht oder sieben auf einen wartet
Jetzt kehren wir die Situation um und betrachten ein Szenario, in dem es nur fĂŒr eine gewisse Zeit sinnvoll ist, nicht aufzugeben und durchzuhalten. Danach sollten wir einfach die Versuche, die Anfrage zu verarbeiten, einstellen, um nicht alle dazu zu bringen, auf einen einzigen blockierenden Dienst zu warten. Anders ausgedrĂŒckt, wir werden die verlorene Position nicht verteidigen, sondern uns auf eine Backup-Position zurĂŒckziehen, um die Benutzer der Website nicht zu enttĂ€uschen und sie nicht in Ungewissheit zu halten.
In Istio kann ein Timeout fĂŒr die Anfragebearbeitung festgelegt werden. Wenn der Dienst dieses Timeout ĂŒberschreitet, wird der Fehler 504 (Gateway Timeout) zurĂŒckgegeben â das alles geschieht ĂŒber die Istio-Konfiguration. Allerdings mĂŒssen wir in den Quellcode des Dienstes einen sleep-Befehl einfĂŒgen (und dann natĂŒrlich ein Rebuild und Redeploy durchfĂŒhren), um die langsame AusfĂŒhrung des Dienstes zu simulieren. Leider geht es nicht anders.
Also haben wir einen dreisekĂŒndigen sleep in den Code des Dienstes recommendation v2 eingefĂŒgt, das entsprechende Image neu gebaut und den Container redeployt. Jetzt fĂŒgen wir mit der folgenden Istio-Routingregel das Timeout hinzu:

Im obigen Screenshot ist zu sehen, dass wir die Verbindung zum Dienst recommendation abbrechen, wenn wir innerhalb von einer Sekunde keine Antwort erhalten, also noch bevor der Fehler 504 auftritt. Nach Anwendung dieser Routingregel (und dem HinzufĂŒgen des dreisekĂŒndigen sleep im Code des Dienstes recommendation:v2) erhalten wir Folgendes:

Wir wiederholen uns, aber das Timeout kann festgelegt werden, ohne den Quellcode zu Àndern. Ein zusÀtzlicher Vorteil ist, dass Sie Ihren Code jetzt so anpassen können, dass er auf das Timeout reagiert, und diese Anpassungen mit Istio problemlos testen können.
Und jetzt alles zusammen
Ein wenig Chaos mit Istio zu erzeugen, ist eine hervorragende Methode, um Ihren Code und die ZuverlĂ€ssigkeit Ihres Systems insgesamt zu testen. Fallback-Vorlagen, Bulkheads und Circuit Breaker, Mechanismen zur Erzeugung von kĂŒnstlichen AusfĂ€llen und Verzögerungen sowie erneute Aufrufe und Timeouts sind Ă€uĂerst nĂŒtzlich beim Aufbau von ausfallsicheren Cloud-Systemen. In Kombination mit Kubernetes und Red Hat OpenShift werden diese Werkzeuge Ihnen helfen, selbstbewusst in die Zukunft zu gehen.
Quelle: habr.com
