OpenTelemetry OpenTelemetry

Deployment-Muster des Collectors: Kein Collector, Agent und Gateway

Wähle eine Topologie und konfiguriere die Übergabe von Agent zu Gateway, einschließlich Kubernetes-Metadaten.

12 min Fortgeschritten

Der Collector ist ein einzelnes Binary, aber du kannst ihn in mehreren Formen betreiben. Welche passt, hängt davon ab, wie viele Services du hast, wie viel Verarbeitung du brauchst und wem die Infrastruktur gehört. Diese Anleitung beschreibt die Muster und zeigt die Konfiguration für das gängigste: Agents auf Knotenebene, die an ein zentrales Gateway weiterleiten.

Die Muster

Kein Collector. Anwendungen exportieren OTLP direkt an ein Backend. Das ist das einfachste Setup, ohne etwas Zusätzliches zu betreiben, und für einen Prototyp in Ordnung. Die Nachteile: Jede Anwendung braucht die Backend-Adresse und Zugangsdaten, ein Wechsel des Ziels bedeutet ein erneutes Deployment der Apps, und es gibt keinen zentralen Ort zum Filtern, Schwärzen oder Sampeln.

Agent. Ein Collector läuft neben dem Workload: als Sidecar oder einer pro Knoten (ein DaemonSet auf Kubernetes). Apps senden an localhost oder den Knoten, sodass der Export schnell und der Netzwerkpfad der App kurz ist. Agents eignen sich für Host- und Knoten-Metriken, Log-Sammlung aus lokalen Dateien und das Anreichern von Daten mit lokalen Metadaten. Der Nachteil sind viele zu konfigurierende und zu aktualisierende Instanzen.

Gateway. Ein oder mehrere Collector laufen als zentraler Service, an den Anwendungen oder Agents senden. Ein Gateway ist der Ort für schwere oder globale Arbeit: Tail Sampling, Routing zu mehreren Backends, Rate Limiting und das Halten der Zugangsdaten für die Backends. Es ist ein Service, den du hinter einem Load Balancer horizontal skalieren kannst.

Agent plus Gateway. Das gängige Produktionsdesign: Agents erledigen lokale Sammlung und leichte Anreicherung und leiten per OTLP an das Gateway weiter, das die zentrale Verarbeitung erledigt und an Backends exportiert. Es hält die Anwendungskonfiguration trivial (an den Knoten-Agent senden), hält Backend-Zugangsdaten an einem Ort und gibt jeder Schicht eine Aufgabe.

App ─OTLP─▶ Agent (pro Knoten) ─OTLP─▶ Gateway (Deployment) ─▶ Backends
                │ Host-Metriken, Logs,            │ Tail Sampling, Routing,
                │ k8s-Metadaten                   │ Zugangsdaten, Retries

Die Agent-Konfiguration

Ein Agent hält die Verarbeitung minimal und leitet alles an das Gateway weiter:

receivers:
  otlp:
    protocols:
      grpc:
        endpoint: 0.0.0.0:4317
      http:
        endpoint: 0.0.0.0:4318
  hostmetrics:
    collection_interval: 30s
    scrapers:
      cpu:
      memory:
      filesystem:
      network:

processors:
  memory_limiter:
    check_interval: 1s
    limit_percentage: 75
    spike_limit_percentage: 15
  k8s_attributes:
    passthrough: true     # nur die Pod-IP festhalten; das Gateway sucht den Rest nach
  batch:

exporters:
  otlp/gateway:
    endpoint: otel-gateway.observability.svc.cluster.local:4317
    tls:
      insecure: true      # nutze in der Produktion echtes TLS zwischen den Schichten
    sending_queue:
      enabled: true
      queue_size: 2000
    retry_on_failure:
      enabled: true

service:
  pipelines:
    traces:
      receivers: [otlp]
      processors: [memory_limiter, k8s_attributes, batch]
      exporters: [otlp/gateway]
    metrics:
      receivers: [otlp, hostmetrics]
      processors: [memory_limiter, k8s_attributes, batch]
      exporters: [otlp/gateway]
    logs:
      receivers: [otlp]
      processors: [memory_limiter, k8s_attributes, batch]
      exporters: [otlp/gateway]

passthrough: true ist der Schlüssel für das Zwei-Schichten-Design. Der Agent fügt jeder Resource nur die Pod-IP hinzu, ohne die Kubernetes-API aufzurufen. Das Gateway kann nicht sehen, wo Telemetrie entstanden ist, sobald sie von einem Agent ankommt, und nutzt daher diese IP zur Anreicherung.

Die Gateway-Konfiguration

receivers:
  otlp:
    protocols:
      grpc:
        endpoint: 0.0.0.0:4317

processors:
  memory_limiter:
    check_interval: 1s
    limit_percentage: 80
    spike_limit_percentage: 20
  k8s_attributes:
    auth_type: serviceAccount
    passthrough: false
    extract:
      metadata:
        - k8s.namespace.name
        - k8s.pod.name
        - k8s.deployment.name
        - k8s.node.name
    pod_association:
      - sources:
          - from: resource_attribute
            name: k8s.pod.ip
      - sources:
          - from: connection
  batch:

exporters:
  otlp/tempo:
    endpoint: tempo:4317
    tls:
      insecure: true
  otlphttp/prometheus:
    endpoint: http://prometheus:9090/api/v1/otlp
  otlphttp/loki:
    endpoint: http://loki:3100/otlp

service:
  pipelines:
    traces:
      receivers: [otlp]
      processors: [memory_limiter, k8s_attributes, batch]
      exporters: [otlp/tempo]
    metrics:
      receivers: [otlp]
      processors: [memory_limiter, k8s_attributes, batch]
      exporters: [otlphttp/prometheus]
    logs:
      receivers: [otlp]
      processors: [memory_limiter, k8s_attributes, batch]
      exporters: [otlphttp/loki]

Das Gateway liest die vom Agent angehängte Pod-IP, fragt die Kubernetes-API nach den Metadaten dieses Pods und fügt Namespace-, Pod- und Deployment-Namen hinzu. Die Backend-Endpunkte unterscheiden sich je nach Produkt, bestätige also die genauen OTLP-Pfade in der Dokumentation deines Backends (die Grafana-Anleitungen in dieser Bibliothek behandeln den Grafana-Stack).

Kubernetes-Berechtigungen für k8s_attributes

Der Prozessor liest Pod-Metadaten, sein Service Account braucht also Lesezugriff:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: otel-k8s-attributes
rules:
  - apiGroups: [""]
    resources: ["pods", "namespaces", "nodes"]
    verbs: ["get", "watch", "list"]
  - apiGroups: ["apps"]
    resources: ["replicasets", "deployments", "statefulsets", "daemonsets"]
    verbs: ["get", "list", "watch"]
  - apiGroups: ["batch"]
    resources: ["jobs", "cronjobs"]
    verbs: ["get", "list", "watch"]

Binde sie an den Service Account, der den Prozessor betreibt. Das Preset kubernetesAttributes des Helm-Charts erstellt das nötige RBAC für dich. Wenn Agents als DaemonSet laufen und eigene Lookups durchführen statt durchzureichen, setze filter.node_from_env_var auf eine Variable, die den Knotennamen trägt (aus der Downward API), damit jeder Agent nur Pods auf seinem eigenen Knoten beobachtet, was die API-Last auf großen Clustern niedrig hält.

Ein Muster wählen

SituationNutze
Prototyp, ein oder zwei ServicesKein Collector oder ein Gateway
Knoten-Metriken oder Logdateien nötigAgent als DaemonSet
Mehrere Teams, zentrale Policy, Tail Sampling, Backend-Zugangsdaten an einem OrtAgent plus Gateway
Strikte Isolation pro TeamEin Gateway pro Team, optional ein gemeinsames Plattform-Gateway dahinter

Betriebliche Hinweise

  • Betreibe mindestens zwei Gateway-Replikas hinter einem Service und gib Agents eine Queue und Retries, damit ein Gateway-Neustart keine Daten verliert.
  • Nutze TLS zwischen Agents und dem Gateway außerhalb eines vertrauenswürdigen Netzwerks und authentifiziere Sender am Gateway, wo es exponiert ist.
  • Pinne nach Möglichkeit dieselbe Collector-Version über alle Schichten und aktualisiere zuerst das Gateway.
  • Wenn du Tail Sampling hinzufügst, füge die Load-Balancing-Schicht aus der Sampling-Anleitung zwischen Agents und dem Sampler ein.

Beliebte Anleitungen