Grafana Alerting evalúa consultas sobre tus fuentes de datos a intervalos regulares y envía una notificación cuando el resultado cruza un umbral. En este tutorial configurarás el envío de correo de Grafana, crearás puntos de contacto para email y Slack, definirás políticas de notificación que envían las alertas críticas a un canal distinto de los avisos, y crearás dos reglas sobre métricas de Prometheus: un servidor que deja de responder y un disco casi lleno. Primero lo harás desde la interfaz y después verás cómo definir lo mismo en archivos YAML versionables.
Requisitos previos
Para seguir esta guía necesitas:
- Un servidor con Ubuntu 24.04 LTS, por ejemplo un VPS de CubePath, con Grafana 11 o posterior instalado desde el repositorio oficial de Grafana (paquete
grafana, serviciografana-server). - Un usuario no root con privilegios
sudoy acceso a Grafana con una cuenta de rol Admin. - Una fuente de datos Prometheus configurada en Grafana, y node_exporter enviando métricas a ese Prometheus.
- Para el email, una cuenta SMTP (servidor, puerto, usuario y contraseña). Para Slack, una URL de webhook entrante.
Notalos nombres de los menús de esta guía corresponden a Grafana 11 y 12. En las versiones recientes, Alerting está dentro de la sección Alerts & IRM del menú lateral.
Cómo funciona Grafana Alerting
Una alerta recorre cuatro piezas:
| Pieza | Función |
|---|---|
| Regla de alerta | Consulta, condición y tiempo de espera. Se guarda en una carpeta y un grupo de evaluación que fija cada cuánto se evalúa |
| Etiquetas | Pares clave-valor en la regla (por ejemplo severity=critical) que deciden a dónde va la notificación |
| Política de notificación | Árbol de reglas de enrutamiento: según las etiquetas, elige un punto de contacto y cómo agrupar y repetir los avisos |
| Punto de contacto | El destino final: email, Slack, PagerDuty, webhook, Telegram, etc. |
Cada regla pasa por estos estados: Normal (la condición no se cumple), Pending (se cumple, pero aún no ha pasado el tiempo de espera), Alerting o Firing (se cumple durante todo ese tiempo y se notifica), No Data (la consulta no devuelve datos) y Error (la consulta falla).
Paso 1: Configurar el envío de correo
Grafana no envía correo hasta que configuras un servidor SMTP. Abre su configuración:
sudo nano /etc/grafana/grafana.ini
Busca la sección [smtp], que viene comentada, y déjala así, sustituyendo los valores por los de tu proveedor:
[smtp]
enabled = true
host = smtp.your_domain:587
user = alertas@your_domain
password = """your_smtp_password"""
from_address = alertas@your_domain
from_name = Grafana
startTLS_policy = MandatoryStartTLS
Las comillas triples en password evitan que Grafana interprete como comentario un # o un ; dentro de la contraseña. Con el puerto 587, MandatoryStartTLS obliga a cifrar la conexión.
Reinicia Grafana y comprueba que arranca sin errores:
sudo systemctl restart grafana-server
sudo systemctl status grafana-server --no-pager
● grafana-server.service - Grafana instance
Loaded: loaded (/usr/lib/systemd/system/grafana-server.service; enabled; preset: enabled)
Active: active (running) since ...
Paso 2: Crear los puntos de contacto
Crearás dos: uno de email para los avisos normales y uno de Slack para lo crítico.
- En Grafana, ve a Alerting > Contact points y pulsa + Add contact point.
- En Name, escribe
equipo-email. - En Integration, elige Email y en Addresses escribe
ops@your_domain(puedes poner varias direcciones separadas por;). - Pulsa Test y después Send test notification. Debe llegarte un correo de prueba en menos de un minuto.
- Pulsa Save contact point.
Repite el proceso para Slack:
- + Add contact point, con el nombre
guardia-slack. - En Integration, elige Slack y pega la URL del webhook en Webhook URL.
- Pulsa Test para comprobar que el mensaje aparece en el canal, y guarda.
Si la prueba de email falla, el motivo exacto está en el log de Grafana:
sudo grep -i smtp /var/log/grafana/grafana.log | tail -5
Paso 3: Definir las políticas de notificación
La política por defecto recibe todas las alertas que no coincidan con ninguna política anidada. Ve a Alerting > Notification policies:
- En Default policy, pulsa More > Edit, elige
equipo-emailcomo punto de contacto y guarda. - Pulsa + New child policy (o New nested policy) bajo la política por defecto.
- En el emparejador (matcher) escribe
severity=critical. - Elige
guardia-slackcomo punto de contacto. - Activa Override general timings y pon Repeat interval a
1h, para que una alerta crítica que siga activa se recuerde cada hora en lugar de cada 4 horas. - Guarda la política.
Tres tiempos controlan el ruido de las notificaciones:
- Group wait (30 s por defecto): cuánto espera Grafana antes de enviar el primer aviso de un grupo nuevo, para juntar alertas que saltan a la vez.
- Group interval (5 min): cada cuánto se envía un aviso si cambian las alertas de un grupo ya notificado.
- Repeat interval (4 h): cada cuánto se repite el aviso si nada ha cambiado y la alerta sigue activa.
Paso 4: Crear la regla "Target caído"
Esta regla usa la métrica up que Prometheus genera para cada destino: vale 1 si el último scrape funcionó y 0 si no.
- Ve a Alerting > Alert rules y pulsa + New alert rule.
- En Enter alert rule name, escribe
Target caído. - En Define query and alert condition, elige tu fuente de datos Prometheus, cambia el editor a Code y escribe la consulta:
up
- En la condición de alerta (Alert condition), indica que se dispare cuando la consulta esté por debajo de 1 (IS BELOW
1). Pulsa Preview o Run queries: verás una fila por cada destino con su estado actual, que debería ser Normal. - En Add folder and labels, crea la carpeta
Alertasy añade la etiquetaseveritycon valorcritical. - En Set evaluation behavior, crea un grupo de evaluación llamado
infraestructuracon intervalo1my fija el periodo pendiente (Pending period) en2m. La regla solo notificará si el destino lleva caído dos evaluaciones seguidas. - En Configure notifications, deja la opción de usar las políticas de notificación, de modo que la etiqueta
severity=criticalla envíe a Slack. - En Configure notification message, escribe en Summary:
{{ $labels.instance }} ({{ $labels.job }}) no responde
- Pulsa Save rule and exit.
La regla genera una instancia de alerta por cada serie que devuelve la consulta. Si tienes diez destinos, cada uno tiene su propio estado y su propia notificación, con la etiqueta instance que lo identifica.
Paso 5: Crear la regla "Disco casi lleno"
Crea una segunda regla con el mismo procedimiento y estos valores:
- Nombre:
Disco casi lleno. - Consulta (calcula el porcentaje libre de cada sistema de archivos, ignorando los temporales):
100 * node_filesystem_avail_bytes{fstype!~"tmpfs|overlay"} / node_filesystem_size_bytes{fstype!~"tmpfs|overlay"}
- Condición: IS BELOW
10. - Carpeta
Alertas, etiquetaseveritycon valorwarning(irá al email mediante la política por defecto). - Grupo
infraestructuray periodo pendiente de10m. Un disco no se llena en segundos, así que no hace falta reaccionar a picos breves. - Summary:
Queda menos del 10 % de espacio en {{ $labels.mountpoint }} de {{ $labels.instance }}.
En Configure no data and error handling, cambia Alert state if no data a Normal (u OK). Si un servidor deja de enviar métricas ya te avisará la regla Target caído, y así evitas un segundo aviso por lo mismo.
Paso 6: Probar las alertas y silenciarlas
La forma más fiable de probar el circuito completo es provocar una alerta real en un servidor de pruebas. Detén node_exporter (si lo instalaste desde el paquete de Ubuntu, el servicio se llama prometheus-node-exporter):
sudo systemctl stop prometheus-node-exporter
En Alerting > Alert rules, la regla Target caído pasará a Pending en la siguiente evaluación y a Firing unos dos minutos después. Deberías recibir el mensaje en Slack. Vuelve a arrancar el servicio:
sudo systemctl start prometheus-node-exporter
En la siguiente evaluación, la alerta vuelve a Normal y Grafana envía una notificación de resolución (RESOLVED).
Para un mantenimiento programado, en lugar de pausar reglas crea un silencio: ve a Alerting > Silences, pulsa + New silence, añade un matcher como instance = your_server_ip:9100, elige la duración y guarda. Las alertas que coincidan se siguen evaluando, pero no se notifican hasta que el silencio caduque.
Paso 7: Gestionar las alertas como código
Configurar alertas a mano no escala ni deja historial de cambios. Grafana puede cargar puntos de contacto, políticas y reglas desde archivos YAML en /etc/grafana/provisioning/alerting/ al arrancar. Así puedes guardarlos en Git y desplegarlos igual en todos los entornos.
Importantelos recursos cargados desde archivos no se pueden editar desde la interfaz, y el archivo de políticas sustituye el árbol completo de políticas de notificación. Si ya creaste las del paso 3, las de este archivo las reemplazarán. Para migrar lo que ya tienes, cada regla, punto de contacto y política tiene la opción Export en la interfaz, que genera este mismo formato.
Necesitas el UID de tu fuente de datos Prometheus. Ve a Connections > Data sources, abre la fuente Prometheus y cópialo de la URL, que tiene la forma /connections/datasources/edit/<uid>.
Crea el directorio si no existe y el archivo de puntos de contacto:
sudo mkdir -p /etc/grafana/provisioning/alerting
sudo nano /etc/grafana/provisioning/alerting/contact-points.yaml
apiVersion: 1
contactPoints:
- orgId: 1
name: equipo-email
receivers:
- uid: equipo-email
type: email
settings:
addresses: ops@your_domain
singleEmail: true
- orgId: 1
name: guardia-slack
receivers:
- uid: guardia-slack
type: slack
settings:
url: https://hooks.slack.com/services/your_webhook_path
Crea el de políticas:
sudo nano /etc/grafana/provisioning/alerting/policies.yaml
apiVersion: 1
policies:
- orgId: 1
receiver: equipo-email
group_by: ["grafana_folder", "alertname"]
group_wait: 30s
group_interval: 5m
repeat_interval: 4h
routes:
- receiver: guardia-slack
object_matchers:
- ["severity", "=", "critical"]
repeat_interval: 1h
Y el de reglas, sustituyendo your_prometheus_uid por el UID que copiaste:
sudo nano /etc/grafana/provisioning/alerting/rules.yaml
apiVersion: 1
groups:
- orgId: 1
name: infraestructura
folder: Alertas
interval: 1m
rules:
- uid: target-caido
title: Target caído
condition: C
data:
- refId: A
relativeTimeRange:
from: 300
to: 0
datasourceUid: your_prometheus_uid
model:
refId: A
expr: up
- refId: B
datasourceUid: __expr__
model:
refId: B
type: reduce
expression: A
reducer: last
settings:
mode: dropNN
- refId: C
datasourceUid: __expr__
model:
refId: C
type: threshold
expression: B
conditions:
- evaluator:
type: lt
params: [1]
for: 2m
noDataState: NoData
execErrState: Error
labels:
severity: critical
annotations:
summary: "{{ $labels.instance }} ({{ $labels.job }}) no responde"
- uid: disco-casi-lleno
title: Disco casi lleno
condition: C
data:
- refId: A
relativeTimeRange:
from: 300
to: 0
datasourceUid: your_prometheus_uid
model:
refId: A
expr: 100 * node_filesystem_avail_bytes{fstype!~"tmpfs|overlay"} / node_filesystem_size_bytes{fstype!~"tmpfs|overlay"}
- refId: B
datasourceUid: __expr__
model:
refId: B
type: reduce
expression: A
reducer: last
settings:
mode: dropNN
- refId: C
datasourceUid: __expr__
model:
refId: C
type: threshold
expression: B
conditions:
- evaluator:
type: lt
params: [10]
for: 10m
noDataState: OK
execErrState: Error
labels:
severity: warning
annotations:
summary: "Queda menos del 10 % de espacio en {{ $labels.mountpoint }} de {{ $labels.instance }}"
description: 'Espacio libre actual: {{ printf "%.1f" $values.B.Value }} %.'
Cada regla tiene tres pasos encadenados: A es la consulta a Prometheus sobre los últimos 5 minutos (relativeTimeRange en segundos), B reduce cada serie a su último valor descartando los no numéricos (dropNN), y C compara ese valor con el umbral. condition: C indica qué paso decide si la regla se dispara. En las anotaciones, $values.B.Value da acceso al valor calculado en el paso B.
El archivo de contactos contiene la URL secreta del webhook, así que restringe los permisos para que solo root y el usuario grafana puedan leerlos:
sudo chown root:grafana /etc/grafana/provisioning/alerting/*.yaml
sudo chmod 640 /etc/grafana/provisioning/alerting/*.yaml
Reinicia Grafana para cargar los archivos y busca errores de provisioning en el log:
sudo systemctl restart grafana-server
sudo grep -i provisioning /var/log/grafana/grafana.log | tail -10
Si hay un error de formato, el log indica el archivo y el motivo, y Grafana no aplica ese archivo. Si todo es correcto, en Alerting > Alert rules verás las dos reglas en la carpeta Alertas con la marca Provisioned.
Solución de problemas
La regla está en estado No Data. La consulta no devuelve series. Ejecútala en Explore con la misma fuente de datos; lo habitual es un error en el nombre de la métrica o en un filtro de etiquetas. Si la ausencia de datos es normal para esa regla, cambia su estado de No Data a Normal.
La regla está en estado Error. La consulta falla: Prometheus no responde o el UID de la fuente de datos es incorrecto. El detalle aparece al abrir la regla, en la pestaña de historial de estados.
La regla está en Firing, pero no llega la notificación. Abre Alerting > Notification policies y comprueba a qué política llega una alerta con esas etiquetas. Si el problema es el punto de contacto, usa su botón Test y revisa /var/log/grafana/grafana.log.
Los correos no llegan (dial tcp ... i/o timeout). Muchos proveedores de cloud bloquean la salida por el puerto 25. Usa el puerto de envío 587 con STARTTLS o el 465 con TLS de tu proveedor de correo.
Se reciben avisos repetidos de lo mismo. Revisa el group_by de la política: agrupar por alertname y grafana_folder junta todas las instancias de una regla en un único mensaje. Sube también el Repeat interval si las repeticiones son demasiado frecuentes.
Conclusión
Tienes Grafana Alerting enviando alertas por email y Slack según su gravedad, con dos reglas sobre Prometheus que cubren caídas de servidores y discos llenos, silencios para los mantenimientos y la misma configuración definida en archivos YAML versionables. Como siguientes pasos, puedes añadir reglas sobre otros exportadores (bases de datos, Blackbox Exporter), crear plantillas de notificación para dar formato a los mensajes o enlazar cada regla con el panel correspondiente de un dashboard para abrir el contexto directamente desde el aviso.
