Mirko Serbak
Senior Consultant
Ein Ökosystem mit vielen Microservices zu durchschauen, ist für DevOps Teams im Betrieb eine echte Herausforderung. Tracing kann hier Licht ins Dunkel bringen.
Autoren: Mirko Serbak & Simon Flühmann
Stell dir vor, du schläfst tief und fest und träumst von einer perfekten DevOps Toolchain. Mitten in der Nacht wirst du vom lauten Läuten des Pikett-Handys aus dem Schlaf gerissen - das End-to-End-Monitoring meldet eine kritische Anzahl an Fehlern auf der Produktion! Schlaftrunken und noch im Pyjama startest du deinen Rechner und machst dich sogleich auf die Suche nach der Lösung. Die Fehlermeldungen, die du finden kannst, sind sehr kryptisch und du kannst dir daraus keinen Reim machen. Zudem bist du dir nicht mal sicher, wo du deine Suche starten solltest…
Wie Tracing in einer solchen und weiteren Situationen helfen kann, was OpenTelemetry ist und worauf man beim Instrumentieren achten sollte, sowie wie man beim Implementieren vorgehen kann, darauf gehen wir in diesem Blog näher ein.
Mit dem Aufkommen ständig komplexer werdender Software-Systeme sind solche Situationen leider nicht mehr nur der Ausnahmefall, sondern können jederzeit passieren. Wir, als DevOps Team, verlieren zunehmend die Fähigkeit zu erkennen, wie einzelne Komponenten funktionieren und voneinander abhängen. Es ist nicht mehr auf den ersten Blick erkennbar, wie ein Software-System als Ganzes funktioniert.
Das Problem verschärft sich besonders beim Einsatz moderner Applikationen. Diese setzen auf hoch verteilte Architekturmuster mit Microservices, Skalierung und Asynchronität, nutzen hybride Cloud-Services bis hin zur kompletten Externalisierung einzelner Funktionsaufrufe oder Berechnungen (Functions as a Service (FaaS) und Serverless computing). Hinzu kommen schnelle und unabhängige Release-Zyklen mit Continuous Deployment, welche dafür sorgen, dass sich Systeme permanent verändern.
Ein Trace fasst eine oder mehrere kontextuell zusammengehörige und aufeinanderfolgende Arbeitseinheiten, sogenannte Spans, zu einem Paket zusammen. Ein Span repräsentiert eine zeitlich festgelegte Operation innerhalb einer Transaktion und teilt seinen Kontext mit anderen Spans innerhalb des Trace. Gantt-Diagramme oder gerichtete Graphen können diese Zusammengehörigkeit gut visualisieren:
Für den effizienten Betrieb von Software ist ein gut kalibriertes Tracing-System für ein DevOps Team extrem hilfreich. Tracing beantwortet Fragen zu einem Request, die kein anderes System beantworten kann:
Was macht unsere Applikation genau?
Tracing zeigt auf, welchen Weg ein Request durch welche Services genommen hat, wie sich die Services verhalten haben und wie unsere Applikation integriert ist.
Wo sind unsere Bottlenecks?
Falls ein Request langsam ist, hilft Tracing Latenzen zu identifizieren und effektiv anzugehen.
Was ist der Kontext eines Fehlers in unserer Applikation?
Falls ein Request scheitert, erleichtert Tracing, dank der Transaktionsicht die Lokalisation des Fehlers und visualisiert, welche Services daran beteiligt sind. Das ist sowohl hilfreich für die Root-Cause Analyse, als auch für den Einbau kurzfristiger Bypass-Rettungsaktionen.
Am Beispiel von Uber Technologies erkennt man sofort, weshalb Tracing für ein DevOps Team absolut elementar ist: Um nicht im Chaos des Ökosystems von über 3’000 hochskalierten Microservices in unterschiedlichsten Programmiersprachen zu versinken, sah sich das Observability Team von Uber gezwungen ein eigenes Tool für Transaktions-Tracing zu entwickeln. So entstand das Open-Source Tracing Backend “Jaeger” (siehe Bild) und ein Grundstein für das Open-Source-Projekt “OpenTelemetry” war gelegt.
Yuri Shkuro, SWE Uber Technologies, Autor "Mastering Distributed Tracing", Entwickler von Jaeger & Co-Gründer des OpenTelemetry CNCF Projekts
OpenTelemetry (OTel) ist ein Projekt der Cloud Native Computing Foundation (CNCF). Es vereint seit 2019 OpenTracing und OpenCensus, welche ursprünglich von Uber Technologies und Google Inc. entwickelt wurden und ist inzwischen ein etablierter Industriestandard. OpenTelemetry bietet ein Set an generischen, herstellerneutralen APIs, sprachspezifischen SDKs für gängige Programmiersprachen und Daten-Konventionen zur Instrumentierung von Code. Weiter bietet OpenTelemetry bewährte Werkzeuge wie den OpenTelemetry Collector für das Sammeln, Prozessieren und Weiterleiten von Daten sowie Mechanismen für die Kontext-Propagierung über Service-Grenzen hinweg.
Damit ein System Tracing-Daten emittieren kann, muss es instrumentiert werden. Als Open-Source Standard bietet OpenTelemetry Entwicklern ein gutes Werkzeug, bestehend aus zwei Herangehensweisen: Manuelle Instrumentierung oder automatische Instrumentierung. Je nach Use Case bietet sich automatische Instrumentierung, manuelle Instrumentierung oder eine Kombination der beiden Ansätze an.
Die automatische Instrumentierung erfordert, anders als die manuelle Instrumentierung, keine Code-Anpassungen. Stattdessen wird der Code meist zur Laufzeit oder Kompilierzeit automatisch um die für das Tracing benötigten Bibliotheken und Frameworks von einem Agenten ergänzt. Momentan bietet OpenTelemetry solche Agents nur für ein Set von Sprachen an. Anbieter von proprietären Tracing- bzw. Observability-Tools bieten eine umfassendere Abdeckung von Programmiersprachen.
In Java kann der OpenTelemetry Agent beim Ausführen einer App beispielsweise folgendermassen mitgegeben werden:
Der Agent kann zudem mit Parametern so konfiguriert werden, dass die Tracing-Daten an den richtigen Endpoint emittiert werden. Diese Herangehensweise ermöglicht es also, mit minimalem Entwicklungsaufwand Tracing-Daten zu erstellen und zu versenden. Da die Instrumentierung aber automatisiert erfolgt, können nur Standardfälle betrachtet werden und applikationsspezifische Logik kann nicht berücksichtigt werden.
Enthält ein System oder eine Applikation komplexe und Business-kritische Implementationen, kann es sich lohnen, diese manuell zu instrumentieren. Das Erstellen und Verwalten der Spans und des Context (OTel API) sowie die Pipeline Konfiguration (OTel SDK) müssen dabei explizit im Code angelegt werden. Im Folgenden wird wiederum ein Beispiel anhand einer Java Applikation gemacht.
Das Angebot an auf dem Markt erhältlichen Observability Backends für die Interpretation von Tracing Daten ist sehr divers und auch deren Funktionsumfang unterscheidet sich stark. Anbieter wie Dynatrace oder Datadog bieten Observability-Suiten an - Komplettlösungen, welche alle Arten von Telemetriedaten erfassen und verarbeiten können. Beide Hersteller bieten ausgereifte Tools für den Betrieb und die Überwachung von Software.
Dem gegenüber stehen Open-Source Lösungen wie Jaeger oder Zipkin. Diese Tools sind primär für die Verarbeitung von Traces ausgelegt und können andere Telemetriesignale nur limitiert verarbeiten. Sie sind somit als ergänzendes Teilstück eines ganzheitlichen Observability Systems für Logs, Metrics und Traces zu betrachten.
Je komplexer und verteilter ein System, desto mehr lohnt sich der Einsatz von Tracing. Im Allgemeinen empfehlen wir folgende Schritte, um Tracing in einem System umzusetzen:
Um wieder auf unseren Pikettdienst-Vorfall zu kommen: So konntest du schnell mit Hilfe des Tracing Systems auf Spurensuche und den Authentication-Service als Verursacher identifizieren. Es hatte sich beim Abarbeiten von Login Events auf dem Kafka Topic ein riesiger Consumer-Lag aufgebaut. Mit diesem Wissen konnte das Problem durch das Zuschalten weiterer Authentication-Service Instanzen innerhalb kürzester Zeit behoben werden.
Unser Fazit ist, dass ein gutes Tracing-System dir das Klingeln auf dem Pikett-Handy nicht ersparen wird, jedoch die benötigte Zeit, um das Problem zu identifizieren und zu beheben wesentlich verkürzen, sodass du bald wieder seelenruhig weiter träumen kannst ;-).
Willst du mehr zum Thema Tracing erfahren? Dann melde Dich bei uns.