OpenTelemetry OpenTelemetry

Envoyer la télémétrie vers des backends et sécuriser le pipeline

Configurez des exporters OTLP pour Tempo, Loki et Prometheus, ainsi que TLS, l'authentification et les secrets.

14 min Intermédiaire

Collecter la télémétrie n’est que la moitié du travail ; l’autre moitié est de la livrer au bon endroit en toute sécurité. Ce guide montre comment configurer des exporters pour les backends open source courants (la stack Grafana sert pour les exemples), et comment sécuriser le trafic entrant et sortant du Collector avec TLS, authentification et secrets qui restent hors de vos fichiers de configuration.

Exporters OTLP : gRPC et HTTP

Deux exporters parlent OTLP :

  • otlp utilise gRPC. L’endpoint est host:port sans schéma, généralement le port 4317.
  • otlphttp utilise HTTP. L’endpoint est une URL, généralement le port 4318, et l’exporter lui ajoute le chemin du signal (/v1/traces, /v1/metrics, /v1/logs).

Utilisez un suffixe de nom pour définir plusieurs exporters du même type :

exporters:
  otlp/tempo:
    endpoint: tempo.observability.svc.cluster.local:4317
    tls:
      insecure: true
  otlphttp/loki:
    endpoint: http://loki.observability.svc.cluster.local:3100/otlp
  otlphttp/prometheus:
    endpoint: http://prometheus.observability.svc.cluster.local:9090/api/v1/otlp

Spécificités des backends à connaître :

  • Tempo accepte OTLP directement sur ses ports de receiver (4317 gRPC, 4318 HTTP) lorsque le receiver OTLP est activé dans sa configuration.
  • Loki accepte les logs OTLP sur /otlp sur son port HTTP ; avec otlphttp, l’URL finale devient donc /otlp/v1/logs.
  • Prometheus accepte les métriques OTLP sur /api/v1/otlp/v1/metrics, mais uniquement s’il est démarré avec le receiver OTLP activé (l’option --web.enable-otlp-receiver).

Confirmez ces chemins dans la documentation de chaque produit pour la version que vous exécutez. Routez ensuite chaque signal vers son backend :

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

Un pipeline peut avoir plusieurs exporters pour envoyer les mêmes données à plusieurs endroits, par exemple un backend principal et une archive.

TLS sur les exporters

Pour tout ce qui traverse un réseau non fiable, utilisez TLS :

exporters:
  otlp/backend:
    endpoint: otlp.example.com:4317
    tls:
      ca_file: /etc/otel/certs/ca.crt        # pour faire confiance à une CA privée
      cert_file: /etc/otel/certs/client.crt  # pour le TLS mutuel
      key_file: /etc/otel/certs/client.key

Avec une CA publique, vous pouvez omettre tout le bloc tls, car les racines du système sont utilisées. insecure: true désactive TLS et est réservé au développement dans le cluster. Évitez insecure_skip_verify: true en production, car il supprime la protection que TLS apporte.

TLS et authentification sur les receivers

Un Collector qui écoute sur un port réseau devrait exiger TLS et, s’il est accessible par quoi que ce soit que vous ne contrôlez pas, une authentification.

receivers:
  otlp:
    protocols:
      grpc:
        endpoint: 0.0.0.0:4317
        tls:
          cert_file: /etc/otel/certs/server.crt
          key_file: /etc/otel/certs/server.key
          client_ca_file: /etc/otel/certs/ca.crt   # exige des certificats clients (mTLS)

Pour l’authentification par jeton, utilisez une extension d’authentification. L’extension bearertokenauth peut à la fois envoyer et vérifier un jeton :

extensions:
  bearertokenauth/client:
    scheme: Bearer
    token: ${env:BACKEND_TOKEN}

exporters:
  otlphttp/backend:
    endpoint: https://otlp.example.com
    auth:
      authenticator: bearertokenauth/client

service:
  extensions: [bearertokenauth/client]

Pour valider les requêtes entrantes, d’autres extensions existent, comme basicauth et oidc, référencées depuis le receiver avec auth: { authenticator: <name> }. Les options disponibles diffèrent selon la distribution et la version ; consultez le README de l’extension.

Pour des identifiants simples basés sur des en-têtes, vous pouvez aussi définir des en-têtes sur un exporter :

exporters:
  otlphttp/saas:
    endpoint: https://otlp.vendor.example.com
    headers:
      api-key: ${env:VENDOR_API_KEY}

Garder les secrets hors de la configuration

N’écrivez jamais un jeton ou un mot de passe littéralement dans un fichier de configuration qui vit dans Git. Référencez plutôt une variable d’environnement, et fournissez la variable depuis un magasin de secrets :

exporters:
  otlphttp/backend:
    headers:
      authorization: Bearer ${env:BACKEND_TOKEN}

Sur Kubernetes, injectez la variable depuis un Secret :

env:
  - name: BACKEND_TOKEN
    valueFrom:
      secretKeyRef:
        name: otel-backend
        key: token

Le Secret lui-même devrait être chiffré dans Git (par exemple avec SOPS, comme dans les guides Flux) ou synchronisé depuis un gestionnaire de secrets. Le Collector prend aussi en charge un provider file: (${file:/path/to/secret}) qui lit un fichier monté, ce qui convient aux secrets montés comme volumes et renouvelés par la plateforme. Quelle que soit la source, confirmez que le provider est disponible dans votre distribution ; les builds contrib en incluent plusieurs.

Exposition réseau

Comme le Collector s’exécute souvent à l’intérieur du cluster, sa posture par défaut compte :

  • Liez avec discernement. Les versions récentes lient par défaut les receivers à localhost, ce qui est sûr mais inaccessible depuis d’autres conteneurs. Utilisez 0.0.0.0 uniquement pour les ports qui doivent être accessibles, et protégez-les avec une NetworkPolicy, TLS ou une authentification.
  • Désactivez ce que vous n’utilisez pas. Retirez les receivers et ports de Service inutilisés pour que la surface reste petite.
  • Les endpoints de debug sont pour les opérateurs. Gardez zpages et pprof sur localhost, et ne les exposez jamais publiquement.
  • Expurgez avant l’export. Utilisez les processors attributes ou transform pour supprimer identifiants, jetons et données personnelles avant qu’ils ne quittent votre réseau (voir le guide de préparation à la production).

Une NetworkPolicy qui n’autorise que les namespaces applicatifs à joindre le Collector :

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-otlp-from-apps
  namespace: observability
spec:
  podSelector:
    matchLabels:
      app.kubernetes.io/name: opentelemetry-collector
  policyTypes: [Ingress]
  ingress:
    - from:
        - namespaceSelector:
            matchLabels:
              telemetry: "enabled"
      ports:
        - protocol: TCP
          port: 4317
        - protocol: TCP
          port: 4318

Vérifier

  1. Exécutez otelcol validate --config=config.yaml pour détecter les erreurs de YAML et de schéma.
  2. Démarrez le Collector et vérifiez ses logs pour des erreurs de connexion ou de TLS sur les exporters.
  3. Envoyez un span de test, puis cherchez-le dans le backend. S’il n’arrive pas, comparez le protocole et le port de l’exporter avec ce que le backend écoute réellement.
  4. Vérifiez les métriques propres du Collector pour les compteurs otelcol_exporter_send_failed_*, qui augmentent lorsqu’un backend rejette des données.

Guides populaires