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 apt por dnf)
  • 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 /metrics de cada target en el scrape_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étricaDescripción
node_cpu_seconds_totalTiempo de CPU por modo (user, system, idle) — usar con rate()
node_memory_MemAvailable_bytesMemoria disponible (incluye caché reclaimable)
node_memory_MemTotal_bytesMemoria física total
node_filesystem_avail_bytesEspacio libre en disco
node_network_receive_bytes_totalBytes recibidos por interfaz — usar con rate()
node_load1 / node_load5 / node_load15Promedios de carga del sistema
node_disk_io_time_seconds_totalTiempo 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ónPropó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ísticaPrometheusZabbixNagiosDatadogNetdata
ModeloPull (scrape)Push/PullPullPush (agente)Push
AlmacenamientoTSDB localPostgreSQL/MySQLArchivos planosSaaS cloudDB propia
Lenguaje de consultaPromQL (potente)Custom + SQLNingunoDogStatsDCustom
DashboardsGrafana (externo)IntegradoNo nativoIntegradoIntegrado
CostoGratis / open-sourceGratis (enterprise pago)Gratis (enterprise pago)SaaSGratis (cloud pago)
Curva de aprendizajeModerada (PromQL)PronunciadaPronunciadaBajaMuy 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 /metrics en un intervalo configurable
  • Node Exporter expone métricas de hardware y SO en el puerto 9100
  • PromQL con rate(), increase() y histogram_quantile() forma la base de consultas útiles
  • Escribe reglas de alerta con cláusula for para 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.time o --storage.tsdb.retention.size
  • Siempre pon Prometheus detrás de un proxy inverso con TLS y restringe acceso directo a puertos

Artículos Relacionados