Fundamentos de Prometheus en Entornos Contenerizados
Prometheus se ha consolidado como el estándar de facto para la observabilidad en ecosistemas nativos de la nube. Su arquitectura se basa en un modelo de extracción (Pull) a través de HTTP, lo que elimina la necesidad de integrar SDKs complejos en las aplicaciones. Cualquier componente que exponga un endpoint HTTP puede ser monitoreado, facilitando su integración en infraestructuras dinámicas como Docker o Kubernetes.
Características Principales
- Modelo de datos multidimensional: Las series temporales se identifican por el nombre de la métrica y pares clave-valor (labels).
- TSDB integrado: Almacenamiento optimizado para escrituras secuenciales y lecturas por rangos temporales.
- PromQL: Lenguaje de consulta expresivo para agregar, filtrar y analizar datos en tiempo real.
- Mecanismos de recolección dual: Soporte para el modelo Pull estándar y PushGateway para trabajos efímeros o por lotes.
- Descubrimiento dinámico: Integración nativa con la API de Kubernetes para adaptar los targets automáticamente a los cambios en el clúster.
Arquitectura y Componentes Clave
1. Prometheus Server
El núcleo del sistema, encargado de extraer y almacenar métricas. Internamente se divide en:
- Retrieval: Motor de extracción que consume los endpoints de los exporters.
- TSDB (Time Series Database): Base de datos diseñada específicamente para índices temporales, optimizada para escrituras en bloque y eliminaciones por ventanas de tiempo.
- HTTP Server: Interfaz que expone las APIs para consultas PromQL y configuración de alertas.
2. Ecosistema de Recolección
- Exporters: Traductores de métricas. Exponen datos de sistemas legacy o bases de datos en el formato de texto de Prometheus, esperando a que el servidor los consulte.
- Pushgateway: Intermediario para aplicaciones batch o cron jobs que no pueden ser consultadas directamente, permitiéndoles empujar sus métricas antes de terminar.
3. Descubrimiento y Alertas
El módulo kubernetes_sd es crucial en K8s, ya que resuelve la naturaleza efímera de los Pods, actualizando los targets sin intervención manual. Por otro lado, Alertmanager gestiona el enrutamiento, silenciamiento y agrupación de notificaciones (correo, Slack, PagerDuty) basadas en reglas de PromQL.
Despliegue en Kubernetes con Helm
La forma más eficiente de implementar esta pila es utilizando el operador de Prometheus a través de Helm.
Paso 1: Instalación del Stack
Primero, registramos el repositorio oficial y actualizamos los índices locales:
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo update
Luego, desplegamos el stack completo (que incluye Prometheus, Alertmanager y Grafana):
helm install observabilidad-stack prometheus-community/kube-prometheus-stack -n monitoreo --create-namespace
Paso 2: Exposición de los Dashboards
Para acceder a las interfaces web, podemos utilizar kubectl port-forward:
# Acceder al UI de Prometheus
kubectl port-forward svc/observabilidad-stack-kube-prometheus-prometheus 9090:9090 -n monitoreo
# Acceder al UI de Grafana
kubectl port-forward svc/observabilidad-stack-grafana 3000:80 -n monitoreo
Instrumentación de Aplicaciones (Ejemplo en Node.js)
Para que Prometheus pueda monitorear una aplicación personalizada, esta debe exponer un endpoint de métricas. A continuación, se muestra cómo instrumentar un servidor web en Node.js utilizando Express y la librería prom-client, registrando tanto el conteo de peticiones como su latencia.
const express = require('express');
const client = require('prom-client');
// Inicializar el registro por defecto
const register = new client.Registry();
client.collectDefaultMetrics({ register });
// Definir un Histogram para medir la duración de las peticiones HTTP
const httpDuration = new client.Histogram({
name: 'http_request_duration_seconds',
help: 'Duración de las peticiones HTTP en segundos',
labelNames: ['method', 'route', 'status_code'],
buckets: [0.01, 0.05, 0.1, 0.5, 1, 2, 5]
});
register.registerMetric(httpDuration);
const app = express();
const PORT = process.env.PORT || 8080;
// Middleware para medir el tiempo de respuesta
app.use((req, res, next) => {
const end = httpDuration.startTimer({ method: req.method, route: req.path });
res.on('finish', () => {
end({ status_code: res.statusCode });
});
next();
});
app.get('/', (req, res) => {
res.send('Servidor instrumentado y listo para Prometheus');
});
// Endpoint expuesto para que Prometheus extraiga las métricas
app.get('/metrics', async (req, res) => {
res.set('Content-Type', register.contentType);
res.end(await register.metrics());
});
app.listen(PORT, () => {
console.log(`Servidor corriendo en el puerto ${PORT}`);
});
Configuración de Reglas y Visualización
Definición de ServiceMonitors y Alertas
El opreador de Prometheus utiliza Recursos Personalizados (CRDs) para configurar el monitoreo sin editar el archivo de configuración principle. Para monitorear la aplicación Node.js anterior, se crea un ServiceMonitor que apunte al puerto y path de /metrics. Las alertas se definen mediante el CRD PrometheusRule, evaluando expresiones como rate(http_request_duration_seconds_sum[5m]) / rate(http_request_duration_seconds_count[5m]) > 0.5 para detectar latencias altas.
Integración con Grafana
El stack de Helm configura automáticamente Prometheus como fuente de datos en Grafana. Desde el panel de Grafana, se pueden importar dashboards predefinidos (como los IDs 315 para Kubernetes o 11074 para Node.js) o construir paneles personalizados utilizando consultas PromQL para visualizar el rendimiento del clúster y las aplicaciones en tiempo real.