OpenTelemetry OpenTelemetry

Patrones de despliegue del Collector: sin Collector, agente y gateway

Elige una topología y configura el traspaso de agente a gateway, incluidos los metadatos de Kubernetes.

12 min Intermedio

El Collector es un solo binario, pero puedes ejecutarlo de varias formas. Cuál encaja depende de cuántos servicios tengas, de cuánto procesamiento necesites y de quién sea dueño de la infraestructura. Esta guía describe los patrones y muestra la configuración del más común: agentes a nivel de nodo que reenvían a un gateway central.

Los patrones

Sin Collector. Las aplicaciones exportan OTLP directamente a un backend. Es la configuración más simple, sin nada extra que ejecutar, y sirve para un prototipo. Los inconvenientes: cada aplicación necesita la dirección y las credenciales del backend, cambiar de destino significa volver a desplegar las aplicaciones y no hay ningún lugar central donde filtrar, redactar o muestrear.

Agente. Un Collector se ejecuta junto a la carga de trabajo: como sidecar, o uno por nodo (un DaemonSet en Kubernetes). Las aplicaciones envían a localhost o al nodo, así que la exportación es rápida y la ruta de red de la aplicación es corta. Los agentes son buenos para métricas de host y de nodo, recopilación de logs desde archivos locales y enriquecimiento de los datos con metadatos locales. El inconveniente son las muchas instancias que configurar y actualizar.

Gateway. Uno o más Collectors se ejecutan como un servicio central al que envían las aplicaciones o los agentes. Un gateway es el lugar para el trabajo pesado o global: tail sampling, enrutamiento a varios backends, limitación de tasa y custodia de las credenciales de los backends. Es un servicio que puedes escalar horizontalmente detrás de un balanceador de carga.

Agente más gateway. El diseño común de producción: los agentes hacen recopilación local y un enriquecimiento ligero, y reenvían por OTLP al gateway, que hace el procesamiento central y exporta a los backends. Mantiene la configuración de las aplicaciones trivial (enviar al agente del nodo), mantiene las credenciales de los backends en un solo lugar y da a cada capa un solo trabajo.

App ─OTLP─▶ Agente (por nodo) ─OTLP─▶ Gateway (Deployment) ─▶ Backends
                │ métricas de host, logs,         │ tail sampling, enrutamiento,
                │ metadatos de k8s                │ credenciales, reintentos

La configuración del agente

Un agente mantiene el procesamiento al mínimo y reenvía todo al gateway:

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     # solo registra la IP del pod; el gateway busca el resto
  batch:

exporters:
  otlp/gateway:
    endpoint: otel-gateway.observability.svc.cluster.local:4317
    tls:
      insecure: true      # usa TLS real entre capas en producción
    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 es la clave del diseño de dos capas. El agente solo añade la IP del pod a cada resource, sin llamar a la API de Kubernetes. El gateway no puede ver dónde se originó la telemetría una vez que llega desde un agente, así que usa esa IP para enriquecer.

La configuración del gateway

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]

El gateway lee la IP del pod que adjuntó el agente, pregunta a la API de Kubernetes por los metadatos de ese pod y añade los nombres de namespace, pod y deployment. Los endpoints de los backends difieren según el producto, así que confirma las rutas OTLP exactas en la documentación de tu backend (las guías de Grafana de esta biblioteca cubren la pila de Grafana).

Permisos de Kubernetes para k8s_attributes

El processor lee los metadatos de los pods, así que su service account necesita acceso de lectura:

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"]

Asócialo a la service account que ejecuta el processor. El preset kubernetesAttributes del chart de Helm crea el RBAC necesario por ti. Cuando los agentes se ejecutan como DaemonSet y hacen sus propias búsquedas en lugar de pasarlas, define filter.node_from_env_var con una variable que lleve el nombre del nodo (desde la downward API), de modo que cada agente solo vigile los pods de su propio nodo, lo que mantiene baja la carga sobre la API en clústeres grandes.

Cómo elegir un patrón

SituaciónUsa
Prototipo, uno o dos serviciosSin Collector, o un gateway
Necesitas métricas de nodo o archivos de logAgente como DaemonSet
Varios equipos, política central, tail sampling, credenciales de backend en un solo lugarAgente más gateway
Aislamiento estricto por equipoUn gateway por equipo, opcionalmente un gateway de plataforma compartido detrás de ellos

Notas operativas

  • Ejecuta al menos dos réplicas de gateway detrás de un Service, y da a los agentes una cola y reintentos para que un reinicio del gateway no pierda datos.
  • Usa TLS entre agentes y gateway fuera de una red de confianza, y autentica a los emisores hacia el gateway donde esté expuesto.
  • Fija la misma versión del Collector en todas las capas cuando puedas, y actualiza primero el gateway.
  • Si añades tail sampling, añade el nivel de balanceo de carga de la guía de muestreo entre los agentes y el sampler.

Guías populares