OpenTelemetry OpenTelemetry

Den OpenTelemetry Operator für Collector und Auto-Instrumentierung nutzen

Deklariere Collector und Instrumentierung als Kubernetes-Ressourcen und injiziere Agents mit Pod-Annotationen.

15 min Experte

Der OpenTelemetry Operator verwaltet zwei Dinge als Kubernetes-Ressourcen: Collector (ein OpenTelemetryCollector-Objekt) und Auto-Instrumentierung (ein Instrumentation-Objekt plus Pod-Annotationen, die dem Operator sagen, einen Agent zu injizieren). Anwendungsteams bekommen Telemetrie durch Hinzufügen einer Annotation, nicht durch Bearbeiten von Dockerfiles, und Plattformteams halten die Einstellungen an einem Ort in Git.

Den Operator installieren

Der Operator nutzt Admission-Webhooks, die TLS-Zertifikate brauchen. Der einfachste Weg ist cert-manager, das das Chart standardmäßig erwartet. Ohne cert-manager lass Helm ein selbstsigniertes Zertifikat erzeugen:

helm repo add open-telemetry https://open-telemetry.github.io/opentelemetry-helm-charts
helm repo update

helm install my-opentelemetry-operator open-telemetry/opentelemetry-operator \
  --namespace opentelemetry-operator-system --create-namespace \
  --set "manager.collectorImage.repository=otel/opentelemetry-collector-k8s" \
  --set admissionWebhooks.certManager.enabled=false \
  --set admissionWebhooks.autoGenerateCert.enabled=true

Ist cert-manager bereits installiert, kannst du die Zertifikatseinstellungen auf ihren Standards lassen oder deinen eigenen Issuer über admissionWebhooks.certManager.issuerRef referenzieren. Pinne die Chart-Version mit --version und lege die Values in eine Datei oder ein Flux-HelmRelease statt in --set-Flags.

Einen Collector deklarieren

apiVersion: opentelemetry.io/v1beta1
kind: OpenTelemetryCollector
metadata:
  name: demo
  namespace: observability
spec:
  mode: deployment        # deployment, daemonset, statefulset oder sidecar
  replicas: 2
  config:
    receivers:
      otlp:
        protocols:
          grpc:
            endpoint: 0.0.0.0:4317
          http:
            endpoint: 0.0.0.0:4318
    processors:
      memory_limiter:
        check_interval: 1s
        limit_percentage: 80
        spike_limit_percentage: 20
      batch: {}
    exporters:
      debug: {}
    service:
      pipelines:
        traces:
          receivers: [otlp]
          processors: [memory_limiter, batch]
          exporters: [debug]

Der Block config ist dasselbe Collector-YAML, das du bisher geschrieben hast, in die Ressource eingebettet. Der Operator erstellt den Workload und einen Service namens <name>-collector (hier demo-collector), der die Ports bereitstellt, die deine Receiver nutzen. Die verfügbaren mode-Werte entsprechen den Mustern aus der Deployment-Anleitung: daemonset für Agents, deployment für Gateways und sidecar für einen in Anwendungs-Pods injizierten Collector. Prüfe die in deinem Cluster verfügbare CRD-Version (kubectl get crd opentelemetrycollectors.opentelemetry.io), da sich die API-Version über Releases hinweg geändert hat.

Instrumentierungs-Einstellungen deklarieren

Eine Instrumentation-Ressource hält die SDK-Einstellungen, die der Operator in annotierte Pods injiziert:

apiVersion: opentelemetry.io/v1alpha1
kind: Instrumentation
metadata:
  name: demo-instrumentation
  namespace: webapp
spec:
  exporter:
    endpoint: http://demo-collector.observability.svc.cluster.local:4318
  propagators:
    - tracecontext
    - baggage
  sampler:
    type: parentbased_traceidratio
    argument: "0.25"
  java:
    env:
      - name: OTEL_INSTRUMENTATION_COMMON_DEFAULT_ENABLED
        value: "true"

Wichtige Details:

  • exporter.endpoint ist standardmäßig http://localhost:4317, wenn es weggelassen wird, was meist nichts ausliefert. Setze es immer auf den Service deines Collectors.
  • Nutze für einen Collector in einem anderen Namespace den vollständigen DNS-Namen, <service>.<namespace>.svc.cluster.local.
  • Die dokumentierten Beispiele nutzen Port 4318 (HTTP) für .NET, Go, Java und Python und 4317 (gRPC) für Node.js. Passe den Port an das Protokoll an, das der Sprach-Agent nutzt.
  • Sprachspezifische Umgebungsvariablen kommen unter spec.<language>.env, etwa spec.java.env oder spec.python.env.

Erstelle die Instrumentation vor der Anwendung. Der Operator injiziert den Agent, wenn ein Pod erstellt wird. Existiert die Ressource noch nicht, startet der Pod ohne den Init-Container, und du musst ihn neu starten.

Workloads per Annotation einbeziehen

Füge eine Annotation zum Pod-Template eines Deployments hinzu:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: checkout
  namespace: webapp
spec:
  selector:
    matchLabels: { app: checkout }
  template:
    metadata:
      labels: { app: checkout }
      annotations:
        instrumentation.opentelemetry.io/inject-java: "true"
    spec:
      containers:
        - name: checkout
          image: myorg/checkout:1.4.2

Die Annotation pro Sprache:

SpracheAnnotation
Javainstrumentation.opentelemetry.io/inject-java: "true"
Pythoninstrumentation.opentelemetry.io/inject-python: "true"
Node.jsinstrumentation.opentelemetry.io/inject-nodejs: "true"
.NETinstrumentation.opentelemetry.io/inject-dotnet: "true"
Goinstrumentation.opentelemetry.io/inject-go: "true" (plus die Annotation für die Ziel-Executable)
Nur SDK-Einstellungeninstrumentation.opentelemetry.io/inject-sdk: "true"

Der Wert kann "true" sein (nutze die Instrumentation in diesem Namespace), der Name einer ("my-instrumentation"), ein Namespace-qualifizierter Name ("other-ns/my-instrumentation") oder "false". Setze die Annotation auf einen Namespace, um jeden Workload darin zu instrumentieren.

Verwandte Annotationen, die du nutzen wirst:

  • instrumentation.opentelemetry.io/container-names: "app,worker" wählt, welche Container instrumentiert werden. Standardmäßig ist es nur der erste.
  • resource.opentelemetry.io/service.name: checkout setzt Resource-Attribute wie den Service-Namen. Weitere sind service.version und deployment.environment.name.
  • instrumentation.opentelemetry.io/inject-sdk: "true" injiziert nur die Umgebungsvariablen, für Apps, die bereits ein SDK enthalten.
  • Ein einzelner Container kann nicht mehr als eine Sprache injiziert bekommen. Setups mit mehreren Containern und Sprachen brauchen das Feature-Flag enable-multi-instrumentation und Annotationen für Container-Namen pro Sprache.
  • Go erfordert das Feature-Gate enable-go-instrumentation, die Annotation otel-go-auto-target-exe (oder die Einstellung OTEL_GO_AUTO_TARGET_EXE) und einen privilegierten Sidecar, prüfe also zuerst die Sicherheitsfolgen.

Anwenden und prüfen

kubectl apply -f collector.yaml -f instrumentation.yaml
kubectl apply -f checkout-deployment.yaml

kubectl get opentelemetrycollectors,instrumentations -A
kubectl get pod -n webapp -l app=checkout -o jsonpath='{.items[0].spec.initContainers[*].name}'; echo
kubectl logs -n observability deploy/demo-collector | grep -i 'service.name'

Ein Init-Container namens opentelemetry-auto-instrumentation am Anwendungs-Pod bedeutet, dass die Injection funktioniert hat. Erzeuge etwas Traffic, und der debug-Exporter des Collectors sollte Spans mit deinem Service-Namen ausgeben.

Fehlersuche

  1. Ist die Instrumentation-Ressource da? kubectl describe otelinst -n <namespace>.
  2. Operator-Fehler? Lies die Logs des Containers manager im Operator-Namespace.
  3. Wurde sie vor der App erstellt? Falls nicht, starte das Deployment neu, damit der Pod neu erstellt und injiziert wird. Prüfe kubectl get events -n <namespace> auf den Init-Container.
  4. Stimmt die Annotation? Sie muss auf spec.template.metadata.annotations stehen, und die Sprache muss zur App passen.
  5. Stimmt der Endpunkt? Ein falsches Protokoll oder ein falscher Port oder ein kurzer Service-Name über Namespaces hinweg sendet stillschweigend nichts.

Wann der Operator zu bevorzugen ist

Nutze ihn, wenn viele Teams in den Cluster deployen und du Telemetrie per Annotation als Opt-in mit zentral verwalteten Einstellungen willst. Nutze das einfache Helm-Chart, wenn du nur einen Collector brauchst und die SDK-Konfiguration in den eigenen Manifesten jeder Anwendung behandelst. Der Operator und das Chart können nebeneinander existieren, aber verwalte nicht denselben Collector mit beiden.

Beliebte Anleitungen