¿Por qué OpenTelemetry? ¿Por qué darse el trabajo de entrar en otro ámbito más en el universo de la observabilidad? ¿Además, qué es OpenTelemetry?

Veamos cómo lo define la comunidad: OpenTelemetry es un framework y un conjunto de herramientas de observabilidad diseñadas para crear y administrar los datos de telemetría como las trazas, las métricas y los logs. Lo esencial es que OpenTelemetry es independiente del proveedor y de las herramientas. Esto quiere decir que se puede utilizar con una gran variedad de backends de observabilidad, lo que incluye herramientas de código abierto como Jaeger y Prometheus, además de productos comerciales. OpenTelemetry es un proyecto de la Cloud Native Computing Foundation (CNCF).

Suena interesante. Y si lees sobre la misión, la visión y los valores de la comunidad, parece aún más interesante. Pero igual, probablemente hay un montón de proyectos de sandbox de la CNCF que tienen objetivos muy similares. ¿Qué hace que OpenTelemetry (también conocido como OTel) sea tan especial?

Échale un vistazo a cómo este proyecto ha evolucionado con el tiempo y qué compañías están contribuyendo activamente; puedes ver cómo está creciendo y lo que será capaz de hacer en los próximos años.

Así que la pregunta real es: ¿por qué no unirse ahora?

Comprender Kubernetes

El propósito de este blog no es hablar de lo que la mayoría de nosotros ya sabemos sobre Kubernetes, pero un poco de contexto podría ser útil.

Se supone que Kubernetes es una plataforma con un alto grado de disponibilidad. Para ello, fue diseñado para transferir varias responsabilidades a varios componentes escalables. Echemos un vistazo rápido al resumen de los documentos oficiales:

Hay muchas variables que deben funcionar correctamente para que tus flujos de trabajo puedan ejecutarse sin problemas. Afortunadamente, estos componentes muestran su información de rendimiento de manera detallada para que puedas tener una mejor perspectiva de lo que está sucediendo en el clúster. Aún mejor, todos utilizan un lenguaje común: Prometheus.

Recopilar métricas en todo el clúster

Puesto que Kubernetes nos habla en Prometheus, ¿por qué no responder de la misma manera? Aunque parezca sencillo, realmente no lo es.

Para comenzar, Prometheus funciona con un mecanismo pull, lo que quiere decir que tú eres responsable de definir los extremos que Prometheus necesita para buscar y extraer las métricas que expone. Eso es todo un desafío si se tiene en cuenta que Kubernetes es por naturaleza extremadamente dinámico en lo que se refiere a crear y eliminar contenedores rápidamente.

Por suerte, Prometheus ha incorporado la detección de servicios para Kubernetes para la cual puedes configurar diferentes trabajos de extracción (scrape) para que tus instancias de Prometheus puedan determinar qué se debe verificar de antemano.

¿Y la escalabilidad?

A medida que nuestro clúster crece cada vez más, una instancia de Prometheus podría necesitar una gran cantidad de recursos y por lo tanto una máquina muy grande para poder ejecutarse. Preferiríamos tener varias instancias más pequeñas que se ejecutan en máquinas más pequeñas. Sin embargo, puesto que estamos extrayendo métricas, tener varias instancias quiere decir que extraeríamos los mismos extremos varias veces.

Dicho esto, ahora es un buen momento para introducir el recolector de OpenTelemetry. Resumido brevemente, el recolector OTel consta de tres componentes principales: receptores, procesadores y exportadores. Si utilizas diferentes opciones de estos tres componentes, podrás crear varias canalizaciones para manejar los datos de telemetría y enviarlos a los distintos backends según tus necesidades.

¿Cómo podemos aprovechar el recolector OTel para que hable con Kubernetes?

Viene con un receptor Prometheus, que se puede configurar de la misma manera que un servidor Prometheus, es decir, podemos utilizar las mismas definiciones de los trabajos de extracción. Lo bueno es que no es necesario almacenar las métricas obtenidas localmente (aparte de la memoria en sí). Puedes pensar en ello como Prometheus en modo de agente.

Hasta aquí, vamos bien. Pero el problema del sharding (particionamiento) sigue estando presente: todavía no podemos escalar nuestros recolectores OTel horizontalmente. Para eso es que sirve el Target Allocator. Este está ubicado al frente de los recolectores OTel con información de estado y manipula sus configuraciones de Prometheus, en función de los objetivos que se deben extraer, distribuyéndolos en todas las instancias. Cada extremo es extraído por una instancia del recolector OTel a la vez. Para obtener más información sobre cómo funciona la escalabilidad del extractor, consulta la documentación oficial.

Hemos hablado mucho sobre cómo funciona Prometheus, cómo aprovechar los recolectores OTel y cómo escalarlos, pero no hemos dicho nada acerca de lo que en realidad tenemos que recolectar. Veamos qué ofrece Kubernetes.

Primero, cada componente del panel de control aparece en sus puertos dedicados y proporciona sus métricas en el extremo /metrics. Por ejemplo, veamos la configuración de un trabajo de extracción del kube-api-server:

scrape_configs:
- job_name: 'kubernetes-apiservers'
  scrape_interval: 60s
  kubernetes_sd_configs:
    - role: endpoints
  scheme: https
  tls_config:
    ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
    insecure_skip_verify: true
  bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
  relabel_configs:
    - source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name]
      action: keep
      regex: default;kubernetes;https

Segundo, necesitamos visibilidad en las máquinas (nodos). Un producto popular y maduro para la recopilación y exposición de las métricas de nodos es Node Exporter. Podemos ejecutarlo como un daemonset en todos los nodos (Linux) y extraer lo que recopila de la máquina subyacente como sigue:

scrape_configs:
- job_name: 'kubernetes-node-exporter'
  scrape_interval: 60s
  honor_labels: true
  kubernetes_sd_configs:
    - role: endpoints
  relabel_configs:
    - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scrape]
      action: keep
      regex: true
    - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scrape_slow]
      action: drop
      regex: true
    - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scheme]
      action: replace
      target_label: __scheme__
      regex: (https?)
    - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_path]
      action: replace
      target_label: __metrics_path__
      regex: (.+)
    - source_labels: [__address__, __meta_kubernetes_service_annotation_prometheus_io_port]
      action: replace
      target_label: __address__
      regex: (.+?)(?::\d+)?;(\d+)
      replacement: $$1:$$2
    - source_labels: [__meta_kubernetes_service_name]
      action: keep
      regex: <NODE_EXPORTER_SERVICE_NAME>
    - source_labels: [__meta_kubernetes_namespace]
      action: replace
      target_label: namespace
    - source_labels: [__meta_kubernetes_service_name]
      action: replace
      target_label: service
    - source_labels: [__meta_kubernetes_pod_node_name]
      action: replace
      target_label: node

Ahora que ya tenemos las métricas a nivel de máquina, podemos pasar a un nivel superior y monitorear nuestros contenedores. Las métricas de contenedores son recopiladas por la herramienta cAdvisor (Container Advisor), que se ejecuta en cada nodo. Podemos extraerlas como sigue:

scrape_configs:
- job_name: 'kubernetes-nodes-cadvisor'
  scrape_interval: 60s
  scheme: https
  tls_config:
    ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
    insecure_skip_verify: true
  bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
  kubernetes_sd_configs:
    - role: node
  relabel_configs:
    - target_label: __address__
      replacement: kubernetes.default.svc:443
    - source_labels: [__meta_kubernetes_node_name]
      regex: (.+)
      target_label: __metrics_path__
      replacement: /api/v1/nodes/$$1/proxy/metrics/cadvisor

Por último, pero no menos importante, ahora tenemos que conocer el estado de los componentes de nuestro clúster. La herramienta kube-state-metrics solicita esa información a los distintos extremos y genera métricas que podemos extraer una vez más con el receptor Prometheus de nuestros recolectores OTel:

scrape_configs:
- job_name: 'kubernetes-kube-state-metrics'
  scrape_interval: 60s
  honor_labels: true
  kubernetes_sd_configs:
    - role: endpoints
  relabel_configs:
    - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scrape]
      action: keep
      regex: true
    - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scrape_slow]
      action: drop
      regex: true
    - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scheme]
      action: replace
      target_label: __scheme__
      regex: (https?)
    - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_path]
      action: replace
      target_label: __metrics_path__
      regex: (.+)
    - source_labels: [__address__, __meta_kubernetes_service_annotation_prometheus_io_port]
      action: replace
      target_label: __address__
      regex: (.+?)(?::\d+)?;(\d+)
      replacement: $$1:$$2
    - source_labels: [__meta_kubernetes_service_name]
      action: keep
      regex: <KUBE_STATE_METRICS_SERVICE_NAME>
    - source_labels: [__meta_kubernetes_namespace]
      action: replace
      target_label: namespace
    - source_labels: [__meta_kubernetes_service_name]
      action: replace
      target_label: service
    - source_labels: [__meta_kubernetes_pod_node_name]
      action: replace
      target_label: node

En este momento, no es necesario decir que simplemente podemos crear un trabajo de extracción dedicado a cada componente individual que deseamos monitorear.

¿Qué más podemos obtener del clúster?

Además de las métricas que hemos recopilado exitosamente con el receptor Prometheus, también podemos recopilar eventos y logs de nuestros clústeres. (Nota: no hablaremos de las trazas en este blog.)

Comencemos con los eventos. Kubernetes gatilla eventos cada vez que se produce una creación, eliminación o mutación en el clúster. Esos eventos se pueden recuperar haciendo una consulta a kube-api-server. Afortunadamente, el recolector OTel cuenta con un receptor para eso: el receptor k8sevents. (Nota: en la actualidad se está hablando sobre si conviene convertir este receptor en obsoleto y usar el receptor k8sobject en el futuro.)

Puedes ejecutar una sola instancia del recolector para obtener los eventos de Kubernetes y enviarlos a New Relic como logs. Atención: varias instancias del receptor k8sevent obtendrán los mismos eventos y los enviarán a New Relic.

¿Y los logs? El recolector OTel incluye un receptor filelog, que puedes ejecutar como un daemonset y en el que puedes montar el directorio de logs del nodo. Puedes utilizar distintas expresiones regulares (regex) para recopilar, analizar, filtrar y enriquecer los logs de cualquier componente en tu clúster.

Desplegar recolectores OTel y monitorear con New Relic

Sabemos dónde se encuentran los datos de telemetría que se necesitan y cómo recopilarlos. Ahora tenemos que:

  1. Crear una estrategia para desplegar nuestras instancias del recolector OTel con las configuraciones necesarias.
  2. Crear dashboards y alertas adecuados con consultas extensas de New Relic Query Language (NRQL) para monitorear nuestros clústeres.

¡Buenas noticias! Hay un repositorio que contiene todo lo que hemos mencionado hasta ahora:

  • Un gráfico Helm público que puedes usar para implementar tus recolectores OTel.
  • Un despliegue Terraform que puedes utilizar para arrancar el monitoreo prediseñado en tu cuenta de New Relic.

Si deseas más información, échale un vistazo a los siguientes recursos:

  • Lee esta documentación para comprender por qué necesitamos varios tipos (daemonset, despliegue, statefulset, singleton) de recolectores.
  • Consulta esta documentación si quieres desplegar la solución de monitoreo en tu clúster.
  • Averigua cómo consultar correctamente y descifrar los datos recopilados de Prometheus en esta documentación.

Consulta esta documentación si deseas crear dashboards y alertas en tu cuenta de New Relic.