Istio und Kubernetes in Produktion. Teil 2. Rückverfolgung

Im letzten Artikel haben wir die grundlegenden Komponenten von Service Mesh Istio untersucht , uns mit dem System vertraut gemacht und die grundlegenden Fragen beantwortet, die normalerweise zu Beginn der Arbeit mit Istio auftreten. In diesem Teil werden wir uns ansehen, wie die Sammlung von Ablaufverfolgungsinformationen über das Netzwerk organisiert wird.



Das erste, was vielen Entwicklern und Systemadministratoren begegnet, wenn sie die Worte Service Mesh hören, ist die Verfolgung. In der Tat fügen wir jedem Netzwerkknoten einen speziellen Proxyserver hinzu, über den der gesamte TCP-Verkehr geleitet wird. Es scheint, dass Sie jetzt problemlos Informationen zu allen Netzwerkinteraktionen im Netzwerk senden können. Leider gibt es in der Realität viele Nuancen, die berücksichtigt werden müssen. Schauen wir sie uns an.

Missverständnis Nummer eins: Wir können kostenlos Daten über Reisen über das Netzwerk erhalten


Tatsächlich können wir relativ kostenlos nur die Knoten unseres Systems durch Pfeile und die Datenrate verbinden, die zwischen den Diensten übertragen wird (tatsächlich nur die Anzahl der Bytes pro Zeiteinheit). In den meisten Fällen kommunizieren unsere Dienste jedoch über ein Protokoll auf Anwendungsebene, z. B. HTTP, gRPC, Redis usw. Und natürlich möchten wir die Ablaufverfolgungsinformationen genau nach diesen Protokollen anzeigen. Wir möchten die Anforderungsrate und nicht die Datenrate anzeigen. Wir möchten die Latenz von Anforderungen durch unser Protokoll verstehen. Schließlich möchten wir den vollständigen Pfad sehen, den die Anforderung vom Eintritt in unser System bis zum Empfang einer Antwort vom Benutzer führt. Dieses Problem ist nicht so einfach zu lösen.

Schauen wir uns zunächst an, wie das Senden von Ablaufverfolgungsbereichen aus architektonischer Sicht in Istio aussieht. Wie wir uns aus dem ersten Teil erinnern, hat Istio eine separate Komponente zum Sammeln von Telemetrie, die als Mixer bezeichnet wird. In der aktuellen Version 1.0. * Das Senden erfolgt jedoch direkt von Proxyservern, nämlich mit Envoy-Proxy. Der Envoy-Proxy unterstützt das sofortige Senden von Ablaufverfolgungsbereichen über das Zipkin-Protokoll. Andere Protokolle können verbunden werden, jedoch nur über das Plugin. Mit Istio erhalten wir sofort den zusammengestellten und konfigurierten Envoy-Proxy, der nur das Zipkin-Protokoll unterstützt. Wenn wir beispielsweise das Jaeger-Protokoll verwenden und Ablaufverfolgungsbereiche über UDP senden möchten, müssen wir unser Istio-Proxy-Image zusammenstellen. Es gibt Unterstützung für benutzerdefinierte Plugins für istio-proxy, diese befinden sich jedoch noch in der Alpha-Version. Wenn wir auf viele benutzerdefinierte Einstellungen verzichten möchten, wird daher die Anzahl der Technologien zum Speichern und Empfangen von Ablaufverfolgungsbereichen reduziert. Von den Hauptsystemen können Sie jetzt Zipkin selbst oder Jaeger verwenden, aber alles mit einem Zipkin-kompatiblen Protokoll (das viel weniger effizient ist) dorthin senden. Das Zipkin-Protokoll selbst umfasst das Senden aller Ablaufverfolgungsinformationen an Sammler mithilfe des HTTP-Protokolls, was recht teuer ist.

Wie gesagt, wir möchten Protokolle auf Anwendungsebene verfolgen. Dies bedeutet, dass die Proxyserver, die sich neben jedem Dienst befinden, verstehen müssen, welche Art von Interaktion gerade stattfindet. Standardmäßig legt Istio den Typ für alle einfachen TCP-Ports fest. Dies bedeutet, dass keine Traces gesendet werden. Damit Traces gesendet werden können, müssen Sie diese Option zuerst in der Hauptnetzkonfiguration aktivieren und vor allem alle Ports der kubernetes-Dienstentitäten gemäß dem im Dienst verwendeten Protokoll umbenennen. Das ist zum Beispiel so:

apiVersion: v1 kind: Service metadata: name: nginx spec: ports: - port: 80 targetPort: 80 name: http selector: app: nginx 

Sie können auch zusammengesetzte Namen wie http-magic verwenden (Istio sieht http und erkennt diesen Port als http-Endpunkt). Das Format ist: Proto-Extra.

Um nicht eine große Anzahl von Konfigurationen zum Definieren eines Protokolls zu patchen, können Sie eine schmutzige Problemumgehung verwenden: Patchen einer Pilotkomponente zu einem Zeitpunkt, an dem nur die Protokolldefinitionslogik ausgeführt wird . Am Ende müssen Sie diese Logik natürlich auf Standard ändern und zur Namenskonvention für alle Ports wechseln.

Um zu verstehen, ob das Protokoll wirklich korrekt definiert ist, müssen Sie in einen der Sidecar-Container mit Envoy-Proxy gehen und eine Anfrage an den Admin-Port der Envoy-Schnittstelle mit location / config_dump senden. In der resultierenden Konfiguration müssen Sie sich die gewünschte Servicefeldoperation ansehen. Es wird in Istio als Kennung verwendet, wohin die Anfrage geht. Um den Wert dieses Parameters in Istio anzupassen (wir werden ihn dann in unserem Ablaufverfolgungssystem sehen), muss das serviceCluster-Flag beim Starten des Beiwagencontainers angegeben werden. Zum Beispiel kann es so aus Variablen berechnet werden, die von den abwärts gerichteten API-Kubernetzen erhalten wurden:

--serviceCluster ${POD_NAMESPACE}.$(echo ${POD_NAME} | sed -e 's/-[a-z0-9]*-[a-z0-9]*$//g')

Ein gutes Beispiel für das Verständnis der Funktionsweise der Ablaufverfolgung im Gesandten finden Sie hier .

Der Endpunkt selbst zum Senden von Ablaufverfolgungsbereichen muss auch in den --zipkinAddress tracing-collector.tracing:9411 Proxys angegeben werden, z. B.: --zipkinAddress tracing-collector.tracing:9411

Missverständnis Nummer zwei: Wir können kostengünstig die vollständigen Spuren der Weitergabe von Anfragen für das System sofort abrufen


Dies ist leider nicht so. Die Komplexität der Implementierung hängt davon ab, wie Sie die Interaktion von Diensten bereits implementiert haben. Warum so?

Tatsache ist, dass es nicht ausreicht, nur den gesamten Datenverkehr abzufangen, damit istio-proxy die Korrespondenz eingehender Anforderungen an einen Dienst mit denen desselben Dienstes versteht. Sie benötigen eine Art Link-ID. Envoy-Proxy-HTTP verwendet spezielle Header, nach denen Envoy versteht, welche bestimmte Dienstanforderung bestimmte Anforderungen an andere Dienste generiert. Liste solcher Header:

  • x-request-id,
  • x-b3-traceid,
  • x-b3-spanid,
  • x-b3-parentpanid,
  • x-b3-abgetastet,
  • x-b3-Flags,
  • x-ot-span-Kontext.

Wenn Sie einen einzelnen Punkt haben, z. B. einen Basisclient, an dem Sie eine solche Logik hinzufügen können, ist alles in Ordnung. Sie müssen nur warten, bis alle Clients diese Bibliothek aktualisiert haben. Wenn Sie jedoch ein sehr heterogenes System haben und die Kampagne nicht von Diensten zu Diensten über das Netzwerk vereinheitlicht wird, ist dies höchstwahrscheinlich ein großes Problem. Ohne die Hinzufügung einer solchen Logik sind alle Verfolgungsinformationen nur "Geschwister". Das heißt, wir erhalten alle dienstübergreifenden Interaktionen, aber sie werden nicht in eine einzige Durchgangskette durch das Netzwerk geklebt.

Fazit


Istio bietet ein praktisches Tool zum Sammeln von Ablaufverfolgungsinformationen über das Netzwerk. Sie müssen jedoch verstehen, dass Sie für die Implementierung Ihr System anpassen und die Funktionen der Implementierung von Istio berücksichtigen müssen. Infolgedessen müssen Sie zwei Hauptpunkte lösen: Bestimmen des Protokolls der Anwendungsschicht (das vom Envoy-Proxy unterstützt werden sollte) und Einrichten der Weiterleitung von Informationen über die Konnektivität von Anforderungen an den Dienst aus Anforderungen des Dienstes (unter Verwendung von Headern im Fall des HTTP-Protokolls). Wenn diese Probleme behoben sind, erhalten wir ein leistungsstarkes Tool, mit dem Sie Informationen aus dem Netzwerk transparent erfassen können, selbst in sehr heterogenen Systemen, die in vielen verschiedenen Sprachen und Frameworks geschrieben sind.

Im nächsten Artikel über Service Mesh werden wir eines der größten Probleme von Istio betrachten - den hohen Speicherverbrauch jedes Sidecar-Proxy-Containers - und erläutern, wie damit umgegangen werden soll.

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


All Articles