Die meisten Architekturdiagramme hören bei den Services auf. Der Telemetrie-Pfad wird später gezeichnet, während eines Incidents, von der Person, die herausfinden will, warum die Hälfte der Traces fehlt oder warum sich die Log-Rechnung verdoppelt hat. Dann hängt die Antwort von Details ab, die niemand aufgeschrieben hat: welche Komponente sampelt, welche den Pod-Namen ergänzt und was passiert, wenn ein Backend langsam ist.
Ein Observability-Architekturdiagramm zeigt, wie Logs, Metriken und Traces jeden Service verlassen, wo sie angereichert, gesampelt und gefiltert werden und wo sie landen. Dieser Beitrag baut eines rund um OpenTelemetry auf Kubernetes, erklärt die Agent- und Gateway-Muster dahinter und listet auf, was du beschriften solltest, damit das Diagramm auch beim nächsten Ausfall hilft.
Drei Signale, drei Fragen
| Signal | Frage, die es beantwortet | Typische Quelle | Wohin es meist geht |
|---|---|---|---|
| Metriken | Stimmt etwas nicht, und wie sehr? | Zähler und Histogramme aus dem SDK, Kubelet- und Node-Statistiken | Eine Zeitreihendatenbank, etwa ein Prometheus-kompatibler Speicher |
| Traces | Wo im Request-Pfad liegt das Problem? | Spans aus dem SDK oder aus Auto-Instrumentierung | Ein Trace-Speicher, etwa Jaeger oder Tempo |
| Logs | Was genau ist passiert? | stdout und stderr, Logdateien, SDK-Log-Einträge | Ein Log-Speicher, etwa Loki oder OpenSearch |
Die drei sind nur zusammen nützlich, wenn sie Kontext teilen. Eine Trace-ID in der Logzeile und derselbe service.name und Pod-Name auf jedem Signal lassen dich vom Alert zum langsamen Span und weiter zur Logzeile springen, die ihn erklärt. Die Architektur muss diesen Kontext intakt halten.
Die Bausteine
OTLP ist das OpenTelemetry-Protokoll für alle drei Signale. Die Spezifikation legt die Standardports fest: 4317 für OTLP über gRPC und 4318 für OTLP über HTTP.
SDKs und Auto-Instrumentierung laufen in jedem Service und exportieren OTLP. Richte sie auf einen lokalen Collector statt auf einen Anbieter, dann brauchen Routing-Änderungen kein neues Deployment.
Der Collector ist ein einzelnes Binary mit Pipelines pro Signal: Receiver nehmen Daten an, Processor verändern sie, Exporter senden sie weiter. Die Deployment-Dokumentation beschreibt zwei Hauptarten, ihn zu betreiben:
- Agent. Ein Collector läuft neben der Anwendung, als Sidecar oder als DaemonSet mit einem Pod pro Node. Auf Kubernetes ist der Agent auch der Ort, an dem die Kubernetes-Komponenten arbeiten: Der Kubernetes Attributes Processor ergänzt Pod-, Namespace- und Deployment-Namen, der Filelog Receiver liest stdout und stderr der Container mit, und der Kubeletstats Receiver holt Node- und Pod-Metriken.
- Gateway. Ein oder mehrere Collector laufen als eigenständiger Service, typischerweise ein Endpunkt pro Cluster, Rechenzentrum oder Region. Das Gateway ist der Ort für Entscheidungen, die du nur einmal treffen willst: Sampling, das Filtern sensibler Attribute, das Verwalten von Backend-Zugangsdaten und das Senden an mehrere Backends.
Head oder Tail Sampling
Traces sind das teure Signal, deshalb sampeln die meisten Teams sie. Head Sampling entscheidet beim Start des Traces, etwa 10 Prozent zu behalten. Es ist billig, kann einen Trace aber nicht deshalb behalten, weil er später fehlschlägt. Tail Sampling entscheidet, nachdem es alle oder die meisten Spans eines Traces gesehen hat, und kann so jeden Fehler und jede langsame Anfrage behalten.
Tail Sampling hat strukturelle Kosten: Alle Spans eines Traces müssen beim selben Collector ankommen. Hinter einem Round-Robin-Load-Balancer tun sie das nicht. Das Gateway-Muster löst das mit zwei Stufen: Die erste betreibt den Load-Balancing-Exporter mit der Trace-ID als Routing-Schlüssel, die zweite den Tail Sampling Processor. Das sind zwei Kästen im Diagramm, und es lohnt sich, beide zu zeigen.
Das Beispiel: ein Shop auf Kubernetes
Der Shop betreibt drei Deployments in einem Namespace shop: web, checkout-api und payments-worker, jeweils mit dem OpenTelemetry-SDK. Der Namespace observability enthält die Pipeline: ein DaemonSet otel-agent, ein Deployment otel-lb, das Spans nach Trace-ID routet, und ein Deployment otel-sampler, das die Tail-Sampling-Policy anwendet. Metriken, Traces und Logs gehen jeweils an einen eigenen Speicher, und Alert-Regeln laufen auf den Metriken.
Diagramminhalt
- shop
- web
- checkout-api
- payments-worker
- observability
- otel-agent
- otel-lb
- otel-sampler
- Trace store
- Metrics store
- Log store
- Alerting
- OTLP/gRPC 4317
- stdout logs (filelog)
- traces
- by trace ID
- kept traces
- metrics
- logs
- alert rules
So liest du es:
- Links, die Services. Jedes Deployment exportiert Traces, Metriken und Logs per OTLP/gRPC über Port 4317 an den Agent auf seinem Node. Die gestrichelte Kante ist das Container-stdout, das der Agent vom Node liest, statt es übers Netz zu empfangen.
- Mitte, der Agent. Der Agent ergänzt alles um Kubernetes-Metadaten und sendet dann Metriken und Logs direkt an ihre Speicher, Traces an das Gateway.
- Mitte, das Gateway.
otel-lbroutet jeden Span nach Trace-ID, sodass alle Spans eines Traces beim selben Pod vonotel-samplerankommen, der Fehler und langsame Traces behält und den Rest sampelt. - Rechts, Speicher und Alerts. Jedes Signal hat sein eigenes Backend. Alert-Regeln lesen die Metriken und alarmieren, wer gerade Bereitschaft hat.
- Der Markdown-Block hält die Sampling-Policy fest und die eine Regel, die jede Pipeline befolgt: der Memory Limiter zuerst.
Was du beschriften solltest
- Protokoll und Port auf jedem Hop. OTLP/gRPC 4317 oder OTLP/HTTP 4318 und das Exportformat zu jedem Backend.
- Welche Signale auf jeder Kante laufen. Eine Pipeline transportiert selten alle drei auf dieselbe Weise.
- Wo gesampelt wird und mit welcher Policy. Schreib die Zahlen hin; ein bloßes „gesampelt“ lädt zu falschen Annahmen ein.
- Wo Daten angereichert oder geschwärzt werden. Kubernetes-Metadaten im Agent, das Entfernen von Tokens und personenbezogenen Daten im Gateway.
- Aufbewahrung pro Backend. Sie erklärt die Kosten und was eine Untersuchung noch finden kann.
- Fehlerverhalten. Queues, Wiederholungen und was verworfen wird, wenn ein Backend ausfällt.
Häufige Fehler
- SDKs, die direkt an einen Anbieter exportieren. Jede Routing- oder Zugangsdaten-Änderung wird zum neuen Deployment, und es gibt keinen Ort, um Daten zu filtern, bevor sie das Haus verlassen.
- Tail Sampling hinter einem einfachen Load Balancer. Die Spans eines Traces landen bei verschiedenen Collectoren, und die Sampling-Entscheidungen fallen auf Bruchstücken.
- Kein Memory Limiter. Die Konfigurationsdokumentation enthält einen Processor
memory_limiter; setz ihn in jeder Pipeline an die erste Stelle, damit der Collector bei einer Spitze Daten ablehnt, statt keinen Speicher mehr zu haben. - Metrik-Labels mit hoher Kardinalität. Eine Nutzer- oder Request-ID als Metrik-Label vervielfacht die Zeitreihen. Leg sie stattdessen auf Spans und Logs.
- Eine Pipeline ohne Überwachung. Der Collector stellt eigene Metriken bereit, standardmäßig auf Port 8888, wie in der Dokumentation zur internen Telemetrie beschrieben. Alarmiere bei fehlgeschlagenen Exporten, sonst erfährst du von verlorenen Daten genau in dem Incident, der sie gebraucht hätte.
Für den Cluster selbst deckt das Kubernetes-Architekturdiagramm Control Plane, Nodes und Workloads ab, und das Microservices-Architekturdiagramm die Services, die diese Pipeline beobachtet.
In Archboard nachbauen
- Melde dich mit Google oder GitHub an und leg ein Diagramm an.
- Füge aus dem Kubernetes-Pack zwei Namespace-Rahmen hinzu,
shopundobservability. Setz inshopfür jeden Service ein Deployment. - Füge in
observabilityein DaemonSet für den Agent und zwei Deployment-Nodes für die Load-Balancing- und die Sampling-Stufe hinzu. - Füge aus dem DevOps-Pack die Nodes Metriken, Ablaufverfolgung und Protokolle für die Backends hinzu, dazu einen Alarm für das Alerting.
- Verbinde sie und beschrifte jede Kante mit den Signalen und dem Protokoll, etwa „OTLP/gRPC 4317“. Zeichne die Kante für die Container-Logs gestrichelt.
- Füge aus dem Basis-Pack einen Markdown-Block mit der Sampling-Policy hinzu.
Das Beispiel nutzt 13 Diagramm-Nodes und bleibt damit im Free-Plan. Laufen deine Services schon auf Kubernetes, macht das Tool Kubernetes YAML zu Diagramm aus den Manifesten einen ersten Entwurf der linken Hälfte.
FAQ
Brauche ich einen Gateway-Collector, oder reichen Agents? Für kleine Setups reichen Agents. Füge ein Gateway hinzu, wenn du Tail Sampling, einen zentralen Ort für Zugangsdaten und Filterung oder mehrere Backends brauchst; der Agent leitet dann an das Gateway weiter.
Sollten auch Logs durch den Collector laufen? Das können sie. Der Filelog Receiver im Agent liest Container-Logs, ergänzt dieselben Kubernetes-Metadaten wie bei Traces und Metriken und lässt dich vor dem Speichern filtern. Viele Teams ziehen Logs als Letztes auf den Collector um, nach Traces und Metriken.
Reicht Head Sampling jemals aus? Ja, wenn der Traffic gering ist oder jeder Trace gleich aussieht. Wenn du jeden Fehler und jede langsame Anfrage brauchst, nutze Tail Sampling und zeichne die zwei Gateway-Stufen, die es erfordert.
Wohin gehören Dashboards und Alerts im Diagramm? Neben den Speicher, den sie abfragen. Alert-Regeln auf Metriken sind Teil der Architektur: Sie entscheiden, wer geweckt wird.
Wie halte ich dieses Diagramm aktuell? Ändere es im selben Pull Request wie die Collector-Konfiguration und verlinke es im Runbook. Siehe Architekturdiagramme, die nicht veralten.