OpenTelemetry OpenTelemetry

Envía telemetría a backends y protege el pipeline

Configura exporters OTLP para Tempo, Loki y Prometheus, además de TLS, autenticación y secretos.

14 min Intermedio

Recopilar telemetría es la mitad del trabajo; la otra mitad es entregarla al lugar correcto de forma segura. Esta guía muestra cómo configurar exporters para los backends de código abierto más comunes (los ejemplos usan la pila de Grafana) y cómo proteger el tráfico de entrada y salida del Collector con TLS, autenticación y secretos que se mantengan fuera de tus archivos de configuración.

Exporters OTLP: gRPC y HTTP

Dos exporters hablan OTLP:

  • otlp usa gRPC. El endpoint es host:puerto sin esquema, normalmente el puerto 4317.
  • otlphttp usa HTTP. El endpoint es una URL, normalmente el puerto 4318, y el exporter añade la ruta de la señal (/v1/traces, /v1/metrics, /v1/logs) a ella.

Usa un sufijo de nombre para definir varios del mismo tipo:

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

Detalles de los backends que conviene conocer:

  • Tempo acepta OTLP directamente en sus puertos de receiver (4317 gRPC, 4318 HTTP) cuando el receiver OTLP está habilitado en su configuración.
  • Loki acepta logs OTLP en /otlp en su puerto HTTP, así que con otlphttp la URL final pasa a ser /otlp/v1/logs.
  • Prometheus acepta métricas OTLP en /api/v1/otlp/v1/metrics, pero solo si se inicia con el receiver OTLP habilitado (el flag --web.enable-otlp-receiver).

Confirma estas rutas en la documentación de cada producto para la versión que ejecutes. Luego enruta cada señal a su 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 puede tener varios exporters para enviar los mismos datos a más de un lugar, por ejemplo un backend principal y un archivo.

TLS en los exporters

Para cualquier cosa que cruce una red no confiable, usa TLS:

exporters:
  otlp/backend:
    endpoint: otlp.example.com:4317
    tls:
      ca_file: /etc/otel/certs/ca.crt        # para confiar en una CA privada
      cert_file: /etc/otel/certs/client.crt  # para TLS mutuo
      key_file: /etc/otel/certs/client.key

Con una CA pública puedes omitir todo el bloque tls, ya que se usan las raíces del sistema. insecure: true desactiva TLS y es solo para desarrollo dentro del clúster. Evita insecure_skip_verify: true en producción, porque elimina la protección que ofrece TLS.

TLS y autenticación en los receivers

Un Collector que escucha en un puerto de red debería exigir TLS y, si es accesible para algo que no controlas, autenticación.

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 certificados de cliente (mTLS)

Para la autenticación basada en tokens, usa una extensión de autenticación. La extensión bearertokenauth puede tanto enviar como comprobar un token:

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]

Para validar las peticiones entrantes, existen otras extensiones, como basicauth y oidc, referenciadas desde el receiver con auth: { authenticator: <nombre> }. Las opciones disponibles difieren según la distribución y la versión, así que consulta el README de la extensión.

Para credenciales simples basadas en encabezados, también puedes definir encabezados en un exporter:

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

Mantén los secretos fuera de la configuración

Nunca escribas un token o una contraseña literalmente en un archivo de configuración que viva en Git. Haz referencia a una variable de entorno y suministra la variable desde un almacén de secretos:

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

En Kubernetes, inyecta la variable desde un Secret:

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

El propio Secret debería estar cifrado en Git (por ejemplo con SOPS, como en las guías de Flux) o sincronizado desde un gestor de secretos. El Collector también soporta un provider file: (${file:/path/to/secret}) que lee un archivo montado, lo que se adapta a secretos montados como volúmenes y rotados por la plataforma. Sea cual sea la fuente que uses, confirma que el provider está disponible en tu distribución; las builds contrib incluyen varios.

Exposición de red

Como el Collector suele ejecutarse dentro del clúster, su postura predeterminada importa:

  • Enlaza de forma deliberada. Las versiones recientes dejan los receivers en localhost por defecto, lo que es seguro pero inaccesible desde otros contenedores. Usa 0.0.0.0 solo para los puertos que deban ser accesibles, y protégelos con una NetworkPolicy, TLS o autenticación.
  • Desactiva lo que no uses. Elimina los receivers y puertos de Service sin usar para mantener pequeña la superficie.
  • Los endpoints de depuración son para operadores. Mantén zpages y pprof en localhost, y nunca los expongas públicamente.
  • Redacta antes de exportar. Usa los processors attributes o transform para eliminar credenciales, tokens y datos personales antes de que salgan de tu red (consulta la guía de preparación para producción).

Una NetworkPolicy que permite solo a los namespaces de aplicación llegar al 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

Verifica

  1. Ejecuta otelcol validate --config=config.yaml para detectar errores de YAML y de esquema.
  2. Inicia el Collector y revisa sus logs en busca de errores de conexión o TLS en los exporters.
  3. Envía un span de prueba y búscalo en el backend. Si no llega, compara el protocolo y el puerto del exporter con lo que el backend escucha realmente.
  4. Comprueba las propias métricas del Collector en busca de contadores otelcol_exporter_send_failed_*, que suben cuando un backend rechaza datos.

Guías populares