Saltar a contenido

Alloy

Agente de recolección de logs (Grafana Alloy). Corre como DaemonSet en los 3 nodos y envía los logs de pods y del sistema (journald) a Loki.

Resumen

Alloy sustituye a Promtail (deprecado) como recogedor de logs. Hace solo logs; las métricas las hace Prometheus (node-exporter/kube-state-metrics), así que Alloy no las duplica. Descubre pods vía la API de k8s (loki.source.kubernetes) y les sigue los logs; también lee el journald de cada nodo (loki.source.journal).

Estado

Campo Valor
Estado Operativo
Argo CD Application alloy
Namespace monitoring

Despliegue

Campo Valor
Método Helm chart
Chart / imagen alloy@1.12.1 (app v1.19.2)
Origen https://grafana.github.io/helm-charts
Config en el repo clusters/luka/apps/alloy/application.yaml (config river inline)

Red

Campo Valor
Service — (DaemonSet, no expone nada)
IP —
URL interna —
URL externa —
TLS —

Acceso y usuarios

  • No tiene interfaz. Logs vía kubectl -n monitoring logs -l app.kubernetes.io/name=alloy.

Configuración

  • controller.type: daemonset (default): corre en los 3 nodos.
  • Nivel de log: bloque logging { level = "warn" } al inicio del river — evita el ruido de opened log stream de loki.source.kubernetes (~160k líneas/día).
  • Config river (inline en valuesObject.alloy.configMap.content): discovery.kubernetes (pods) → discovery.relabel (filtro al nodo local con NODE_NAME + labels node/namespace/pod/container) → loki.source.kubernetes (tail vía API de k8s) → loki.write (http://loki.monitoring.svc:3100/loki/api/v1/push), más loki.source.journal.
  • Filtro por nodo: discovery.relabel mantiene solo los pods del propio nodo (__meta_kubernetes_pod_node_name = env("NODE_NAME"), expuesto por extraEnv con spec.nodeName). Sin él, cada pod del DaemonSet tailaría todos los pods del cluster (triplicado, porque loki.source.kubernetes usa la API).
  • journald (loki.source.journal):
  • path = "/var/log/journal" — obligatorio: con path vacío el componente usa el socket systemd (sd_journal_open), inexistente en el contenedor, y no recoge nada. Con path usa sd_journal_open_directory y sí lee.
  • max_age = "30m" — evita leer el backlog antiguo que Loki rechaza.
  • relabel_rules vía loki.relabel: extrae __journal__hostname → node y __journal__systemd_unit → unit.
  • mounts.varlog: true: monta /var/log del host, solo para loki.source.journal (los logs de pods van por la API de k8s, no por el filesystem).
  • global.podSecurityContext.supplementalGroups: [999, 4] (systemd-journal, adm)
  • runAsUser: 0: necesarios para leer el journald del host.

Almacenamiento

  • — (sin PVC; efímero).

Dependencias

  • Depende de: k3s, Loki.
  • Usado por: nadie (servicio de plataforma).

Backup y recuperación

  • — (re-desplegable desde Git; sin estado).

Monitorización

  • Pendiente (métricas propias de Alloy si se habilitan en el river).

Referencias

Notas / TODO

  • El job label del journal queda como loki.source.journal.journal (el labels = { job = ... } no lo sobreescribe); el resto de labels (node, unit) sí se aplican. Cosmético.
  • El env() stdlib está deprecado (warning en los logs); revisar alternativa.