Monitorización con Prometheus, Grafana y OpenTelemetry
Cuando hablamos de monitorización SysAdmin en entornos modernos, la combinación de Prometheus Grafana y OpenTelemetry se ha convertido en el estándar de facto. Ya no basta con instalar un agente SNMP o revisar logs a mano. Necesitamos un stack que permita recolectar métricas, trazas y logs de forma unificada, con capacidad de escalar horizontalmente y ofrecer alertas avanzadas sin depender de soluciones propietarias.
Este artículo es una guía completa para implementar este trío de herramientas en un servidor Linux. Cubriremos desde la instalación y configuración básica hasta la integración de OpenTelemetry para obtener visibilidad de extremo a extremo, pasando por dashboards en Grafana y alertas inteligentes con Prometheus.
¿Por qué Prometheus, Grafana y OpenTelemetry juntos?
Antes de entrar en materia, entendamos el papel de cada componente:
- Prometheus: Sistema de recolección y almacenamiento de métricas basado en un modelo de datos multidimensional (etiquetas). Destaca por su potente lenguaje de consultas (PromQL) y su capacidad de autodescubrimiento.
- Grafana: Herramienta de visualización y dashboards. Se conecta a Prometheus (y a cientos de otras fuentes) para crear paneles interactivos y compartibles.
- OpenTelemetry: Conjunto de APIs, SDKs y herramientas para generar, recolectar y exportar telemetría (métricas, trazas y logs). Es el pegamento que nos permite instrumentar aplicaciones sin atarnos a un vendor específico.
La magia ocurre cuando OpenTelemetry envía métricas a Prometheus (a través de exporters o el OTLP Receiver) y las trazas a sistemas como Jaeger o Tempo, todo visualizado en Grafana. Esto nos da una visión holística del sistema: desde la CPU del servidor hasta el tiempo de respuesta de una petición HTTP.
[INFO] OpenTelemetry es un proyecto de CNCF (Cloud Native Computing Foundation), al igual que Prometheus. Esta alineación garantiza compatibilidad y futuro.
Instalación del Stack en Linux
Vamos a instalar todo en un servidor Ubuntu 22.04 LTS. Usaremos Docker Compose para simplificar el despliegue, pero también veremos opciones bare-metal.
Requisitos previos
- Servidor Linux con Docker y Docker Compose instalados.
- Puertos abiertos: 9090 (Prometheus), 3000 (Grafana), 4318 (OpenTelemetry Collector).
- Acceso root o sudo.
Despliegue con Docker Compose
Creamos un directorio de trabajo y un archivo docker-compose.yml:
version: '3.8'
services:
prometheus:
image: prom/prometheus:latest
container_name: prometheus
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
- prometheus_data:/prometheus
command:
- '--config.file=/etc/prometheus/prometheus.yml'
- '--storage.tsdb.path=/prometheus'
ports:
- "9090:9090"
restart: unless-stopped
grafana:
image: grafana/grafana:latest
container_name: grafana
environment:
- GF_SECURITY_ADMIN_PASSWORD=admin123
volumes:
- grafana_data:/var/lib/grafana
ports:
- "3000:3000"
restart: unless-stopped
otel-collector:
image: otel/opentelemetry-collector-contrib:latest
container_name: otel-collector
command: ["--config=/etc/otel-collector-config.yml"]
volumes:
- ./otel-collector-config.yml:/etc/otel-collector-config.yml
ports:
- "4317:4317" # gRPC
- "4318:4318" # HTTP
restart: unless-stopped
volumes:
prometheus_data:
grafana_data:
Ahora necesitamos los archivos de configuración.
Configuración de Prometheus (prometheus.yml)
global:
scrape_interval: 15s
evaluation_interval: 15s
scrape_configs:
- job_name: 'prometheus'
static_configs:
- targets: ['localhost:9090']
- job_name: 'node_exporter'
static_configs:
- targets: ['localhost:9100']
- job_name: 'otel-collector'
scrape_interval: 10s
static_configs:
- targets: ['otel-collector:8888'] # Puerto de métricas del collector
[WARNING] Asegúrate de que el
scrape_intervalno sea demasiado agresivo si tienes muchos targets. 15s es un buen equilibrio.
Configuración de OpenTelemetry Collector (otel-collector-config.yml)
receivers:
otlp:
protocols:
grpc:
endpoint: 0.0.0.0:4317
http:
endpoint: 0.0.0.0:4318
processors:
batch:
timeout: 1s
send_batch_size: 1024
exporters:
prometheus:
endpoint: "0.0.0.0:8888"
namespace: "otel"
service:
pipelines:
metrics:
receivers: [otlp]
processors: [batch]
exporters: [prometheus]
Este collector recibe métricas vía OTLP y las expone en formato Prometheus en el puerto 8888.
Instrumentando una aplicación con OpenTelemetry
Para ver la magia, necesitamos una aplicación que envíe telemetría. Usaremos un ejemplo en Python con Flask.
Instalación de dependencias
pip install opentelemetry-api opentelemetry-sdk opentelemetry-exporter-otlp opentelemetry-instrumentation-flask
Código de ejemplo (app.py)
from flask import Flask
import random
from opentelemetry import trace, metrics
from opentelemetry.exporter.otlp.proto.http.metric_exporter import OTLPMetricExporter
from opentelemetry.sdk.metrics import MeterProvider
from opentelemetry.sdk.metrics.export import PeriodicExportingMetricReader
from opentelemetry.instrumentation.flask import FlaskInstrumentor
app = Flask(__name__)
# Instrumentar Flask automáticamente
FlaskInstrumentor().instrument_app(app)
# Configurar métricas
exporter = OTLPMetricExporter(endpoint="http://localhost:4318/v1/metrics")
reader = PeriodicExportingMetricReader(exporter)
provider = MeterProvider(metric_readers=[reader])
metrics.set_meter_provider(provider)
meter = metrics.get_meter("mi-app")
# Crear métrica personalizada
request_counter = meter.create_counter(
"app.requests.count",
description="Número de peticiones",
unit="1"
)
@app.route("/")
def hello():
request_counter.add(1, {"endpoint": "/"})
return "Hola, mundo!"
@app.route("/error")
def error():
request_counter.add(1, {"endpoint": "/error"})
return "Error simulado", 500
if __name__ == "__main__":
app.run(host="0.0.0.0", port=5000)
Ejecutamos la aplicación y, tras unas cuantas peticiones, las métricas aparecerán en Prometheus bajo el prefijo otel_.
[TIP] Usa
curlpara generar tráfico:while true; do curl http://localhost:5000/; sleep 2; done
Dashboards en Grafana
Conectamos Grafana a Prometheus como fuente de datos (URL: http://prometheus:9090). Ahora podemos importar dashboards predefinidos o crear los nuestros.
Dashboard básico de métricas del sistema
- En Grafana, ve a Create > Dashboard > Add new panel.
- Usa PromQL para consultar métricas. Por ejemplo:
100 - (avg by (instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100)→ Uso de CPU.node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes * 100→ Memoria disponible.
- Añade paneles para métricas de OpenTelemetry:
rate(otel_app_requests_count_total[5m])→ Tasa de peticiones.
Dashboard de Trazas (opcional, con Tempo)
Si quieres ver trazas, despliega Grafana Tempo y configúralo como fuente de datos. OpenTelemetry puede exportar trazas directamente a Tempo vía OTLP.
Alertas avanzadas con Prometheus y Alertmanager
Las alertas avanzadas van más allá de simples umbrales. Podemos crear reglas que evalúen tendencias, ratios o incluso basadas en logs.
Configuración de Alertmanager
Añadimos el servicio al docker-compose.yml:
alertmanager:
image: prom/alertmanager:latest
container_name: alertmanager
volumes:
- ./alertmanager.yml:/etc/alertmanager/alertmanager.yml
ports:
- "9093:9093"
restart: unless-stopped
Reglas de alerta en Prometheus (alert.rules.yml)
groups:
- name: sysadmin_alerts
rules:
- alert: AltaCargaCPU
expr: 100 - (avg by (instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) > 80
for: 5m
labels:
severity: critical
annotations:
summary: "CPU alta en {{ $labels.instance }}"
description: "CPU al {{ $value }}% durante más de 5 minutos."
- alert: TasaErroresApp
expr: rate(otel_app_requests_count_total{endpoint="/error"}[5m]) > 0.5
for: 2m
labels:
severity: warning
annotations:
summary: "Alta tasa de errores en /error"
description: "Tasa de errores: {{ $value }} peticiones/segundo."
- alert: PrediccionDiscoLleno
expr: predict_linear(node_filesystem_avail_bytes{fstype!="tmpfs"}[6h], 24*3600) < 0
for: 1h
labels:
severity: critical
annotations:
summary: "Disco se llenará en 24h en {{ $labels.instance }}"
[INFO] La función
predict_lineares una de las más potentes de PromQL. Permite anticipar problemas usando regresión lineal.
Configuración de Alertmanager (alertmanager.yml)
route:
receiver: 'slack'
group_wait: 30s
group_interval: 5m
repeat_interval: 4h
receivers:
- name: 'slack'
slack_configs:
- api_url: 'https://hooks.slack.com/services/TXXXXX/BXXXXX/XXXXXXXX'
channel: '#alertas-sysadmin'
send_resolved: true
Ahora, cada vez que se cumpla una regla, recibirás una notificación en Slack (o correo, PagerDuty, etc.).
Integración avanzada: Métricas de bases de datos y servicios
Monitorización de PostgreSQL con OpenTelemetry
Podemos usar el receptor postgresql del OpenTelemetry Collector para obtener métricas de la base de datos.
En otel-collector-config.yml, añadimos:
receivers:
postgresql:
endpoint: localhost:5432
username: monitor
password: secret
databases: [mydb]
Luego, en el pipeline:
service:
pipelines:
metrics:
receivers: [otlp, postgresql]
processors: [batch]
exporters: [prometheus]
Esto expondrá métricas como postgresql_connections, postgresql_transactions, etc.
Monitorización de Nginx
Usamos el receptor nginx del collector (o un exporter externo). El collector puede parsear el estado de Nginx si está configurado con stub_status.
Buenas prácticas para SysAdmin
Etiquetado semántico
Usa etiquetas (labels) de forma consistente. Por ejemplo:
env: producción, staging, desarrollo.service: nombre del microservicio.team: equipo responsable.
Esto facilita el filtrado en Grafana y la creación de alertas granulares.
Almacenamiento y retención
Prometheus no es una base de datos de larga duración. Para retención > 30 días, usa Thanos o Cortex. Configura --storage.tsdb.retention.time=30d.
Seguridad
- Protege Grafana con autenticación (por defecto, admin/admin).
- Usa HTTPS en producción.
- Restringe el acceso a los endpoints de Prometheus y OpenTelemetry.
Solución de problemas comunes
| Problema | Causa posible | Solución |
|---|---|---|
| Prometheus no ve el collector | Puerto incorrecto | Verifica que el collector exponga métricas en :8888 |
| Grafana no carga dashboards | Fuente de datos mal configurada | Revisa la URL de Prometheus (usa el nombre del contenedor) |
| OpenTelemetry no envía métricas | Endpoint OTLP incorrecto | Usa http://localhost:4318/v1/metrics |
| Alertas no se disparan | Regla mal escrita | Usa promtool check rules para validar |
[WARNING] Siempre prueba las reglas de alerta en un entorno de desarrollo antes de pasarlas a producción. Un falso positivo puede generar fatiga.
Conclusión
La combinación de Prometheus Grafana y OpenTelemetry ofrece una solución de monitorización SysAdmin robusta, escalable y open source. Con OpenTelemetry, podemos instrumentar cualquier aplicación de forma estandarizada, mientras que Prometheus se encarga del almacenamiento y las alertas avanzadas, y Grafana proporciona la visualización.
Este stack no solo te permite reaccionar ante incidentes, sino anticiparte a ellos mediante reglas predictivas y dashboards proactivos. Es la base de cualquier operación moderna, ya sea en un clúster Kubernetes o en un servidor bare-metal.
El siguiente paso es integrar logs con Loki o Elastic, y trazas con Tempo o Jaeger. Pero eso ya es otra historia.
