LinkMesh

Doku, Blog und Changelog durchsuchen

Die Dokumentation ist nur auf Englisch verfügbar.

ENDE
Zwei identische Pumpen nebeneinander, verbunden durch einen Querverteiler, sodass jede allein die Leitung übernehmen kann
LinkMeshObservability Data Collection Management
OpenTelemetryTelemetry Pipelines

Collector High Availability

Kein Single Point of Failure, kein stiller Datenverlust.

linkmesh.io
8 Min. Lesezeit

Der OpenTelemetry Collector ist leicht aufzusetzen und leicht fragil zu machen. Ein einzelner Gateway-Collector im Pfad jedes Signals ist ein Single Point of Failure: Starten Sie ihn neu, lassen Sie ihm den Speicher ausgehen oder rollen Sie eine fehlerhafte Config, und Telemetrie stoppt — oder schlimmer, verschwindet, ohne dass es jemand bemerkt, bis ein Dashboard leer ist während genau des Incidents, für den Sie es gebraucht hätten. High Availability ist kein Feature, das man einschaltet; es ist ein Satz bewusster Entscheidungen über Redundanz, Buffering und Backpressure.

Dieser Leitfaden behandelt diese Entscheidungen für die zwei Ebenen, die die meisten Flotten betreiben — Agents auf jedem Host und ein geteilter Gateway-Pool — und ist am Ende ehrlich zur Garantie: Der Collector gibt Ihnen At-least-once-Zustellung innerhalb endlicher Buffer, kein magisches Versprechen, dass nie ein Byte verloren geht.

Für wen dieser Leitfaden ist

Platform Engineers und SREs, die OpenTelemetry Collectors im kritischen Pfad betreiben und sie brauchen, um Node-Neustarts, Deploys und Traffic-Spitzen zu überstehen, ohne Telemetrie zu verlieren oder einen Flaschenhals zu schaffen. Voraussetzungen: ein funktionierendes Collector-Deployment und Vertrautheit mit den Agent-/Gateway-Deployment-Patterns.

Zwei Ebenen, zwei HA-Probleme

Die meisten Produktionstopologien haben zwei Collector-Ebenen, und jede fällt anders aus:

  • Agent-Ebene — ein Collector pro Host oder pro Node (DaemonSet), der lokale Telemetrie erfasst. Ihr HA-Problem ist lokales Buffering: Wenn das Downstream kurz unerreichbar ist oder der Agent neu startet, müssen in-flight-Daten überleben statt zu verschwinden.
  • Gateway-Ebene — ein Pool von Collectors, die OTLP von den Agents empfangen, die schwerere Verarbeitung (Tail Sampling, Aggregation, Routing) erledigen und an Backends exportieren. Ihr HA-Problem ist Redundanz und Lastverteilung: Kein einzelnes Gateway darf dasjenige sein, dessen Tod die Pipeline stoppt.

Die gute Nachricht ist, dass sich die Mechanismen überschneiden. Beide Ebenen wollen eine Sending Queue, Retry und einen Memory Limiter; die Gateway-Ebene fügt Load Balancing und zustandslose Replicas obendrauf hinzu.

OTLP an einen Gateway-Pool lastverteilen

Die Gateway-Ebene sollte ein Satz identischer, zustandsloser Replicas hinter etwas sein, das die Last über sie verteilt. Es gibt zwei gängige Ansätze, und sie lösen unterschiedliche Probleme:

  • Ein einfacher L4/L7-Load-Balancer oder Kubernetes-Service. Agents senden OTLP an einen virtuellen Endpoint; der Service oder LB verteilt Verbindungen über gesunde Gateway-Pods. Verlieren Sie einen Pod, wird der Traffic zu den Überlebenden umgeleitet. Das ist der richtige Default für Metriken und Logs, wo jedes Gateway jeden Batch bearbeiten kann.
  • Der loadbalancing-Exporter. Wenn Sie konsistentes Routing brauchen — alle Spans eines Traces landen auf demselben Gateway, damit Tail Sampling den ganzen Trace sieht — reicht ein einfacher LB nicht, weil er einen Trace über Pods aufteilen kann. Der loadbalancing-Exporter hasht auf Trace-ID (oder einen Routing-Key) und löst Backends via DNS oder einen Kubernetes-Resolver auf, sodass zusammengehörige Daten zusammen landen.
exporters:
  loadbalancing:
    routing_key: traceID
    protocol:
      otlp:
        tls:
          insecure: true
    resolver:
      k8s:
        service: otel-gateway.observability
        ports: [4317]

Halten Sie Gateways zustandslos, damit jede Replica austauschbar ist und der Pool horizontal skaliert. Zustand, der geteilt werden muss (wie Tail-Sampling-Entscheidungen über einen Trace hinweg), ist genau das, was der Routing-Key des loadbalancing-Exporters auf einem Node hält, statt den Pool zur Koordination zu zwingen.

Agent · Host 1 Agent · Host 2 Agent · Host N Load Balancer Gateway 1 Gateway 2 Gateway 3 Backend zustandsloser Pool übersteht einen Verlust

Die Sending Queue und Retry

Redundanz handhabt einen toten Node; die Sending Queue und Retry handhaben einen vorübergehend unerreichbaren. Jeder Exporter sollte beide aktivieren, damit ein kurzer Backend-Ausfall oder ein Netz-Aussetzer zu Buffering-und-Retry wird statt zu verworfenen Daten:

exporters:
  otlphttp:
    endpoint: https://backend.example.net
    retry_on_failure:
      enabled: true
      initial_interval: 5s
      max_interval: 30s
      max_elapsed_time: 300s
    sending_queue:
      enabled: true
      num_consumers: 10
      queue_size: 10000

retry_on_failure wiederholt fehlgeschlagene Exporte mit exponentiellem Backoff bis zu max_elapsed_time; danach wird der Batch verworfen statt ewig wiederholt. sending_queue puffert akzeptierte Batches im Speicher, damit Producer nicht blockiert werden, während Exporte in Flight sind. Dimensionieren Sie queue_size für das Volumen, das Sie brauchen, um einen typischen Backend-Aussetzer zu überbrücken — aber denken Sie daran, dass eine In-Memory-Queue bei einem Neustart verloren geht, was das nächste Problem ist.

Eine persistente Queue, die Neustarts übersteht

Eine In-Memory-Queue verdampft, wenn der Collector neu startet — ein Deploy, ein OOM-Kill, ein Node-Reboot — und nimmt alles Gepufferte mit. Die file_storage-Extension unterlegt die Sending Queue mit Disk, sodass akzeptierte Daten einen Neustart überstehen und wiederholt werden, wenn der Collector zurückkommt:

extensions:
  file_storage/queue:
    directory: /var/lib/otelcol/queue

exporters:
  otlphttp:
    endpoint: https://backend.example.net
    sending_queue:
      enabled: true
      storage: file_storage/queue
      queue_size: 100000

service:
  extensions: [file_storage/queue]

Das verwandelt “Neustart verwirft in-flight-Telemetrie” in “Neustart pausiert die Zustellung kurz”. Es zählt am meisten auf der Agent-Ebene, wo der lokale Buffer eines Nodes das Einzige ist, das zwischen einem Downstream-Ausfall und verlorenen Daten steht. Der Preis ist Disk-I/O und eine begrenzte Menge lokalen Speichers — ein Handel, der sich im Pfad von Daten, die Ihnen wichtig sind, fast immer lohnt.

Die LinkMesh-Collector-Flotte — Status, Version und Health jedes Nodes, sodass ein Gateway, das ungesund wird, sichtbar ist, bevor es zu einer Lücke wird.

Backpressure und der Memory Limiter

Der Ausfall, den Sie am wenigsten wollen, ist ein Collector, der mehr akzeptiert, als er exportieren kann, seinen Heap wachsen lässt und OOM-gekillt wird — dabei seine Buffer verliert und die Pipeline mitreisst. Der memory_limiter-Processor verhindert das, indem er Backpressure anwendet: Wenn der Speicher ein Soft-Limit überschreitet, beginnt er, neue Daten abzulehnen und den Druck zurück an die Producer zu schieben (die wiederholen), statt abzustürzen:

processors:
  memory_limiter:
    check_interval: 1s
    limit_percentage: 80
    spike_limit_percentage: 25

Setzen Sie memory_limiter an erste Stelle in der Processor-Kette, damit er Last abwirft, bevor Arbeit an Daten getan wird, die ohnehin nicht exportiert werden können. Backpressure fühlt sich an wie abgelehnte Daten, und das ist sie auch — aber ein Collector, der zurückdrückt und am Leben bleibt, schützt weit mehr Telemetrie als einer, der alles schluckt und stirbt. Paaren Sie ihn mit einem geordneten Drain beim Shutdown (SIGTERM-Handling und eine Termination-Grace-Period, lang genug, um die Queue zu flushen), damit geplante Neustarts flushen statt verwerfen.

Was Sie garantieren können und was nicht

Seien Sie mit Stakeholdern ehrlich zur Garantie, denn sie überzuverkaufen ist der Weg, wie Vertrauen beim ersten echten Ausfall verloren geht:

  • Sie erhalten At-least-once-Zustellung innerhalb endlicher Buffer. Mit Retry und einer persistenten Queue überstehen Daten transiente Ausfälle und Neustarts und werden wiederholt — und können mehr als einmal zugestellt werden, das Downstream muss also Duplikate tolerieren.
  • Buffer sind begrenzt, ein hinreichend langer Ausfall verwirft also trotzdem Daten. Ist das Backend über max_elapsed_time hinaus unten, wird ein Batch aufgegeben; und sobald die Queue voll ist, werden neu ankommende Daten abgelehnt und verworfen. HA verlängert, wie lange Sie einen Ausfall überbrücken können; es macht den Buffer nicht unendlich.
  • Exactly-once wird nicht angeboten. Der Collector macht keine End-to-end-Exactly-once-Zustellung. Entwerfen Sie Dashboards und Alerts so, dass sie gelegentliche Lücken und Duplikate tolerieren, statt einen perfekten Stream anzunehmen.

Das richtige mentale Modell ist den Blast Radius jedes wahrscheinlichen Ausfalls reduzieren — ein Node-Tod, ein Deploy, eine Spitze, ein kurzer Backend-Ausfall — nicht null Verlust unter allen Bedingungen garantieren. Bringen Sie Redundanz, Queue-plus-Retry, Persistenz und Backpressure an ihren Platz, und Sie haben die Ausfälle abgedeckt, die in der Produktion tatsächlich passieren.

Betreiben Sie Collectors im kritischen Pfad?

LinkMesh verwaltet eine Flotte von OpenTelemetry Collectors von einer selbstgehosteten Control Plane aus — liefern Sie validierte Config, inklusive Memory-Limits, in einer Aktion an jeden Node, und beobachten Sie den Durchsatz pro Edge, sodass ein ungesundes Gateway sichtbar ist, bevor es zu einer Lücke wird. Pipeline-Telemetrie fliesst nie durch LinkMesh; sie bleibt auf Ihrer Infrastruktur. Stellen Sie eine auf in Minuten, oder sehen Sie, was sie kann.