Arquitectura de monitorización bare-metal con Prometheus y Grafana
Prometheus recopila métricas numéricas de series temporales mediante endpoints HTTP, normalmente cada 15 a 60 segundos. Grafana consulta Prometheus y convierte esas métricas en paneles, gráficos, tablas y alertas. Node Exporter expone métricas de hosts Linux como uso de CPU, presión de memoria, espacio en disco, E/S del sistema de archivos, carga media y rendimiento de red.
Para la monitorización en producción, ejecute Prometheus y Grafana en un servidor bare-metal dedicado si la monitorización es crítica para el negocio, la retención supera los 30 días o espera monitorizar más de 100 sistemas. Un VPS es adecuado para un laboratorio pequeño, unos pocos sitios web o menos de 20 destinos de bajo volumen. El bare metal proporciona una E/S de disco predecible y evita problemas de vecinos ruidosos durante la compactación de Prometheus.
Esta configuración utiliza un servidor de monitorización y varios servidores Linux monitorizados:
- Prometheus: almacena métricas y evalúa reglas de alerta en el puerto 9090.
- Node Exporter: expone métricas del host en el puerto 9100.
- Grafana: proporciona paneles en el puerto 3000 detrás de Nginx.
- Alertmanager: agrupa y enruta alertas en el puerto 9093.
- Nginx: publica Grafana de forma segura mediante HTTPS.
Requisitos previos y dimensionamiento del servidor
Utilice una instalación limpia de Ubuntu Server 24.04 LTS con una dirección IP pública estática. Los comandos siguientes requieren un usuario no root con acceso sudo. Abra los puertos TCP 22, 80 y 443 a Internet solo si es necesario. Mantenga privados los puertos 9090 de Prometheus, 9093 de Alertmanager y 9100 de Node Exporter siempre que sea posible.
- Sistema operativo: Ubuntu Server 24.04 LTS x86_64
- Servidor de monitorización mínimo: 4 núcleos de CPU, 8 GB de RAM, SSD NVMe de 160 GB
- Servidor de producción recomendado: 8 núcleos de CPU, 32 GB de RAM, SSD NVMe de 960 GB
- Intervalo de scraping utilizado aquí: 15 segundos
- Retención de Prometheus utilizada aquí: 30 días
- Registro DNS requerido: un registro A o AAAA como
grafana.example.com
La capacidad de disco es el recurso limitante para la mayoría de las implementaciones de Prometheus. Un intervalo de scraping de 15 segundos produce 5.760 muestras por métrica cada día. Las métricas de menor cardinalidad, como las estadísticas de CPU, memoria y disco, consumen pocos recursos; las etiquetas que contienen ID de usuario, ID de solicitud, direcciones IP, hashes de contenedores o URL con rutas dinámicas pueden consumir rápidamente almacenamiento y memoria.
Dimensionamiento de producción según el número de hosts monitorizados
Para una retención de 30 días, un intervalo de scraping de 15 segundos y métricas estándar de Node Exporter, dimensione el servidor de monitorización de la siguiente manera.
Conclusión: Comience con 8 núcleos de CPU, 32 GB de RAM y 960 GB de NVMe para unos 100 servidores Linux; aumente la capacidad de disco antes de reducir el periodo de retención.
| Hosts Linux monitorizados | vCPU / núcleos de CPU | RAM | Disco | Ancho de banda mensual |
|---|---|---|---|---|
| 1-20 hosts | 4 núcleos | 8 GB | 160 GB NVMe | 1 TB |
| 21-150 hosts | 8 núcleos | 32 GB | 960 GB NVMe | 3 TB |
| 151-500 hosts | 16 núcleos | 64 GB | 2 × 1,92 TB NVMe en RAID 1 | 8 TB |
Estas cifras cubren métricas del sistema operativo y una cantidad moderada de métricas de aplicaciones. Añada capacidad para métricas de MySQL, PostgreSQL, Redis, servidores de correo, servidores de juegos, Kubernetes, CI/CD, streaming o sondas blackbox. Para más de 500 hosts, retención durante varios años o telemetría de aplicaciones de alta cardinalidad, utilice la federación de Prometheus o una plataforma de métricas a largo plazo como Thanos, Mimir o VictoriaMetrics.
Paso 1: Prepare el servidor bare-metal
Actualice los paquetes, establezca la zona horaria, instale las utilidades necesarias y habilite el firewall uncomplicated. Sustituya UTC por su zona horaria preferida si es necesario.
sudo apt update && sudo apt -y upgrade
sudo timedatectl set-timezone UTC
sudo apt install -y curl wget tar gnupg2 ca-certificates apt-transport-https nginx ufw
sudo ufw allow OpenSSH
sudo ufw allow 'Nginx Full'
sudo ufw enable
sudo ufw status
Cree un directorio dedicado para los datos de Prometheus. Se recomienda almacenamiento NVMe porque Prometheus escribe continuamente un registro de transacciones y compacta periódicamente los bloques de series temporales.
sudo mkdir -p /var/lib/prometheus
sudo mkdir -p /etc/prometheus/rules
sudo useradd --no-create-home --shell /usr/sbin/nologin prometheus
sudo chown -R prometheus:prometheus /var/lib/prometheus /etc/prometheus
Paso 2: Instale Prometheus
Descargue Prometheus 2.53.4 para Linux AMD64, instale sus binarios y cree un servicio systemd. Confirme la versión de lanzamiento en la página de versiones de Prometheus en GitHub antes de actualizar posteriormente; realice los cambios de versión de forma deliberada y probada.
cd /tmp
PROM_VERSION=2.53.4
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
sudo install -m 0755 prometheus-${PROM_VERSION}.linux-amd64/prometheus /usr/local/bin/prometheus
sudo install -m 0755 prometheus-${PROM_VERSION}.linux-amd64/promtool /usr/local/bin/promtool
sudo cp -r prometheus-${PROM_VERSION}.linux-amd64/consoles /etc/prometheus/
sudo cp -r prometheus-${PROM_VERSION}.linux-amd64/console_libraries /etc/prometheus/
sudo chown -R prometheus:prometheus /etc/prometheus
Cree /etc/prometheus/prometheus.yml. Sustituya 10.20.0.11 y 10.20.0.12 por las direcciones IP privadas de los hosts monitorizados. Las direcciones de red privadas evitan exponer Node Exporter a Internet.
sudo tee /etc/prometheus/prometheus.yml > /dev/null <<'EOF'
global:
scrape_interval: 15s
evaluation_interval: 15s
external_labels:
environment: production
site: bare-metal-1
alerting:
alertmanagers:
- static_configs:
- targets: ['127.0.0.1:9093']
rule_files:
- /etc/prometheus/rules/*.yml
scrape_configs:
- job_name: prometheus
static_configs:
- targets: ['127.0.0.1:9090']
- job_name: node
static_configs:
- targets:
- '127.0.0.1:9100'
- '10.20.0.11:9100'
- '10.20.0.12:9100'
EOF
sudo chown prometheus:prometheus /etc/prometheus/prometheus.yml
Cree e inicie la unidad systemd de Prometheus con una retención de 30 días. El ajuste --storage.tsdb.retention.time=30d limita los bloques conservados por antigüedad; utilice también un límite de tamaño para evitar que los datos de monitorización llenen el volumen del servidor.
sudo tee /etc/systemd/system/prometheus.service > /dev/null <<'EOF'
[Unit]
Description=Prometheus Monitoring
Wants=network-online.target
After=network-online.target
[Service]
User=prometheus
Group=prometheus
Type=simple
ExecStart=/usr/local/bin/prometheus \
--config.file=/etc/prometheus/prometheus.yml \
--storage.tsdb.path=/var/lib/prometheus \
--storage.tsdb.retention.time=30d \
--storage.tsdb.retention.size=120GB \
--web.listen-address=127.0.0.1:9090
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl daemon-reload
sudo systemctl enable --now prometheus
sudo systemctl status prometheus --no-pager
Paso 3: Instale Node Exporter en cada servidor Linux monitorizado
Ejecute esta sección en el servidor de Prometheus y en cada máquina de destino. Node Exporter escucha en el puerto 9100. Vincúlelo a una IP privada o utilice reglas de firewall para que solo el servidor de Prometheus pueda conectarse.
cd /tmp
NODE_VERSION=1.8.2
sudo useradd --no-create-home --shell /usr/sbin/nologin node_exporter
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 install -m 0755 node_exporter-${NODE_VERSION}.linux-amd64/node_exporter /usr/local/bin/node_exporter
sudo tee /etc/systemd/system/node_exporter.service > /dev/null <<'EOF'
[Unit]
Description=Prometheus Node Exporter
Wants=network-online.target
After=network-online.target
[Service]
User=node_exporter
Group=node_exporter
Type=simple
ExecStart=/usr/local/bin/node_exporter --web.listen-address=:9100
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl daemon-reload
sudo systemctl enable --now node_exporter
curl -s http://127.0.0.1:9100/metrics | head
En cada host monitorizado, permita el puerto 9100 únicamente desde la dirección privada del servidor de Prometheus. Sustituya 10.20.0.10 por la dirección del servidor de monitorización.
sudo ufw allow from 10.20.0.10 to any port 9100 proto tcp
sudo ufw status numbered
Paso 4: Añada reglas de alerta y Alertmanager
Cree alertas para un host inaccesible, CPU elevada sostenida, poco espacio en disco y poca memoria disponible. Las alertas deben identificar una condición que requiera acción, no cada pico transitorio.
sudo tee /etc/prometheus/rules/host-alerts.yml > /dev/null <<'EOF'
groups:
- name: host-alerts
rules:
- alert: HostDown
expr: up{job="node"} == 0
for: 2m
labels:
severity: critical
annotations:
summary: "Host {{ $labels.instance }} is unreachable"
- alert: HighCPUUsage
expr: 100 - (avg by(instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) > 90
for: 10m
labels:
severity: warning
annotations:
summary: "CPU usage exceeds 90% on {{ $labels.instance }}"
- alert: LowDiskSpace
expr: (node_filesystem_avail_bytes{fstype!~"tmpfs|overlay"} / node_filesystem_size_bytes{fstype!~"tmpfs|overlay"}) * 100 < 10
for: 10m
labels:
severity: critical
annotations:
summary: "Less than 10% disk space remains on {{ $labels.instance }}"
- alert: LowAvailableMemory
expr: node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes * 100 < 10
for: 10m
labels:
severity: warning
annotations:
summary: "Available memory is below 10% on {{ $labels.instance }}"
EOF
sudo chown prometheus:prometheus /etc/prometheus/rules/host-alerts.yml
sudo promtool check config /etc/prometheus/prometheus.yml
sudo systemctl restart prometheus
Instale Alertmanager y comience con un receptor local. Sustituya la configuración del receptor por un relé SMTP debidamente protegido, un webhook, un endpoint compatible con Slack o una integración con PagerDuty después de validar la entrega de alertas.
cd /tmp
ALERT_VERSION=0.27.0
wget https://github.com/prometheus/alertmanager/releases/download/v${ALERT_VERSION}/alertmanager-${ALERT_VERSION}.linux-amd64.tar.gz
tar -xzf alertmanager-${ALERT_VERSION}.linux-amd64.tar.gz
sudo useradd --no-create-home --shell /usr/sbin/nologin alertmanager
sudo install -m 0755 alertmanager-${ALERT_VERSION}.linux-amd64/alertmanager /usr/local/bin/alertmanager
sudo mkdir -p /etc/alertmanager /var/lib/alertmanager
sudo chown -R alertmanager:alertmanager /etc/alertmanager /var/lib/alertmanager
sudo tee /etc/alertmanager/alertmanager.yml > /dev/null <<'EOF'
route:
receiver: local-log
group_by: ['alertname', 'instance']
group_wait: 30s
group_interval: 5m
repeat_interval: 4h
receivers:
- name: local-log
EOF
sudo tee /etc/systemd/system/alertmanager.service > /dev/null <<'EOF'
[Unit]
Description=Prometheus Alertmanager
After=network-online.target
[Service]
User=alertmanager
Group=alertmanager
ExecStart=/usr/local/bin/alertmanager --config.file=/etc/alertmanager/alertmanager.yml --storage.path=/var/lib/alertmanager --web.listen-address=127.0.0.1:9093
Restart=always
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl daemon-reload
sudo systemctl enable --now alertmanager
Paso 5: Instale Grafana
Instale Grafana desde su repositorio APT firmado. Grafana escucha únicamente en localhost porque Nginx gestionará el acceso HTTPS público.
sudo mkdir -p /etc/apt/keyrings
wget -q -O - https://apt.grafana.com/gpg.key | sudo gpg --dearmor -o /etc/apt/keyrings/grafana.gpg
echo "deb [signed-by=/etc/apt/keyrings/grafana.gpg] https://apt.grafana.com stable main" | sudo tee /etc/apt/sources.list.d/grafana.list
sudo apt update
sudo apt install -y grafana
sudo sed -i 's/^;http_addr =.*/http_addr = 127.0.0.1/' /etc/grafana/grafana.ini
sudo systemctl enable --now grafana-server
sudo systemctl status grafana-server --no-pager
Inicie sesión inicialmente mediante el servicio local usando un túnel SSH en lugar de exponer el puerto 3000:
ssh -L 3000:127.0.0.1:3000 youruser@YOUR_SERVER_IP
Abra http://localhost:3000, inicie sesión con admin y admin y cambie la contraseña inmediatamente. Añada una fuente de datos de Prometheus con la URL http://127.0.0.1:9090. Importe el ID de panel 1860 para el popular panel Node Exporter Full y, a continuación, seleccione la fuente de datos de Prometheus.
Paso 6: Publique Grafana mediante Nginx y HTTPS
Configure el DNS de grafana.example.com para que apunte a este servidor antes de solicitar un certificado. Sustituya el dominio en la configuración y en el comando de Certbot.
sudo tee /etc/nginx/sites-available/grafana > /dev/null <<'EOF'
server {
listen 80;
server_name grafana.example.com;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
EOF
sudo ln -s /etc/nginx/sites-available/grafana /etc/nginx/sites-enabled/grafana
sudo rm -f /etc/nginx/sites-enabled/default
sudo nginx -t
sudo systemctl reload nginx
sudo apt install -y certbot python3-certbot-nginx
sudo certbot --nginx -d grafana.example.com --redirect --agree-tos -m [email protected]
sudo systemctl status certbot.timer --no-pager
Cree usuarios individuales de Grafana o conecte un proveedor de identidad; no comparta la cuenta de administrador predeterminada. Desactive el acceso anónimo salvo que los paneles sean intencionadamente públicos.
Paso 7: Verifique la recopilación, el almacenamiento y las alertas
Compruebe que Prometheus considera en buen estado cada destino. Un estado de destino up igual a 1 indica que está disponible; 0 significa que Prometheus no puede realizar el scraping del endpoint.
curl -s http://127.0.0.1:9090/api/v1/query?query=up
curl -s http://127.0.0.1:9090/api/v1/targets | grep -o 'health":"[^"]*' | sort | uniq -c
sudo promtool check rules /etc/prometheus/rules/host-alerts.yml
sudo systemctl --no-pager --full status prometheus node_exporter alertmanager grafana-server nginx
En Grafana Explore, ejecute estas consultas PromQL:
up{job="node"}
100 - (avg by(instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100)
node_memory_MemAvailable_bytes / 1024 / 1024
node_filesystem_avail_bytes{mountpoint="/"} / 1024 / 1024 / 1024
Pruebe la alerta HostDown de forma segura deteniendo Node Exporter en un host no crítico durante más de dos minutos y, después, restáurelo.
sudo systemctl stop node_exporter
# Espere al menos 2 minutos, inspeccione Alertas en Prometheus y, después, restáurelo:
sudo systemctl start node_exporter
Solución de problemas habituales de Prometheus y Grafana
El destino aparece como DOWN en Prometheus
Compruebe el servicio de destino, el firewall y la ruta desde el servidor de Prometheus. El siguiente comando debe devolver métricas del servidor de monitorización. Si se agota el tiempo de espera, permita TCP 9100 únicamente desde la IP privada de Prometheus y verifique que la dirección del destino en prometheus.yml sea correcta.
curl -v http://10.20.0.11:9100/metrics
sudo systemctl status node_exporter --no-pager
sudo ss -lntp | grep 9100
Prometheus consume demasiado disco o RAM
Compruebe las series activas, el consumo de disco y la configuración de retención. Evite las etiquetas con valores ilimitados. Reducir la retención de 30 a 15 días es más seguro que permitir que el sistema de archivos se llene, pero añada capacidad NVMe para una carga de trabajo sostenida.
curl -s http://127.0.0.1:9090/api/v1/status/tsdb
sudo du -sh /var/lib/prometheus
sudo df -h /var/lib/prometheus
sudo journalctl -u prometheus -n 100 --no-pager
Grafana devuelve 502 Bad Gateway
Una respuesta 502 normalmente significa que Grafana está detenido, escucha en una dirección diferente o está bloqueado por un error de configuración. Compruebe ambos servicios y valide Nginx antes de volver a cargarlo.
sudo systemctl status grafana-server nginx --no-pager
sudo ss -lntp | grep 3000
sudo nginx -t
sudo journalctl -u grafana-server -n 100 --no-pager
Grafana no muestra datos
Confirme que la URL de la fuente de datos de Grafana sea http://127.0.0.1:9090, no una URL pública bloqueada por el firewall. En Prometheus, ejecute primero up. Si no se devuelve ninguna serie, corrija el scraping de Prometheus antes de cambiar las variables del panel.
Prácticas operativas para un servidor de monitorización fiable
- Realice copias de seguridad diarias de los paneles de Grafana, las fuentes de datos, las reglas de alerta y los archivos de configuración. Los datos de Prometheus pueden recrearse, pero las métricas históricas son valiosas durante las revisiones de incidentes.
- Monitorice el propio servidor de monitorización con Node Exporter, incluido el uso de disco, la memoria, la CPU y el estado del RAID.
- Utilice unidades NVMe en RAID 1 para los datos importantes de monitorización en producción. RAID no es una copia de seguridad.
- Parchee Ubuntu y actualice Prometheus, Grafana, Node Exporter y Alertmanager durante una ventana de mantenimiento programada.
- Utilice VLAN privadas, acceso VPN o listas de permitidos del firewall para los puertos de métricas. No exponga públicamente los endpoints de Node Exporter o Prometheus.
- Configure alertas para la caducidad de certificados, fallos de copias de seguridad, degradación del RAID y crecimiento del almacenamiento TSDB de Prometheus.