⏱ Tiempo estimado: 25 minutos
🎯 Rama / Perfil: SRE / DevOps / backend devs que quieren medir confiabilidad con datos reales.
🧠 Conocimiento previo necesario: Clases 17 a 20 del curso (SLOs y SLIs, monitoreo, logs vs métricas) y Docker básico.
💡 ¿Qué vas a lograr? Medir la disponibilidad de una app con un SLI real, verlo en un dashboard y disparar una alerta cuando incumples tu SLO de 99%.
🛠 Lo que necesitas antes de empezar
- Docker Desktop (incluye Compose) → 🔗 https://www.docker.com/products/docker-desktop/
- Node.js 20+ → 🔗 https://nodejs.org/
- Terminal bash (en Windows usa WSL o Git Bash) → 🔗 https://learn.microsoft.com/windows/wsl/install
📋 Pasos
Paso 1: Crea una app que expone métricas
Estructura:
slo-lab/
├─ app/ (server.js, package.json, Dockerfile)
├─ prometheus.yml
├─ alerts.yml
└─ docker-compose.yml
En app/ ejecuta npm init -y && npm install express prom-client. Luego crea app/server.js:
js
const express = require('express');
const client = require('prom-client');
const app = express();
client.collectDefaultMetrics();
const requests = new client.Counter({
name: 'http_requests_total', help: 'Total de requests',
labelNames: ['route', 'status']
});
const latency = new client.Histogram({
name: 'http_request_duration_seconds', help: 'Latencia',
labelNames: ['route'], buckets: [0.05, 0.1, 0.25, 0.5, 1, 2]
});
app.use((req, res, next) => {
const end = latency.startTimer();
res.on('finish', () => {
requests.inc({ route: req.path, status: res.statusCode });
end({ route: req.path });
});
next();
});
app.get('/', (req, res) => setTimeout(() => res.send('ok'), Math.random() * 300));
app.get('/flaky', (req, res) => {
if (Math.random() < 0.2) return res.status(500).send('error');
res.send('ok');
});
app.get('/metrics', async (req, res) => {
res.set('Content-Type', client.register.contentType);
res.send(await client.register.metrics());
});
app.listen(3000);
Crea app/Dockerfile:
dockerfile
FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm install --omit=dev
COPY server.js .
CMD ["node", "server.js"]
🔗 prom-client (librería oficial de métricas para Node): https://github.com/siimon/prom-client
Paso 2: Configura Prometheus y la regla de alerta del SLO
prometheus.yml:
yaml
global:
scrape_interval: 5s
rule_files:
- alerts.yml
scrape_configs:
- job_name: app
static_configs:
- targets: ['app:3000']
alerts.yml (SLO: 99% de requests sin error 5xx):
yaml
groups:
- name: slo
rules:
- alert: SLODisponibilidadIncumplido
expr: |
sum(rate(http_requests_total{status!~"5.."}[1m]))
/ sum(rate(http_requests_total[1m])) < 0.99
for: 1m
labels:
severity: page
annotations:
summary: "Disponibilidad por debajo del SLO de 99%"
Paso 3: Levanta todo con Docker Compose
docker-compose.yml:
yaml
services:
app:
build: ./app
ports: ["3000:3000"]
prometheus:
image: prom/prometheus
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
- ./alerts.yml:/etc/prometheus/alerts.yml
ports: ["9090:9090"]
grafana:
image: grafana/grafana
ports: ["3001:3000"]
bash
docker compose up -d --build
Verifica en 🔗 http://localhost:9090/targets que app aparezca en estado UP.
🔗 Prometheus: https://prometheus.io/docs/introduction/overview/ · Grafana: https://grafana.com/docs/grafana/latest/
Paso 4: Genera tráfico y mide tu SLI
bash
for i in $(seq 1 3000); do curl -s localhost:3000/flaky > /dev/null; sleep 0.05; done
En Prometheus (http://localhost:9090/graph) ejecuta esta consulta, que es tu SLI de disponibilidad:
sum(rate(http_requests_total{status!~"5.."}[1m])) / sum(rate(http_requests_total[1m]))
Verás un valor cercano a 0.8, porque /flaky falla el 20% de las veces.
Paso 5: Visualízalo en Grafana
Abre http://localhost:3001 (usuario admin, contraseña admin; te pedirá cambiarla). Ve a Connections → Data sources → Add → Prometheus y usa la URL http://prometheus:9090. Crea un dashboard con 2 paneles:
- Disponibilidad (SLI): la consulta del paso 4.
- Latencia p95:
histogram_quantile(0.95, sum(rate(http_request_duration_seconds_bucket[1m])) by (le))
Paso 6: Mira la alerta dispararse
Con el tráfico corriendo, espera un par de minutos y abre 🔗 http://localhost:9090/alerts. La alerta pasará de Pending a Firing. Ahora apunta el tráfico a / (sin fallos) y verás que se resuelve. Acabas de ver un error budget agotarse y recuperarse.
✅ Resultado esperado
Un stack local de 3 contenedores con una app instrumentada, un SLI de disponibilidad calculado en Prometheus, un dashboard de disponibilidad y latencia p95 en Grafana, y una alerta basada en un SLO de 99%.
🔥 Tu reto (siguiente acción)
Define un segundo SLO de latencia (por ejemplo, “95% de las requests a / en menos de 250 ms”) y escribe su regla de alerta usando http_request_duration_seconds_bucket{le="0.25"}. Luego conecta la alerta a Slack o email con Alertmanager.
📚 Recursos para ir más lejos
- Alertmanager: 🔗 https://prometheus.io/docs/alerting/latest/alertmanager/ (enruta alertas a Slack, email o PagerDuty)
- Libro Google SRE, capítulo de SLOs: 🔗 https://sre.google/sre-book/service-level-objectives/ (la teoría de fondo de lo que acabas de medir)
Curso Profesional de DevOps
COMPARTE ESTE ARTÍCULO Y MUESTRA LO QUE APRENDISTE