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
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.