TL;DR — Resumen Rápido
Configura Prometheus con Node Exporter para monitorear servidores Linux. PromQL, reglas de alerta, Alertmanager, ajuste de almacenamiento y seguridad.
Prometheus es el estándar de facto para monitoreo de infraestructura open-source. Combinado con Node Exporter, brinda visibilidad profunda en cada servidor Linux de tu flota — uso de CPU, presión de memoria, saturación de disco, rendimiento de red y promedios de carga — todo consultable con un poderoso lenguaje de expresiones y alertable a través de Alertmanager. Esta guía cubre desde el metal desnudo hasta un stack de monitoreo listo para producción.
Requisitos Previos
- Ubuntu 22.04 o Debian 12 (idéntico en RHEL/Rocky sustituyendo
aptpordnf) - Acceso root o sudo
- Puertos 9090 (Prometheus), 9100 (Node Exporter) y 9093 (Alertmanager) abiertos en el firewall
- Familiaridad básica con systemd y YAML
Visión General de la Arquitectura
Prometheus utiliza un modelo pull: extrae endpoints HTTP llamados targets en un intervalo configurable y almacena los datos de series temporales localmente en una base de datos columnar (TSDB).
┌─────────────────────────────────────────────────────────┐
│ Servidor Linux │
│ │
│ Node Exporter :9100 ← Prometheus :9090 → Grafana │
│ ↑ ↓ │
│ /proc /sys TSDB en disco │
│ ↓ │
│ Alertmanager :9093 │
│ (email/Slack/PD) │
└─────────────────────────────────────────────────────────┘
Conceptos clave:
- Scrape — Prometheus obtiene
/metricsde cada target en elscrape_interval - TSDB — Base de datos de series temporales local; cada métrica es un float64 con timestamp y etiquetas
- PromQL — Lenguaje de consulta para agregar y calcular tasas sobre series temporales
- Alertmanager — Proceso separado que recibe alertas de Prometheus y enruta notificaciones
Paso 1: Instalar Prometheus
Crear usuario del sistema y directorios
sudo useradd --system --no-create-home --shell /bin/false prometheus
sudo mkdir -p /etc/prometheus /var/lib/prometheus
sudo chown prometheus:prometheus /etc/prometheus /var/lib/prometheus
Descargar e instalar el binario
PROM_VERSION="2.51.2"
cd /tmp
wget "https://github.com/prometheus/prometheus/releases/download/v${PROM_VERSION}/prometheus-${PROM_VERSION}.linux-amd64.tar.gz"
tar xzf prometheus-${PROM_VERSION}.linux-amd64.tar.gz
cd prometheus-${PROM_VERSION}.linux-amd64
sudo cp prometheus promtool /usr/local/bin/
sudo chown prometheus:prometheus /usr/local/bin/prometheus /usr/local/bin/promtool
sudo cp -r consoles console_libraries /etc/prometheus/
sudo chown -R prometheus:prometheus /etc/prometheus/consoles /etc/prometheus/console_libraries
Escribir prometheus.yml
global:
scrape_interval: 15s
evaluation_interval: 15s
external_labels:
environment: "production"
rule_files:
- /etc/prometheus/rules/*.yml
alerting:
alertmanagers:
- static_configs:
- targets: ["localhost:9093"]
scrape_configs:
- job_name: "prometheus"
static_configs:
- targets: ["localhost:9090"]
- job_name: "node"
static_configs:
- targets: ["localhost:9100"]
labels:
instance: "web-01"
sudo chown prometheus:prometheus /etc/prometheus/prometheus.yml
promtool check config /etc/prometheus/prometheus.yml
Crear la unidad systemd
[Unit]
Description=Sistema de Monitoreo Prometheus
After=network.target
[Service]
Type=simple
User=prometheus
Group=prometheus
ExecStart=/usr/local/bin/prometheus \
--config.file=/etc/prometheus/prometheus.yml \
--storage.tsdb.path=/var/lib/prometheus \
--storage.tsdb.retention.time=30d \
--web.listen-address=0.0.0.0:9090 \
--web.enable-lifecycle
Restart=on-failure
RestartSec=5s
NoNewPrivileges=true
ProtectSystem=strict
ReadWritePaths=/var/lib/prometheus
[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable --now prometheus
Paso 2: Instalar Node Exporter
Node Exporter expone métricas de hardware y SO desde /proc y /sys en el puerto 9100.
NODE_VERSION="1.7.0"
cd /tmp
wget "https://github.com/prometheus/node_exporter/releases/download/v${NODE_VERSION}/node_exporter-${NODE_VERSION}.linux-amd64.tar.gz"
tar xzf node_exporter-${NODE_VERSION}.linux-amd64.tar.gz
sudo useradd --system --no-create-home --shell /bin/false node_exporter
sudo cp node_exporter-${NODE_VERSION}.linux-amd64/node_exporter /usr/local/bin/
sudo chown node_exporter:node_exporter /usr/local/bin/node_exporter
[Unit]
Description=Prometheus Node Exporter
After=network.target
[Service]
Type=simple
User=node_exporter
Group=node_exporter
ExecStart=/usr/local/bin/node_exporter \
--collector.systemd \
--collector.processes
Restart=on-failure
NoNewPrivileges=true
ProtectSystem=strict
[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable --now node_exporter
curl -s http://localhost:9100/metrics | head -20
Métricas Clave de Node Exporter
| Métrica | Descripción |
|---|---|
node_cpu_seconds_total | Tiempo de CPU por modo (user, system, idle) — usar con rate() |
node_memory_MemAvailable_bytes | Memoria disponible (incluye caché reclaimable) |
node_memory_MemTotal_bytes | Memoria física total |
node_filesystem_avail_bytes | Espacio libre en disco |
node_network_receive_bytes_total | Bytes recibidos por interfaz — usar con rate() |
node_load1 / node_load5 / node_load15 | Promedios de carga del sistema |
node_disk_io_time_seconds_total | Tiempo en I/O — usar rate() para saturación |
Fundamentos de PromQL
Abre la UI de Prometheus en http://tu-servidor:9090 para experimentar.
Uso de CPU en porcentaje
100 - (avg by (instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100)
Uso de memoria en porcentaje
(1 - (node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes)) * 100
Uso de disco en porcentaje
(1 - (node_filesystem_avail_bytes{fstype!~"tmpfs|devtmpfs"} / node_filesystem_size_bytes)) * 100
Funciones principales de PromQL
| Función | Propósito |
|---|---|
rate() | Tasa por segundo promediada sobre un rango |
increase() | Incremento total en un rango |
histogram_quantile() | Latencia P99 desde una métrica de histograma |
avg by() | Promedio en una dimensión |
topk() | Las N series más altas por valor |
predict_linear() | Predice el valor en N segundos |
Reglas de Alerta
# /etc/prometheus/rules/alerts.yml
groups:
- name: node_alerts
interval: 30s
rules:
- alert: AltoCPU
expr: 100 - (avg by (instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) > 85
for: 5m
labels:
severity: warning
annotations:
summary: "Alto uso de CPU en {{ $labels.instance }}"
description: "Uso de CPU: {{ $value | printf \"%.1f\" }}% por más de 5 minutos."
- alert: PocoEspacioEnDisco
expr: (node_filesystem_avail_bytes{fstype!~"tmpfs|devtmpfs"} / node_filesystem_size_bytes) * 100 < 15
for: 5m
labels:
severity: warning
annotations:
summary: "Poco espacio en disco en {{ $labels.instance }}"
description: "Partición {{ $labels.mountpoint }} tiene {{ $value | printf \"%.1f\" }}% libre."
- alert: InstanciaInaccesible
expr: up == 0
for: 1m
labels:
severity: critical
annotations:
summary: "Instancia {{ $labels.instance }} inaccesible"
description: "{{ $labels.job }}/{{ $labels.instance }} lleva 1 minuto sin responder."
- alert: AltoUsoMemoria
expr: (1 - (node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes)) * 100 > 90
for: 5m
labels:
severity: warning
annotations:
summary: "Alto uso de memoria en {{ $labels.instance }}"
description: "Uso de memoria: {{ $value | printf \"%.1f\" }}%."
sudo mkdir -p /etc/prometheus/rules
sudo chown -R prometheus:prometheus /etc/prometheus/rules
promtool check rules /etc/prometheus/rules/alerts.yml
sudo systemctl reload prometheus
Configuración de Alertmanager
Instalar Alertmanager
AM_VERSION="0.27.0"
cd /tmp
wget "https://github.com/prometheus/alertmanager/releases/download/v${AM_VERSION}/alertmanager-${AM_VERSION}.linux-amd64.tar.gz"
tar xzf alertmanager-${AM_VERSION}.linux-amd64.tar.gz
sudo useradd --system --no-create-home --shell /bin/false alertmanager
sudo mkdir -p /etc/alertmanager /var/lib/alertmanager
sudo cp alertmanager-${AM_VERSION}.linux-amd64/alertmanager /usr/local/bin/
sudo chown alertmanager:alertmanager /usr/local/bin/alertmanager /etc/alertmanager /var/lib/alertmanager
Configurar rutas de notificación
# /etc/alertmanager/alertmanager.yml
global:
slack_api_url: "https://hooks.slack.com/services/TU/WEBHOOK/AQUI"
route:
group_by: ["alertname", "instance"]
group_wait: 30s
group_interval: 5m
repeat_interval: 4h
receiver: "equipo-ops"
routes:
- match:
severity: critical
receiver: "pagerduty"
receivers:
- name: "equipo-ops"
slack_configs:
- channel: "#alertas"
send_resolved: true
- name: "pagerduty"
pagerduty_configs:
- routing_key: "TU_CLAVE_PAGERDUTY"
send_resolved: true
inhibit_rules:
- source_match:
severity: critical
target_match:
severity: warning
equal: ["alertname", "instance"]
sudo systemctl daemon-reload
sudo systemctl enable --now alertmanager
Reglas de Grabación
Las reglas de grabación pre-calculan expresiones PromQL costosas y almacenan el resultado como una nueva métrica, acelerando los dashboards con muchos nodos.
# /etc/prometheus/rules/recording.yml
groups:
- name: node_recording
interval: 1m
rules:
- record: instance:node_cpu_usage:percent
expr: 100 - (avg by (instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100)
- record: instance:node_memory_usage:percent
expr: (1 - (node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes)) * 100
- record: instance:node_filesystem_usage:percent
expr: (1 - (node_filesystem_avail_bytes{fstype!~"tmpfs|devtmpfs"} / node_filesystem_size_bytes)) * 100
Ajuste de Almacenamiento
Prometheus TSDB comprime eficientemente — aproximadamente 1-2 bytes por muestra. Un servidor con 1.000 métricas cada 15 segundos acumula unos 2 GB por mes.
# Flags en el ExecStart del servicio prometheus:
--storage.tsdb.retention.time=90d
--storage.tsdb.retention.size=20GB
--storage.tsdb.wal-compression
du -sh /var/lib/prometheus/
Seguridad
Autenticación básica
# /etc/prometheus/web.yml
basic_auth_users:
admin: "$2y$10$tu-hash-bcrypt-aqui"
Proxy inverso con nginx
server {
listen 443 ssl;
server_name prometheus.ejemplo.com;
ssl_certificate /etc/letsencrypt/live/prometheus.ejemplo.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/prometheus.ejemplo.com/privkey.pem;
auth_basic "Prometheus";
auth_basic_user_file /etc/nginx/.prometheus-htpasswd;
location / {
proxy_pass http://127.0.0.1:9090;
}
}
Reglas de firewall
sudo ufw deny 9090
sudo ufw deny 9093
sudo ufw allow from 10.0.0.5 to any port 9100
Tabla Comparativa
| Característica | Prometheus | Zabbix | Nagios | Datadog | Netdata |
|---|---|---|---|---|---|
| Modelo | Pull (scrape) | Push/Pull | Pull | Push (agente) | Push |
| Almacenamiento | TSDB local | PostgreSQL/MySQL | Archivos planos | SaaS cloud | DB propia |
| Lenguaje de consulta | PromQL (potente) | Custom + SQL | Ninguno | DogStatsD | Custom |
| Dashboards | Grafana (externo) | Integrado | No nativo | Integrado | Integrado |
| Costo | Gratis / open-source | Gratis (enterprise pago) | Gratis (enterprise pago) | SaaS | Gratis (cloud pago) |
| Curva de aprendizaje | Moderada (PromQL) | Pronunciada | Pronunciada | Baja | Muy baja |
Stack de Producción
Servidor Prometheus (2 vCPU / 4 GB RAM):
- /var/lib/prometheus → volumen de datos separado (100 GB+)
- Retención: 30d tiempo O 20 GB tamaño
Node Exporter (en cada servidor):
- Servicio systemd, puerto 9100
- Firewall: permitir 9100 solo desde IP de Prometheus
Alertmanager:
- Slack para warnings, PagerDuty para critical
- Reglas de inhibición: suprimir warnings cuando critical está activo
Grafana (recomendado):
- docker run -d -p 3000:3000 grafana/grafana
- Importar dashboard ID 1860 (Node Exporter Full)
Errores Comunes
rate() requiere al menos dos muestras. Si un contador se reinicia (reinicio del proceso), rate() lo maneja correctamente. Usa rate() para reglas de alerta, no irate().
Explosión de cardinalidad. Nunca uses etiquetas de alta cardinalidad como user_id o request_url. Cada combinación única crea una serie temporal separada.
La cláusula for previene falsas alarmas. Una alerta con for: 5m debe estar activa 5 minutos continuos antes de enviar notificación.
Las reglas de grabación no tienen datos históricos. Después de agregar una regla de grabación, la nueva métrica solo existe desde ese momento.
El timeout de scrape debe ser menor que el intervalo. Si scrape_timeout supera scrape_interval, Prometheus registrará errores.
Resumen
- Prometheus usa un modelo pull — extrae endpoints
/metricsen un intervalo configurable - Node Exporter expone métricas de hardware y SO en el puerto 9100
- PromQL con
rate(),increase()yhistogram_quantile()forma la base de consultas útiles - Escribe reglas de alerta con cláusula
forpara evitar falsas alarmas; enruta por Alertmanager - Las reglas de grabación pre-calculan agregaciones costosas — críticas para dashboards multinodo
- Ajusta la retención de almacenamiento con
--storage.tsdb.retention.timeo--storage.tsdb.retention.size - Siempre pon Prometheus detrás de un proxy inverso con TLS y restringe acceso directo a puertos