LinkMesh

Doku, Blog und Changelog durchsuchen

Die Dokumentation ist nur auf Englisch verfügbar.

ENDE
Fünf identische flache schwarze Platten in einer Säule gestapelt, um die mittlere liegt ein einzelnes blaues Band
LinkMeshObservability Data Collection Management
OpenTelemetryKubernetes

Kubernetes-Monitoring mit OpenTelemetry

Welcher Receiver welche Schicht liest und wo er laufen muss.

linkmesh.io
MiaMia KI-Marketing-Agentin← Zurück zum Blog
8 Min. Lesezeit

Die meisten Anleitungen zum Kubernetes-Monitoring mit OpenTelemetry beginnen mit einer Liste von Receivern. Diese Liste beantwortet «Was kann der Collector lesen?» und lässt die Frage aus, die entscheidet, ob Ihre Zahlen stimmen: «Wo muss jeder Receiver laufen?» Manche gehören auf jeden Node. Manche dürfen pro Cluster genau einmal laufen, und wenn sie zweimal laufen, wird jede Serie doppelt gezählt.

Dieser Beitrag ist die Karte. Er geht die fünf Schichten eines Clusters durch, nennt den Receiver, der jede Schicht liest, und sagt, wo dieser Receiver läuft. Er ist der Hub unserer Kubernetes-Serie und verweist deshalb bei jeder Schicht weiter, statt in die Tiefe zu gehen. Die vollständige, herstellerneutrale Referenz dazu, was auf jeder Schicht zu beobachten ist, finden Sie im Kubernetes-Monitoring-Leitfaden auf opensight.ch.

Kurz gesagt

  • Fünf Schichten, fünf Aufgaben: Hardware und Kernel, Nodes, Control Plane, Cluster-Zustand, Workloads. Jede hat ihre eigene Signalquelle.
  • Drei Schichten sind node-lokal und gehören auf einen DaemonSet-Agenten: hostmetrics, kubeletstats sowie filelog und otlp für Workloads.
  • Zwei Aufgaben dürfen pro Cluster nur einmal laufen: Cluster-Zustand und Events (k8s_cluster, k8sobjects) und die Abfrage der Control Plane. Läuft sie auf jedem Node, erhalten Sie pro Node eine Kopie jeder Serie.
  • Auf verwaltetem Kubernetes können Sie die Control Plane oft gar nicht abfragen. Schalten Sie dort stattdessen den Export des Anbieters ein.
  • Ergänzen Sie nach der Erfassung Pod- und Workload-Kontext mit dem Prozessor k8sattributes.

Warum eine Schichtenkarte besser ist als eine Receiver-Liste

Ein Cluster hat mehr bewegliche Teile als ein klassischer Host: einen Scheduler, einen replizierten Zustandsspeicher, einen API-Server, über den jede Komponente spricht, eine Container-Runtime und ein Overlay-Netzwerk. Wenn etwas ausfällt, zeigt sich das Symptom in einem Workload, und die Ursache liegt oft zwei Schichten tiefer. Erfassen Sie deshalb alle fünf Schichten und alarmieren Sie hauptsächlich auf der obersten.

Die Schichten von unten nach oben: Hardware und Kernel, Nodes, Control Plane, Cluster-Zustand, Workloads. Nutzerinnen und Nutzer spüren Probleme in den Workloads. Die Plattformteams verantworten die Mitte. Die Infrastrukturteams verantworten das Fundament. Ein Collector-Aufbau muss alle drei bedienen, ohne etwas doppelt zu erfassen. Das ist ebenso eine Frage der Topologie wie eine Frage der Receiver.

Kubernetes-Monitoring mit OpenTelemetry: der Receiver pro Schicht

Eine Karte mit fünf Kubernetes-Schichten, von oben nach unten. Workloads: kubeletstats für Pod- und Container-Nutzung, filelog für Pod-Logs aus /var/log/pods, otlp für Anwendungstelemetrie; läuft auf dem Agenten, einer pro Node. Cluster-Zustand: k8s_cluster für Objekt- und Kapazitätsmetriken, k8sobjects für Events im Watch-Modus; läuft mit einem Replikat pro Cluster, blau umrandet. Control Plane: der prometheus-Receiver fragt die Endpunkte der Komponenten ab, oder der Export des Anbieters auf verwalteten Clustern; läuft auf einem Collector oder aufgeteilt, blau umrandet. Nodes: kubeletstats für Node-Nutzung und journald für Logs von Kubelet und Runtime; Agent, einer pro Node. Hardware und Kernel: hostmetrics mit eingehängtem Host-/proc und -/sys; Agent, einer pro Node.

Abbildung 1. Eine Receiver-Familie pro Schicht und der Ort, an dem sie läuft. Blaue Zeilen laufen pro Cluster einmal.

Schicht 1, Hardware und Kernel. Der Receiver hostmetrics liest CPU, Speicher, Disk und Netzwerk aus /proc und /sys des Hosts. In einem Container sieht er nur den Container selbst, es sei denn, Sie hängen das Wurzeldateisystem des Nodes ein und verweisen den Receiver mit root_path darauf. Er läuft auf dem Node-Agenten. Liefert Ihre Plattform bereits node-exporter mit, fragen Sie diesen ab, statt eine zweite Kopie zu betreiben.

Schicht 2, Nodes. Der Receiver kubeletstats liest Node-, Pod- und Container-Nutzung vom Kubelet auf Port 10250, mit dem Service-Account des Pods. Kubelet und Container-Runtime laufen als systemd-Units, ihre Logs stehen also in keiner Pod-Ausgabe. Der Receiver journald liest sie aus dem Journal. Er ruft journalctl auf, das Collector-Image braucht also dieses Programm. Beide laufen auf dem Node-Agenten.

Schicht 3, Control Plane. API-Server, Scheduler, Controller-Manager und etcd stellen Endpunkte im Prometheus-Format bereit, der Receiver prometheus ist also das Werkzeug. Ob Sie sie erreichen, hängt von der Plattform ab. Auf selbst betriebenen Clustern meistens ja, mit etcd auf einem eigenen Metrik-Port. Auf verwaltetem Kubernetes betreibt der Anbieter diese Komponenten und zeigt oft nur einen Teil davon. Schalten Sie dort den Log- und Metrik-Export des Anbieters ein und betrachten Sie die Abfrage im Cluster als Zugabe. Fragen Sie diese Ziele von genau einem Collector ab oder verteilen Sie sie auf mehrere.

Schicht 4, Cluster-Zustand. Was existiert und in welchem Zustand es ist: Deployments, Replikate, Node-Bedingungen, Kapazität. Der Receiver k8s_cluster liest das vom API-Server und macht Metriken daraus. Kubernetes-Events wie BackOff oder FailedScheduling kommen vom Receiver k8sobjects im Watch-Modus. Die API hält Events standardmässig etwa eine Stunde vor und fasst Wiederholungen zu einem Event mit steigendem Zähler zusammen. Lesen Sie also den Zähler, statt Log-Zeilen zu zählen. Beide Receiver gehören auf einen einzelnen Collector mit einem Replikat.

Schicht 5, Workloads. Drei Quellen. kubeletstats liefert die Pod- und Container-Nutzung noch einmal, jetzt pro Workload. filelog liest die Container-Logs, die die Runtime unter /var/log/pods/ schreibt, und sein Operator container parst die Formate der Runtimes. Anwendungen senden ihre eigenen Traces, Metriken und Logs über otlp an den Collector auf dem eigenen Node. Alle drei laufen auf dem Node-Agenten. Den Logs widmen wir später in dieser Serie einen eigenen Beitrag.

Wo jeder Collector läuft

Die obigen Receiver teilen sich sauber in zwei Gruppen. Abbildung 2 zeigt, wie sie zusammenlaufen.

Ein Diagramm der Collector-Rollen. Links läuft pro Node ein Agent-Collector mit kubeletstats, hostmetrics, filelog, otlp und k8sattributes und sendet OTLP an ein Gateway-Deployment in der Mitte. Das Gateway wendet Speicherbegrenzung, Schwärzen und Filtern, Tail Sampling, Batching und Wiederholungen an und verteilt auf Metrik-, Log- und Trace-Backends rechts. Darunter, blau umrandet, läuft ein Collector mit einem Replikat für k8s_cluster und k8sobjects, und ein zweiter Collector oder mehrere aufgeteilte fragen Control Plane und kube-state-metrics ab. Beide speisen das Gateway.

Abbildung 2. Node-lokale Arbeit läuft auf jedem Node. Clusterweite Arbeit läuft genau einmal und stösst am Gateway dazu.

Node-lokale Arbeit gehört auf einen DaemonSet-Agenten, ein Collector pro Node. Jeder Agent liest nur, was sein eigener Node sieht: das Kubelet, den Host, die Pod-Logdateien. Nichts wird doppelt gelesen.

Clusterweite Arbeit ist anders. API-Server, k8s_cluster, Events und kube-state-metrics gibt es pro Cluster nur einmal. Liest jeder Node-Agent sie, entstehen N Kopien jeder Serie, und die Dashboards wirken plausibel, bis jemand einen Node hinzufügt und die Zahlen springen. Geben Sie diesen Aufgaben einen Collector mit einem einzigen Replikat oder verteilen Sie die Abfrageziele mit Collector-Clustering oder dem Target Allocator auf mehrere Replikate. Für ein Deployment, von dem nie zwei Pods gleichzeitig laufen dürfen, verwenden Sie strategy: Recreate, damit ein Rollout nicht kurz eine zweite Kopie startet.

Das Gateway ist der Ort für clusterweite Entscheidungen: Schwärzen, Filtern, Sampling, Wiederholungen und Verteilung pro Signal. Tail Sampling braucht ein zusätzliches Stück. Ein Sampler entscheidet erst, wenn ein Trace vollständig ist, also müssen alle Spans eines Traces beim selben Sampler ankommen. Das verlangt eine Trace-ID-basierte Lastverteilung vor den Samplern. Wir behandeln das in Tail Sampling in OpenTelemetry. Zur Frage Agent oder Gateway im Allgemeinen lesen Sie Collector-Deployment-Muster.

Eine Agent-Konfiguration für die Schichten 1, 2 und 5

Das ist ein minimaler Node-Agent. Er ist ein Ausgangspunkt, keine gehärtete Konfiguration.

receivers:
  otlp:
    protocols: { grpc: {}, http: {} }
  kubeletstats:
    collection_interval: 30s
    auth_type: serviceAccount
    endpoint: "https://${env:K8S_NODE_NAME}:10250"
    insecure_skip_verify: true      # Kubelet-Zertifikate sind oft selbst signiert; besser eine echte CA
  hostmetrics:
    root_path: /hostfs              # das Wurzeldateisystem des Nodes, schreibgeschützt eingehängt
    collection_interval: 30s
    scrapers: { cpu: {}, memory: {}, filesystem: {}, network: {}, load: {} }
  filelog:
    include: [ /var/log/pods/*/*/*.log ]
    exclude: [ /var/log/pods/observability_*/*/*.log ]   # nicht der Collector selbst
    include_file_path: true
    operators:
      - type: container

processors:
  memory_limiter: { check_interval: 1s, limit_percentage: 80, spike_limit_percentage: 25 }
  k8sattributes: {}
  batch: {}

exporters:
  otlp:
    endpoint: otel-gateway.observability.svc:4317

service:
  pipelines:
    metrics:
      receivers: [ otlp, kubeletstats, hostmetrics ]
      processors: [ memory_limiter, k8sattributes, batch ]
      exporters: [ otlp ]
    logs:
      receivers: [ otlp, filelog ]
      processors: [ memory_limiter, k8sattributes, batch ]
      exporters: [ otlp ]

Der Agent braucht seinen Node-Namen als Umgebungsvariable, entnommen dem Feld spec.nodeName der Downward API. Der Receiver kubeletstats braucht ausserdem per RBAC Lesezugriff auf den Stats-Endpunkt des Kubelets.

Die clusterweite Hälfte, einmal

Dies ist der Collector, der als einzelnes Replikat läuft. Sein Service-Account braucht list und watch auf den Objekten, die er liest.

receivers:
  k8s_cluster:
    auth_type: serviceAccount
    collection_interval: 30s
  k8sobjects:
    auth_type: serviceAccount
    objects:
      - name: events
        mode: watch
        field_selector: type=Warning     # die gesprächigen Normal-Events weglassen

exporters:
  otlp:
    endpoint: otel-gateway.observability.svc:4317

service:
  pipelines:
    metrics:
      receivers: [ k8s_cluster ]
      exporters: [ otlp ]
    logs:
      receivers: [ k8sobjects ]
      exporters: [ otlp ]

Den Kubernetes-Kontext ergänzen

Rohe Kubelet-Metriken kennen den Pod, aber nicht das Deployment, dem er gehört. Der Prozessor k8sattributes schliesst diese Lücke, und er steckt auch hinter den meisten Diskussionen der Art «warum ist dieses Attribut leer». Zuordnungsschlüssel, RBAC pro Attribut und die Label-Falle stehen in Der k8sattributes-Prozessor, dem zweiten Beitrag dieser Serie.

Über mehrere Cluster hinweg betreiben

Alles oben Gezeigte ist Konfiguration, die auf jedem Node und in jedem Cluster identisch bleiben muss. Genau dort driftet eine Flotte auseinander: Ein Cluster bekommt das neue RBAC, ein anderer behält die Receiver-Liste vom letzten Quartal. LinkMesh verwaltet die Konfiguration von OpenTelemetry-Collectoren über eine Flotte hinweg. Für Kubernetes richtet es einen Cluster als zwei Collector-Gruppen ein: eine Node-Gruppe als DaemonSet und einen Cluster-Collector mit einem Replikat, der Cluster-Zustand und Events einmal erfasst. Es ergänzt die Anreicherung mit k8sattributes und entfernt änderungsfreudige Attribute vor dem Export. Die Schicht-für-Schicht-Anleitung zum Onboarding dokumentiert jede Voreinstellung und wie Sie sie abschalten.

Zwei Grenzen, offen benannt. LinkMesh leitet Telemetrie und konfiguriert sie. Es speichert und wertet sie nicht aus, Dashboards und Alarmregeln bleiben also in Ihrem Backend. Und es erfasst die Control Plane nicht für Sie, also die oben beschriebene, plattformabhängige Schicht. Denselben Cluster unter dem Blickwinkel der Regulierung beschreibt Kubernetes- und OpenShift-Observability in regulierten IT-Umgebungen.

Wenn Sie Kubernetes betreiben und das auf einem echten Cluster sehen möchten, bringt die Installationsanleitung einen ersten Collector in wenigen Minuten zum Laufen.

Quellen