OpenTelemetry OpenTelemetry

Utiliser l'OpenTelemetry Operator pour les Collectors et l'auto-instrumentation

Déclarez Collectors et instrumentation comme des ressources Kubernetes, et injectez des agents avec des annotations de pod.

15 min Avancé

L’OpenTelemetry Operator gère deux choses sous forme de ressources Kubernetes : les Collectors (un objet OpenTelemetryCollector) et l’auto-instrumentation (un objet Instrumentation plus des annotations de pod qui indiquent à l’Operator d’injecter un agent). Les équipes applicatives obtiennent de la télémétrie en ajoutant une annotation, sans modifier de Dockerfile, et les équipes plateforme gardent les paramètres en un seul endroit dans Git.

Installer l’Operator

L’Operator utilise des admission webhooks, qui nécessitent des certificats TLS. La voie la plus simple est cert-manager, que le chart attend par défaut. Sans cert-manager, laissez Helm générer un certificat auto-signé :

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

Avec cert-manager déjà installé, vous pouvez laisser les paramètres de certificat à leurs valeurs par défaut, ou référencer votre propre issuer via admissionWebhooks.certManager.issuerRef. Épinglez la version du chart avec --version, et placez les values dans un fichier ou dans une HelmRelease Flux plutôt que dans des options --set.

Déclarer un Collector

apiVersion: opentelemetry.io/v1beta1
kind: OpenTelemetryCollector
metadata:
  name: demo
  namespace: observability
spec:
  mode: deployment        # deployment, daemonset, statefulset ou 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]

Le bloc config est le même YAML de Collector que vous écrivez depuis le début, intégré dans la ressource. L’Operator crée la charge de travail et un Service nommé <name>-collector (ici demo-collector) qui expose les ports utilisés par vos receivers. Les valeurs de mode disponibles correspondent aux modèles du guide de déploiement : daemonset pour les agents, deployment pour les gateways, et sidecar pour un Collector injecté dans les pods applicatifs. Vérifiez la version de CRD disponible dans votre cluster (kubectl get crd opentelemetrycollectors.opentelemetry.io), car la version d’API a changé au fil des releases.

Déclarer les paramètres d’instrumentation

Une ressource Instrumentation contient les paramètres de SDK que l’Operator injecte dans les pods annotés :

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"

Détails importants :

  • exporter.endpoint vaut par défaut http://localhost:4317 s’il est omis, ce qui ne livre généralement rien. Définissez-le toujours vers le Service de votre Collector.
  • Pour un Collector dans un autre namespace, utilisez le nom DNS complet, <service>.<namespace>.svc.cluster.local.
  • Les exemples documentés utilisent le port 4318 (HTTP) pour .NET, Go, Java et Python, et 4317 (gRPC) pour Node.js. Faites correspondre le port au protocole utilisé par l’agent du langage.
  • Les variables d’environnement propres à un langage se placent sous spec.<language>.env, comme spec.java.env ou spec.python.env.

Créez l’Instrumentation avant l’application. L’Operator injecte l’agent lorsqu’un pod est créé. Si la ressource n’existe pas encore, le pod démarre sans l’init container et vous devez le redémarrer.

Inscrire les charges de travail avec des annotations

Ajoutez une annotation au pod template d’un Deployment :

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

L’annotation selon le langage :

LangageAnnotation
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 l’annotation de l’exécutable cible)
Paramètres du SDK uniquementinstrumentation.opentelemetry.io/inject-sdk: "true"

La valeur peut être "true" (utiliser l’Instrumentation de ce namespace), le nom d’une instrumentation ("my-instrumentation"), un nom qualifié par le namespace ("other-ns/my-instrumentation"), ou "false". Placez l’annotation sur un namespace pour instrumenter toutes les charges de travail qu’il contient.

Annotations connexes que vous utiliserez :

  • instrumentation.opentelemetry.io/container-names: "app,worker" choisit les conteneurs à instrumenter. Par défaut, seul le premier l’est.
  • resource.opentelemetry.io/service.name: checkout définit des attributs de resource comme le nom du service. D’autres incluent service.version et deployment.environment.name.
  • instrumentation.opentelemetry.io/inject-sdk: "true" injecte uniquement les variables d’environnement, pour les applications qui incluent déjà un SDK.
  • Un même conteneur ne peut pas recevoir l’injection de plus d’un langage. Les configurations multi-conteneurs et multi-langages nécessitent le feature flag enable-multi-instrumentation et des annotations de noms de conteneurs par langage.
  • Go nécessite le feature gate enable-go-instrumentation, l’annotation otel-go-auto-target-exe (ou le paramètre OTEL_GO_AUTO_TARGET_EXE), et un sidecar privilégié ; examinez donc d’abord les implications de sécurité.

Appliquer et vérifier

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'

Un init container nommé opentelemetry-auto-instrumentation sur le pod applicatif signifie que l’injection a fonctionné. Générez du trafic, et l’exporter debug du Collector devrait afficher des spans avec le nom de votre service.

Dépannage

  1. La ressource Instrumentation est-elle présente ? kubectl describe otelinst -n <namespace>.
  2. Des erreurs de l’Operator ? Lisez les logs du conteneur manager dans le namespace de l’Operator.
  3. A-t-elle été créée avant l’application ? Sinon, redémarrez le Deployment pour que le pod soit recréé et injecté. Vérifiez kubectl get events -n <namespace> pour l’init container.
  4. L’annotation est-elle correcte ? Elle doit figurer dans spec.template.metadata.annotations, et le langage doit correspondre à l’application.
  5. L’endpoint est-il correct ? Un protocole ou un port erroné, ou un nom de Service court entre namespaces, n’envoie silencieusement rien.

Quand préférer l’Operator

Utilisez-le lorsque de nombreuses équipes déploient dans le cluster et que vous voulez que la télémétrie soit activée à la demande par annotation, avec des paramètres gérés de manière centrale. Utilisez le chart Helm simple lorsque vous avez seulement besoin d’un Collector et que vous gérez la configuration des SDK dans les manifestes de chaque application. L’Operator et le chart peuvent coexister, mais ne gérez pas le même Collector avec les deux.

Guides populaires