OpenTelemetry OpenTelemetry

Den Collector produktionsreif machen: Speicherlimits, Batching und Retries

Konfiguriere Prozessoren, Queues und persistenten Speicher, damit Telemetrie Überlast und Ausfälle übersteht.

12 min Fortgeschritten

Ein Collector, der auf einem Laptop funktioniert, kann in der Produktion umfallen: Eine Traffic-Spitze erschöpft den Speicher, ein Backend-Ausfall verwirft Daten oder ein Neustart verliert alles, was gerade unterwegs ist. Die Lösungen sind alle Konfiguration. Diese Anleitung behandelt die Prozessoren und Exporter-Einstellungen, die jeder produktive Collector haben sollte, und die Reihenfolge, in der du sie setzt.

Die Basis-Pipeline

processors:
  memory_limiter:
    check_interval: 1s
    limit_percentage: 80
    spike_limit_percentage: 20
  batch:
    timeout: 5s
    send_batch_size: 8192

service:
  pipelines:
    traces:
      receivers: [otlp]
      processors: [memory_limiter, batch]
      exporters: [otlp/backend]

Die Reihenfolge zählt: Prozessoren laufen in der aufgelisteten Reihenfolge. memory_limiter kommt zuerst, damit Backpressure die Receiver erreicht, bevor irgendetwas anderes Speicher verbraucht. batch kommt zuletzt, nach jedem Filtern oder Anreichern, damit Batches aus den endgültigen Daten gebaut werden.

memory_limiter

Er beobachtet den Speicher des Collectors und verweigert neue Daten, wenn die Nutzung zu hoch wird, sodass der Prozess langsamer wird, statt vom Betriebssystem beendet zu werden.

processors:
  memory_limiter:
    check_interval: 1s
    limit_mib: 4000
    spike_limit_mib: 800
  • check_interval gibt an, wie oft der Speicher gemessen wird. Ein Wert von 1s wird empfohlen, und der Standard 0s deaktiviert die periodische Prüfung.
  • limit_mib ist das harte Limit für den Heap-Speicher. Der gesamte Prozess nutzt typischerweise etwas mehr.
  • spike_limit_mib ist der erwartete maximale Sprung zwischen Prüfungen und hat standardmäßig 20 Prozent des Limits. Das weiche Limit ist limit_mib minus spike_limit_mib (hier 3200 MiB).
  • limit_percentage und spike_limit_percentage drücken dieselben Limits als Anteil des verfügbaren Speichers aus (Linux mit cgroups). Sie passen zu Containern, in denen das Speicherlimit von Kubernetes gesetzt wird. Ist limit_mib ebenfalls gesetzt, hat es Vorrang.

Oberhalb des weichen Limits verweigert der Prozessor Daten, indem er einen Fehler an die vorherige Komponente zurückgibt, und gut erzogene Sender wiederholen oder verlangsamen. Oberhalb des harten Limits erzwingt er außerdem Garbage Collection. Setze es etwas unter das Speicherlimit des Containers, damit es greift, bevor es der Kernel tut.

batch

Batching gruppiert Einträge, sodass Exporte weniger und größer sind, was Netzwerk und Backend-Arbeit spart.

processors:
  batch:
    timeout: 5s            # senden nach dieser Zeit, auch wenn der Batch nicht voll ist
    send_batch_size: 8192  # Ziel-Batchgröße
    send_batch_max_size: 0 # 0 bedeutet keine Obergrenze

Stimme timeout auf Latenz und send_batch_size auf Durchsatz ab. Neuere Collector-Versionen können auch innerhalb der Queue eines Exporters bündeln; prüfe die Dokumentation des Exporter-Helpers für deine Version.

Exporter-Queue und Retries

Exporter, die über das Netzwerk senden, haben eine Sending Queue und eine Retry-Policy. Sie sitzen im Exporter, nicht in einem Prozessor, und sie sind es, die dich vor kurzen Backend-Ausfällen schützen:

exporters:
  otlp/backend:
    endpoint: backend.example.com:4317
    sending_queue:
      enabled: true
      queue_size: 5000        # Standard ist 1000
    retry_on_failure:
      enabled: true
      initial_interval: 5s
      max_interval: 30s
      max_elapsed_time: 10m   # Standard ist 300s

Wie du über die Zahlen denkst:

  • Die Queue puffert Batches, während das Backend langsam oder down ist. Eine größere Queue übersteht längere Vorfälle, nutzt aber mehr Speicher.
  • retry_on_failure wiederholt mit wachsenden Abständen, bis zu max_elapsed_time. Danach werden die Daten verworfen.
  • Dimensioniere beides für dein Volumen und den längsten Ausfall, den du ohne Verlust überstehen willst.

Persistente Queue: Neustarts überleben

Standardmäßig lebt die Queue im Speicher, ein Absturz verliert also, was in der Queue war. Stütze sie mit der Extension file_storage auf die Platte:

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

exporters:
  otlp/backend:
    endpoint: backend.example.com:4317
    sending_queue:
      storage: file_storage

service:
  extensions: [file_storage]
  pipelines:
    traces:
      receivers: [otlp]
      processors: [memory_limiter, batch]
      exporters: [otlp/backend]

Drei Teile sind erforderlich: die Extension definieren, sie im Exporter referenzieren und unter service.extensions aktivieren. Mounte ein Persistent Volume an dieses Verzeichnis, zum Beispiel einen PersistentVolumeClaim für ein StatefulSet. Daten können weiterhin verloren gehen, wenn die Platte vollläuft oder ausfällt oder wenn das Backend länger als das Retry-Limit down bleibt, überwache also die Plattennutzung.

Nützliche Prozessoren über die Grundlagen hinaus

Attribute hinzufügen oder ändern:

processors:
  resource/env:
    attributes:
      - key: deployment.environment.name
        value: production
        action: upsert
  attributes/scrub:
    actions:
      - key: http.request.header.authorization
        action: delete
      - key: user.email
        action: hash

resource bearbeitet Attribute, die den Erzeuger beschreiben (auf einen ganzen Batch angewendet), und attributes bearbeitet Attribute pro Span, Metrikpunkt oder Log-Record. Nutze sie, um Umgebungs-Labels hinzuzufügen und sensible Werte zu entfernen oder zu hashen, bevor Daten dein Netzwerk verlassen.

Rauschen verwerfen mit dem Prozessor filter, geschrieben in der OpenTelemetry Transformation Language (OTTL):

processors:
  filter/health:
    error_mode: ignore
    traces:
      span:
        - 'attributes["url.path"] == "/healthz"'
        - 'attributes["url.path"] == "/ready"'

Daten transformieren mit dem Prozessor transform:

processors:
  transform/normalize:
    error_mode: ignore
    trace_statements:
      - context: span
        statements:
          - set(attributes["team"], "payments") where resource.attributes["service.name"] == "checkout"

OTTL ist mächtig, teste Statements also mit dem debug-Exporter auf einer Kopie deiner Daten, bevor du sie in der Produktion aktivierst. Die Statement-Syntax und die verfügbaren Kontexte ändern sich zwischen Versionen, prüfe also die README des Prozessors für deine. Diese Prozessoren sind in der Contrib-Distribution.

Den Collector selbst schützen

  • Setze Kubernetes-Ressourcen-Requests und -Limits und halte memory_limiter unter dem Limit.
  • Füge health_check hinzu und nutze es für Liveness- und Readiness-Probes.
  • Überwache die eigenen Metriken des Collectors auf Port 8888 auf Queue-Größe, verworfene Einträge und verweigerte Daten. Alarmiere, wenn sich otelcol_exporter_queue_size seiner Kapazität nähert oder Exporter Sendefehler melden.
  • Betreibe für Gateways mehr als ein Replikat hinter einem Service und dimensioniere ein einzelnes Replikat für den Burst, den du erwartest.

Checkliste

  • memory_limiter ist der erste Prozessor in jeder Pipeline.
  • batch ist der letzte Prozessor.
  • Netzwerk-Exporter haben eine Sending Queue und eine Retry-Policy, dimensioniert für deine Ausfalltoleranz.
  • Wo Datenverlust inakzeptabel ist, ist eine persistente Queue konfiguriert.
  • Sensible Attribute werden am Rand gelöscht oder gehasht.
  • Health Checks, Ressourcenlimits und Collector-Metriken sind vorhanden.

Beliebte Anleitungen