Istio Tracing and Monitoring: Microservices und das Unsicherheitsprinzip

Das Heisenbergsche Unsicherheitsprinzip besagt, dass es unmöglich ist, die Position eines Objekts und seine Geschwindigkeit gleichzeitig zu messen. Wenn sich ein Objekt bewegt, hat es keinen Standort. Und wenn der Ort ist, bedeutet das, dass er keine Geschwindigkeit hat.



Bei Microservices auf der Red Hat OpenShift-Plattform (und unter Kubernetes) können sie dank der entsprechenden Open-Source-Software gleichzeitig ihre Leistung und ihren Zustand melden. Dies widerlegt natürlich nicht den alten Heisenberg, beseitigt jedoch die Unsicherheit beim Arbeiten mit Cloud-Anwendungen. Mit Istio ist es einfach, die Nachverfolgung und Überwachung solcher Anwendungen zu organisieren, um alles unter Kontrolle zu halten.

Terminologie definieren


Mit Ablaufverfolgung ist die Protokollierung der Systemaktivität gemeint. Es klingt ziemlich allgemein, aber in der Tat ist es eine der Hauptregeln, Trace-Daten in den entsprechenden Speicher zu kopieren, ohne sich Gedanken über die Formatierung zu machen. Die gesamte Suche und Analyse der Daten obliegt dem Verbraucher. Istio verwendet das Jaeger-Trace-System, das das OpenTracing-Datenmodell implementiert.

Mit Spuren (Spuren und das Wort "Spuren" wird hier in der Bedeutung von "Spuren" verwendet, wie zum Beispiel bei der ballistischen Untersuchung) sind Daten gemeint, die den Durchgang einer Anforderung oder Arbeitseinheit vollständig beschreiben, wie sie sagen: "von und bis". Zum Beispiel alles, was von dem Moment an passiert, in dem der Benutzer einen Knopf auf einer Webseite drückt, bis die Daten zurückgegeben werden, einschließlich aller damit verbundenen Microservices. Wir können sagen, dass eine Ablaufverfolgung den Durchlauf der Anforderung hin und her vollständig beschreibt (oder simuliert). In der Jaeger-Schnittstelle werden Spuren entlang der Zeitachse in Komponenten zerlegt, z. B. wie eine Kette in separate Glieder zerlegt werden kann. Nur anstelle von Links besteht der Track aus den sogenannten Spans.

Die Zeitspanne ist das Intervall vom Beginn einer Arbeitseinheit bis zu ihrer Fertigstellung. Wenn wir die Analogie fortsetzen, können wir sagen, dass jede Spanne ein separates Glied in der Kette ist. Ein Bereich kann ein oder mehrere untergeordnete Bereiche haben oder nicht. Infolgedessen hat die Spanne der obersten Ebene (Wurzelspanne) dieselbe Gesamtdauer wie die Spur, zu der sie gehört.

Überwachung ist in der Tat die Beobachtung Ihres Systems - durch die Augen, über eine Benutzeroberfläche oder durch Automatisierung. Die Überwachung basiert auf Trace-Daten. In Istio wird die Überwachung mit Prometheus-Tools implementiert und verfügt über eine entsprechende Benutzeroberfläche. Prometheus unterstützt die automatische Überwachung mithilfe von Warnmeldungen und Warnmeldungsmanagern.

Lass die Kerben


Damit die Rückverfolgung möglich ist, muss die Anwendung eine Auflistung von Bereichen erstellen. Dann müssen sie nach Jaeger exportiert werden, damit er wiederum eine visuelle Darstellung der Spur erstellt. Diese Bereiche kennzeichnen unter anderem den Namen des Vorgangs sowie die Zeitstempel von Beginn und Ende des Vorgangs. Spans werden gesendet, indem Jaeger-spezifische HTTP-Anforderungsheader von eingehenden Anforderungen an ausgehende Anforderungen weitergeleitet werden. Abhängig von der verwendeten Programmiersprache kann dies eine geringfügige Änderung des Anwendungsquellcodes erfordern. Im Folgenden finden Sie ein Beispiel für Java-Code (bei Verwendung des Spring Boot-Frameworks), der Ihrer Anforderung in der Spring-Konfigurationsklasse B3-Header (im Zipkin-Stil) hinzufügt:


Die folgenden Kopfzeileneinstellungen werden verwendet:


Wenn Sie Java verwenden, können Sie den Code unverändert lassen, indem Sie der Maven-POM-Datei einige Zeilen hinzufügen und Umgebungsvariablen festlegen. Hier sind die Zeilen, die Sie zur POM.XML-Datei hinzufügen müssen, um den Jaeger Tracer Resolver zu implementieren:


Und die entsprechenden Umgebungsvariablen werden in der Docker-Datei gesetzt:


Das war's, jetzt ist alles eingerichtet und unsere Microservices werden Trace-Daten generieren.

Wir schauen allgemein


Istio enthält ein einfaches Bedienfeld, das auf Grafana basiert. Wenn alles auf der Red Hat OpenShift PaaS-Plattform konfiguriert ist und ausgeführt wird (in unserem Beispiel werden Red Hat OpenShift und Kubernetes im Minischichtbetrieb bereitgestellt), wird dieses Fenster mit dem folgenden Befehl gestartet:

open "$(minishift openshift service grafana -u)/d/1/istio-dashboard?refresh=5⩝Id=1" 

Mit dem Grafana-Panel können Sie das System schnell bewerten. Ein Fragment dieses Panels ist in der folgenden Abbildung dargestellt:


Hier sehen Sie, dass der Microservice-Kunde die Microservice-Präferenz v1 und die Microservice-Empfehlung v1 und v2 aufruft. Das Grafana-Bedienfeld verfügt über einen Dashboard-Zeilenblock für Kennzahlen auf hoher Ebene, z. B. die Gesamtzahl der Anforderungen (globales Anforderungsvolumen), den Prozentsatz erfolgreicher Anforderungen (Erfolgsraten) und 4xx Fehler. Darüber hinaus gibt es eine Server-Mesh-Ansicht mit Diagrammen für jeden Dienst und einen Dienstzeilenblock, in dem detaillierte Informationen für jeden Container für jeden Dienst angezeigt werden.

Jetzt tiefer graben


Mit einer richtig konfigurierten Ablaufverfolgung können Sie mit Istio direkt nach dem Auspacken in die Analyse der Systemleistung eintauchen. In der Jaeger-Benutzeroberfläche können Sie Traces anzeigen und sehen, wie weit und tief sie gehen, sowie Leistungsengpässe visuell lokalisieren. Wenn Sie Red Hat OpenShift auf der Minischicht-Plattform verwenden, starten Sie die Jaeger-Benutzeroberfläche mit dem folgenden Befehl:

 minishift openshift service jaeger-query --in-browser 


Was kann über die Ablaufverfolgung auf diesem Bildschirm gesagt werden:

  • Es ist in 7 Bereiche unterteilt.
  • Die Gesamtausführungszeit beträgt 6,99 ms.
  • Die Microservice-Empfehlung, die die letzte in der Kette ist, dauert 0,69 ms.

Mit Diagrammen dieses Typs können Sie schnell herausfinden, in welcher Situation die Leistung des gesamten Systems durch einen einzigen schlecht funktionierenden Service beeinträchtigt wird.

Lassen Sie uns nun die Aufgabe verkomplizieren und zwei Instanzen des Empfehlungsmikroservice starten: v2 mit dem Befehl oc scale --replicas = 2 deployment / recommended-v2. Hier sind die Schoten, die wir danach haben werden:


Wenn wir jetzt zurück zu Jaeger wechseln und die Spanne für den Empfehlungsservice bereitstellen, werden wir sehen, an welche Pod-Anfragen weitergeleitet werden. Auf diese Weise können wir die Bremsen leicht auf der spezifischen Pod-Ebene lokalisieren. Sie sollten sich das Feld node_id ansehen:


Wo und wie alles geht


Jetzt gehen wir zur Prometheus-Oberfläche und sehen dort erwartungsgemäß, dass Anfragen zwischen der zweiten und der ersten Version des Empfehlungsdienstes im Verhältnis 2: 1 aufgeteilt werden, ausschließlich durch die Anzahl der Arbeitspods. Darüber hinaus ändert sich dieses Diagramm dynamisch, wenn Pods nach oben und unten skaliert werden. Dies ist insbesondere bei der kanarischen Bereitstellung hilfreich (wir werden dieses Bereitstellungsschema beim nächsten Mal genauer untersuchen).


Es ist nur der Anfang


Tatsächlich haben wir heute, wie sie sagen, ein Lagerhaus mit nützlichen Informationen über Jaeger, Grafana und Prometheus nur geringfügig berührt. Im Allgemeinen war dies unser Ziel - Sie in die richtige Richtung zu führen und die Perspektiven von Istio zu eröffnen.

Und denken Sie daran, all dies ist bereits in Istio integriert. Bei Verwendung bestimmter Programmiersprachen (z. B. Java) und Frameworks (z. B. Spring Boot) kann all dies realisiert werden, ohne den Anwendungscode selbst vollständig zu berühren. Ja, der Code muss leicht geändert werden, wenn Sie andere Sprachen verwenden, hauptsächlich Nodejs oder C #. Da jedoch die Rückverfolgbarkeit (Lesen, „Nachverfolgung“) eine der Voraussetzungen für die Erstellung zuverlässiger Cloud-Systeme ist, müssen Sie den Code in jedem Fall bearbeiten, unabhängig davon, ob Sie Istio verwenden oder nicht. Warum also nicht die Mühe gewinnbringender ausgeben?

Zumindest um die Fragen „wo?“ Und „wie schnell?“ Immer mit 100% iger Sicherheit zu beantworten.

Chaos Engineering bei Istio: Es wurde konzipiert


Die Fähigkeit, Dinge zu zerbrechen, trägt dazu bei, dass sie nicht zerbrechen


Das Testen von Software ist nicht nur eine komplizierte, sondern auch eine wichtige Sache. Gleichzeitig ist das Testen der Korrektheit (zum Beispiel, ob eine Funktion das richtige Ergebnis liefert) eine Sache, und das Testen in einem unzuverlässigen Netzwerk ist eine völlig andere Aufgabe (oft wird angenommen, dass das Netzwerk immer fehlerfrei funktioniert, und dies ist die erste von acht Missverständnissen in Bezug auf die Verteilung rechnen). Eine der Schwierigkeiten bei der Lösung dieses Problems besteht darin, Fehler im System zu simulieren oder absichtlich einzuführen, indem die sogenannte Fehlerinjektion durchgeführt wird. Dies kann durch Ändern des Quellcodes der Anwendung selbst erfolgen. Dann testen Sie aber nicht Ihren Originalcode, sondern dessen Version, die speziell Fehler simuliert. Infolgedessen besteht die Gefahr, dass Sie in die tödliche Umarmung der Fehlerinjektion geraten und mit den Heisenbeuteln kollidieren - Fehler, die verschwinden, wenn Sie versuchen, sie zu erkennen.

Und jetzt werden wir zeigen, wie Istio hilft, mit diesen Schwierigkeiten umzugehen.

Wie es aussieht, wenn alles in Ordnung ist


Stellen Sie sich das folgende Szenario vor: Wir haben zwei Pods für unseren Empfehlungsmikroservice, die wir aus dem Istio-Tutorial entnommen haben. Ein Pod ist als v1 und der andere als v2 markiert. Wie Sie sehen, funktioniert zwar alles einwandfrei:


(Die Nummer auf der rechten Seite ist übrigens nur ein Anrufzähler für jeden Pod.)

Aber das brauchen wir nicht, oder? Versuchen wir, alles aufzubrechen, ohne den Quellcode zu berühren.

Wir sorgen für Unterbrechungen in der Arbeit des Mikrodienstes


Unten finden Sie die Yaml-Datei für die Istio-Routing-Regel, die in zwei Fällen fehlschlägt (Serverfehler 503):


Bitte beachten Sie, dass wir ausdrücklich vorschreiben, dass in der Hälfte der Fälle der Fehler 503 zurückgegeben werden soll.

Und hier ist ein Screenshot des Curl-Befehls, der in der Schleife gestartet wird, nachdem wir diese Regel aktiviert haben, um Fehler zu simulieren. Wie Sie sehen, gibt die Hälfte der Anforderungen den Fehler 503 zurück und unabhängig davon, zu welchem ​​Pod (v1 oder v2) sie gehen:


Um den normalen Betrieb wiederherzustellen, genügt es, diese Regel zu entfernen, in unserem Fall den Tutorial-Befehl istioctl delete routerule recommended-503 -n. Hier ist Tutorial der Name des Red Hat OpenShift-Projekts, in dem unser Istio-Tutorial ausgeführt wird.

Künstliche Verzögerungen machen


Künstliche Fehler 503 helfen beim Testen des Systems auf Fehlertoleranz. Die Fähigkeit, Verzögerungen vorherzusagen und zu verarbeiten, sollte Sie jedoch noch mehr beeindrucken. Und Verzögerungen im wirklichen Leben treten häufiger auf als Ausfälle. Ein langsam laufender Mikroservice ist das Gift, unter dem das gesamte System leidet. Dank Istio können Sie den Code für die Verzögerungsverarbeitung testen, ohne ihn zu ändern. Zunächst werden wir zeigen, wie dies bei künstlich eingeführten Netzwerkverzögerungen geschehen kann.

Bitte beachten Sie, dass Sie nach einem solchen Test möglicherweise Ihren Code verfeinern müssen (oder möchten). Die gute Nachricht ist, dass Sie in diesem Fall proaktiv und nicht reaktiv handeln. So sollte der Entwicklungszyklus aufgebaut sein: Codierungstest-Feedback-Codierungstest ...

So sieht die Regel aus ... Obwohl Sie wissen, was? Istio ist so einfach und diese Yaml-Datei ist so klar, dass alles in diesem Beispiel für sich selbst spricht.


In der Hälfte der Fälle haben wir eine Verzögerung von 7 Sekunden. Und das ist keineswegs dasselbe, als hätten wir den Befehl sleep in den Quellcode eingefügt, da Istio die Anfrage wirklich um 7 Sekunden verzögert. Da Istio die Jaeger-Verfolgung unterstützt, ist diese Verzögerung in Jaegers verzerrter Benutzeroberfläche hervorragend, wie im folgenden Screenshot gezeigt. Beachten Sie die lange Anfrage in der oberen rechten Ecke des Diagramms - ihre Dauer beträgt 7,02 Sekunden:


In diesem Szenario können Sie den Code unter Netzwerklatenzbedingungen testen. Und es ist klar, dass wir durch das Entfernen dieser Regel die künstliche Verzögerung beseitigen werden. Wir wiederholen, aber wir haben das alles wieder getan, ohne den Quellcode zu berühren.

Geh nicht zurück und gib nicht auf


Eine weitere Funktion von Istio, die für das Chaos-Engineering nützlich ist, besteht darin, den Service eine bestimmte Anzahl von Malen aufzurufen. Es geht hier darum, nicht aufzuhören, es zu versuchen, wenn die erste Anfrage mit Fehler 503 endet - und dann haben wir vielleicht zum elften Mal Glück. Vielleicht hat sich der Dienst aus dem einen oder anderen Grund nur für kurze Zeit niedergelassen. Ja, dieser Grund sollte aufgedeckt und beseitigt werden. Aber das ist später, aber jetzt wollen wir versuchen, das System weiter zum Laufen zu bringen.

Wir möchten, dass der Service von Zeit zu Zeit einen 503-Fehler ausgibt, und danach wird Istio versuchen, ihn erneut zu kontaktieren. Und hier brauchen wir eindeutig einen Weg, um Fehler 503 zu erzeugen, ohne den Code selbst zu berühren ...

Hör auf zu warten! Wir haben es einfach gemacht.

Diese Datei bewirkt, dass der Recommendation-v2-Dienst in der Hälfte des Falls einen 503-Fehler generiert:


Offensichtlich schlägt ein Teil der Anforderungen fehl:


Und jetzt verwenden wir die Retry Istio-Funktion:


Diese Routing-Regel führt drei Wiederholungsversuche mit einem Intervall von zwei Sekunden durch und sollte 503-Fehler reduzieren (und im Idealfall vollständig vom Radar entfernen):


Wir fassen zusammen: Wir haben es so gemacht, dass Istio für die Hälfte der Anfragen zuerst einen Fehler von 503 generiert hat. Und zweitens unternimmt derselbe Istio drei Versuche, sich erneut mit dem Dienst zu verbinden, wenn ein 503-Fehler auftritt. Infolgedessen funktioniert alles einwandfrei. Somit haben wir mit der Retry-Funktion unser Versprechen erfüllt, nicht zurückzutreten und nicht aufzugeben.

Und ja, wir haben es noch einmal gemacht, ohne den Code zu berühren. Wir brauchten nur zwei Istio-Routing-Regeln:


Wie man einen Benutzer nicht im Stich lässt oder sieben nicht wartet


Und jetzt drehen wir die Situation um und betrachten das Szenario, in dem Sie sich nicht zurückziehen und nur eine bestimmte Zeit aufgeben müssen. Und dann müssen Sie einfach aufhören, die Anforderung zu verarbeiten, um nicht alle dazu zu zwingen, auf einen Bremsvorgang zu warten. Mit anderen Worten, wir werden die verlorene Position nicht schützen, sondern zur Reservelinie wechseln, um den Benutzer der Site nicht im Stich zu lassen und ihn nicht zu zwingen, in Unwissenheit zu versinken.

In Istio können Sie das Anforderungszeitlimit festlegen. Wenn der Dienst dieses Zeitlimit überschreitet, wird der Fehler 504 (Gateway-Zeitlimit) zurückgegeben. Dies erfolgt wiederum über die Istio-Konfiguration. Wir müssen jedoch den Befehl sleep zum Dienstquellcode hinzufügen (und dann natürlich neu erstellen und erneut bereitstellen), um den langsamen Betrieb des Dienstes zu simulieren. Leider wird es nicht anders funktionieren.

Wir haben also einen Ruhezustand von drei Sekunden in den Empfehlungs-v2-Servicecode eingefügt, das entsprechende Image neu erstellt und einen Container-Remodus durchgeführt. Nun fügen wir eine Zeitüberschreitung hinzu, indem wir die folgende Istio-Routing-Regel anwenden:


Der obige Screenshot zeigt, dass wir den Versuch, den Empfehlungsdienst zu kontaktieren, abbrechen, wenn wir keine Antwort innerhalb einer Sekunde erhalten, d. H. Bevor der Fehler 504 auftritt : v2) erhalten wir Folgendes:


Wir wiederholen noch einmal, aber das Timeout kann eingestellt werden, ohne den Quellcode zu berühren. Der zusätzliche Vorteil ist, dass Sie Ihren Code jetzt so ändern können, dass er auf eine Zeitüberschreitung reagiert. Diese Verbesserungen können Sie mit Istio ganz einfach testen.

Und jetzt alles zusammen


Mit Istio ein bisschen Chaos zu stiften, ist eine großartige Möglichkeit, Ihren Code und die Zuverlässigkeit Ihres gesamten Systems zu testen. Fallback-, Schott- und Leistungsschaltermuster, Mechanismen zur Erzeugung künstlicher Ausfälle und Verzögerungen sowie wiederholte Anrufe und Zeitüberschreitungen sind beim Erstellen fehlertoleranter Cloud-Systeme sehr nützlich. In Kombination mit Kubernetes und Red Hat OpenShift helfen diese Tools Ihnen, sicher in die Zukunft zu blicken.

Source: https://habr.com/ru/post/de485136/


All Articles