StackPractices
intermediate Por Mathias Paulenko

Plantilla de Runbook de Guardia

Una plantilla que documenta alertas comunes y procedimientos de respuesta paso a paso para ingenieros de guardia.

Temas: devops

Visión General

A las 3 a.m., un ingeniero junior recibe una página: “Pool de conexiones a base de datos agotado.” Sin un runbook, pasan 30 minutos buscando en Google en lugar de 5 minutos siguiendo una lista de verificación. Un runbook no es un lujo para equipos grandes — es una herramienta de supervivencia para quien esté de guardia. Esta plantilla estructura alertas comunes, pasos de diagnóstico y procedimientos de resolución para que los ingenieros de guardia actúen con confianza, no con miedo.

Cuándo Usar

Usa este recurso cuando:

  • Estás creando la primera rotación de guardia de tu equipo y no tienes procedimientos documentados
  • Tu tiempo medio de resolución (MTTR) es alto porque los ingenieros depuran desde cero cada vez
  • Estás incorporando nuevos miembros al equipo que se unirán a la rotación de guardia

Solución

# Runbook de Guardia: `<Servicio / Equipo>`

## 1. Índice de Alertas

| Nombre de Alerta | Severidad | ¿Page? | Sección del Runbook | Última Verificación |
|------------------|-----------|--------|---------------------|---------------------|
| Alta Tasa de Error | SEV 2 | Sí | 2.1 | `AAAA-MM-DD` |
| Latencia P99 > 2s | SEV 2 | Sí | 2.2 | `AAAA-MM-DD` |
| Uso de Disco > 85% | SEV 3 | No | 2.3 | `AAAA-MM-DD` |
| Uso de Memoria > 90% | SEV 3 | No | 2.4 | `AAAA-MM-DD` |
| SSL Expira < 7 días | SEV 3 | No | 2.5 | `AAAA-MM-DD` |
| Dependencia No Saludable | SEV 2 | Sí | 2.6 | `AAAA-MM-DD` |
| Acumulación en Cola de Trabajos | SEV 3 | No | 2.7 | `AAAA-MM-DD` |

## 2. Procedimientos de Respuesta

### 2.1. Alta Tasa de Error

**Síntomas:**
- Tasa de error > 1% (o umbral definido en alerta)
- Pico en respuestas 5xx

**Pasos de Diagnóstico:**
1. Revisar dashboard de errores para los tipos de error principales
2. Correlacionar con despliegues recientes (últimas 2 horas)
3. Verificar salud de dependencias downstream
4. Revisar logs de aplicación para stack traces

**Resolución:**
- Si causado por despliegue: ejecutar plan de rollback
- Si causado por falla de dependencia: ver 2.6 Dependencia No Saludable
- Si causado por agotamiento de recursos: ver 2.3 o 2.4
- Si pico transitorio: monitorear 10 minutos; recuperación automática común

**Escalamiento:**
- Si tasa de error > 10% o errores de pérdida de datos: página al líder de equipo (SEV 1)
- Si no hay causa raíz en 30 minutos: página al líder de equipo

### 2.2. Latencia P99 > 2s

**Síntomas:**
- Latencia P99 por encima del umbral
- Quejas de usuarios sobre respuestas lentas

**Pasos de Diagnóstico:**
1. Verificar latencia de consultas a base de datos
2. Verificar tasa de acierto de caché (Redis / Memcached)
3. Buscar patrones de consulta N+1 en logs
4. Verificar latencia de servicios downstream
5. Revisar utilización de CPU y memoria

**Resolución:**
- Si cuello de botella en base de datos: matar consultas largas, escalar réplicas de lectura
- Si tormenta de miss de caché: pre-calentar caché, aumentar TTL temporalmente
- Si latencia downstream: ver 2.6 Dependencia No Saludable

**Escalamiento:**
- Si latencia > 10s o afecta > 50% de usuarios: página al líder de equipo
- Si causado por DDoS: involucrar equipo de seguridad inmediatamente

### 2.3. Uso de Disco > 85%

**Síntomas:**
- Alerta de uso de disco disparándose
- Riesgo de fallas de escritura

**Pasos de Diagnóstico:**
1. Identificar directorios más grandes (`du -sh /* | sort -rh | head`)
2. Verificar configuración de rotación de logs
3. Buscar archivos temporales o core dumps
4. Verificar tamaño y tasa de crecimiento de base de datos

**Resolución:**
- Limpiar logs antiguos (asegurar que la política de retención lo permita)
- Truncar tablas / particiones sobredimensionadas
- Expandir disco si es cloud-hosted (AWS EBS, GCP PD)
- Habilitar rotación de logs si está deshabilitada

**Escalamiento:**
- Si > 95% y escrituras fallando: página al líder de equipo
- Si expansión falla: página al equipo de infraestructura

### 2.4. Uso de Memoria > 90%

**Síntomas:**
- Alerta de uso de memoria disparándose
- Riesgo de kills por OOM

**Pasos de Diagnóstico:**
1. Identificar procesos con alto consumo de memoria (`ps aux --sort=-%mem | head`)
2. Verificar fugas de memoria (tendencia de 7 días)
3. Verificar tamaño de caché y tasa de evicción
4. Buscar crecimiento descontrolado de colas

**Resolución:**
- Reiniciar servicio si se sospecha fuga (arreglo temporal)
- Escalar a instancia más grande si hay crecimiento sostenido
- Reducir tamaño de caché o TTL
- Arreglar fuga de código en siguiente release

**Escalamiento:**
- Si kills por OOM causan reinicios: página al líder de equipo
- Si causa raíz de fuga no está clara: página al líder de equipo

### 2.5. SSL Expira < 7 Días

**Síntomas:**
- Advertencia de expiración de certificado

**Pasos de Diagnóstico:**
1. Confirmar detalles del certificado y fecha exacta de expiración
2. Verificar que la renovación automática está configurada
3. Verificar si el cert está desplegado en todos los endpoints

**Resolución:**
- Si renovación automática falló: renovar manualmente (ver runbook de cert)
- Si cert manual: crear ticket de renovación para equipo SRE
- Desplegar cert renovado en todos los balanceadores de carga / CDNs

**Escalamiento:**
- Si expiración < 24 horas: página al líder de equipo SRE

### 2.6. Dependencia No Saludable

**Síntomas:**
- Health check de servicio downstream fallando
- Errores de timeout a endpoint específico

**Pasos de Diagnóstico:**
1. Verificar página de estado de la dependencia
2. Verificar dashboard de métricas de la dependencia
3. Verificar conectividad de red (ping, traceroute)
4. Buscar problemas de resolución DNS
5. Verificar que tokens de autenticación / API keys no hayan expirado

**Resolución:**
- Si interrupción de dependencia: habilitar circuit breaker, servir modo degradado
- Si problema de red: involucrar proveedor de red / cloud
- Si problema de auth: rotar credenciales
- Si problema de capacidad: solicitar escalamiento al equipo de la dependencia

**Escalamiento:**
- Si dependencia es crítica y no hay modo degradado: página al líder de equipo + equipo de dependencia

### 2.7. Acumulación en Cola de Trabajos

**Síntomas:**
- Profundidad de cola creciendo
- Lag de procesamiento aumentando

**Pasos de Diagnóstico:**
1. Verificar cantidad y salud de procesos worker
2. Verificar utilización de CPU / memoria de workers
3. Buscar crecimiento en cola de mensajes fallidos (dead-letter)
4. Revisar tasa de fallo de trabajos

**Resolución:**
- Escalar workers horizontalmente si CPU < 70%
- Reiniciar workers atascados
- Reintentar trabajos fallidos desde dead-letter queue
- Si cuello de botella en base de datos: escalar réplicas de lectura

**Escalamiento:**
- Si acumulación > 1 hora y creciendo: página al líder de equipo

Explicación

El runbook trata cada alerta como un flujo de trabajo de diagnóstico, no solo como un problema a arreglar. Al forzar al ingeniero a verificar cosas específicas en orden, reduce la probabilidad de diagnóstico erróneo (por ejemplo, reiniciar un servicio cuando el problema es una dependencia downstream). Las reglas de escalamiento evitan que el ingeniero de guardia permanezca en silencio durante horas mientras lucha solo.

Cómo Construir y Mantener el Runbook

Un runbook que no coincide con tus alertas es peor que ninguno — enseña a los ingenieros a ignorarlo. Construye el tuyo desde evidencia, no imaginación.

1. Mina tu histórico de incidentes. Saca las últimas 6-12 páginas y tickets del último año. Agrúpalos por causa raíz, no por nombre de alerta — tres alertas distintas suelen compartir un mismo arreglo. Los siete procedimientos de la plantilla cubren los sospechosos habituales; tu propio histórico te dice cuáles escribir primero.

2. Mapea severidad a canal antes de necesitarlo. Decide de antemano qué despierta a una persona y qué va a un ticket. Un mapa simple evita que la fatiga de alertas se coma la rotación:

SeveridadCanalExpectativa de respuesta
SEV 1 — caída visible o pérdida de datosPage + canal de incidenteAcusar recibo en 5 min
SEV 2 — degradado o en riesgoPageAcusar recibo en 15 min
SEV 3 — aviso, sin impacto aúnTicket / dashboardTriaje el siguiente día laborable

3. Escribe para quien nunca ha visto la alerta. Comandos exactos antes que descripciones (“corre kubectl top pods”, no “revisa el uso de recursos”). Si un paso requiere criterio, di cómo se ve “malo” (“hit rate bajo 80% es tu problema”).

4. Conecta las alertas a las secciones del runbook. Usa la anotación runbook: mostrada abajo para que la propia página lleve el enlace. Nadie debería tener que buscar el documento a las 3 a.m. — la guía de monitoreo y alertas cubre el patrón de anotaciones en profundidad, y la guía de respuesta a incidentes de guardia cubre el flujo de rotación alrededor.

5. Cierra el ciclo después de cada incidente. El checklist post-incidente al final de esta página es el mecanismo de mantenimiento: alerta nueva → entrada nueva en el runbook, diagnóstico fallado → pasos corregidos. Luego verifica cada entrada trimestralmente — la columna “Última Verificación” del índice de alertas existe para que los procedimientos obsoletos se detecten antes de que lo haga la próxima página de las 3 a.m.

6. Asigna un responsable. Un runbook sin dueño se pudre. Un ingeniero lo posee (normalmente el líder de guardia), y “actualizar el runbook” es parte de la definición de hecho de cada incidente — mira la receta de alertas en Prometheus para conectar el lado de alertas de ese ciclo.

Mermaid flowchart TD diagram

Lecciones Reales de Runbooks

Los runbooks se ganan su lugar en los incidentes que todos recuerdan — y en los pequeños que nadie recuerda.

Knight Capital (2012). Un despliegue reutilizó un flag que despertó código dormido desde 2003, y la firma perdió $440M en 45 minutos. No había procedimiento documentado para el flag, el kill ni el rollback — para cuando alguien entendió qué hacía el sistema, el mercado ya se había quedado con el dinero. El argumento clásico de “todo procedimiento de deploy tiene un paso de deshacer escrito”.

Caída de AWS S3 (2017). Un operador depurando un sistema de facturación lento corrió un comando que retiró más capacidad de la prevista — y tumbó una porción enorme de internet durante horas. El postmortem de Amazon dijo que el arreglo incluía “añadir salvaguardas para evitar que la capacidad bajara de un nivel mínimo” — una restricción que pertenecía al paso del runbook, no a la cabeza del operador.

Incidente de base de datos de GitLab (2017). Resolviendo problemas de replicación de noche, un ingeniero borró el directorio de la base de datos de producción y perdió seis horas de datos. El postmortem famosamente transparente de GitLab es en sí un artefacto de runbook: documentaron exactamente qué pasó y qué habría ayudado — la fatiga de alertas y las salvaguardas ausentes que un runbook vivo captura.

Gamedays de Netflix. Netflix corre ejercicios de fallo deliberados (los DiRT que crecieron hasta el Chaos Engineering) en parte para mantener honestos los runbooks — un procedimiento no probado es ficción hasta que alguien lo sigue bajo presión. Para eso está la columna “Última Verificación” del índice de alertas: si la fecha está vieja, el procedimiento es una hipótesis, no un plan.

El hilo común: los incidentes castigan la brecha entre “sabemos qué hacer” y “está escrito, probado y enlazado desde la alerta”.

Variantes

ContextoEnfoque de AlertaAdición Clave
KubernetesReinicios de pods, presión de nodos, errores de ingressComandos kubectl para inspección de pods
ServerlessErrores de Lambda, cold starts, throttlingQueries de CloudWatch Logs Insights
Backend móvilFallas de push notifications, límites de rate de APISegmentación de errores por dispositivo
Pipeline de datosFallas de trabajos, drift de schema, datos tardíosProcedimientos de reintento de tareas Airflow / Dagster
Multi-regiónLatencia específica por región, lag de replicaciónSección de runbook de failover

Lo que funciona

  1. Mantén cada procedimiento en una página; los runbooks largos no se leen durante incidentes
  2. Incluye comandos exactos, no solo “revisa logs”; el estrés reduce la precisión al tipear
  3. Verifica cada procedimiento trimestralmente; runbooks obsoletos son peores que ninguno
  4. Enlaza a dashboards y logs, no pegues screenshots que caducan
  5. Incluye una decisión de “cuándo escalar” para cada alerta; la ambigüedad causa demora

Errores Comunes

  1. Escribir runbooks para expertos; son para el ingeniero que nunca ha visto esta alerta
  2. No probar comandos del runbook en un entorno de staging
  3. Omitir pasos de rollback; a veces el arreglo es “deshacer el último cambio”
  4. Crear runbooks pero no enlazarlos desde el sistema de alertas
  5. Tratar los runbooks como documentos estáticos; deben actualizarse después de cada incidente

Soluciones Avanzadas

Ejecución automatizada de runbook con scripts de diagnóstico

Pre-cablea pasos comunes de diagnóstico en scripts ejecutables que el ingeniero de guardia puede ejecutar con un solo comando:

#!/bin/bash
# diagnose.sh - Recopilador automatizado de diagnóstico para ingenieros de guardia
# Usage: ./diagnose.sh <service-name>

set -euo pipefail

SERVICE="${1:?Usage: $0 <service-name>}"
TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
REPORT_DIR="/tmp/diagnostics-${SERVICE}-${TIMESTAMP}"

mkdir -p "$REPORT_DIR"

echo "=== Collecting diagnostics for $SERVICE at $TIMESTAMP ==="

# 1. Service status
echo "Checking service status..."
systemctl status "$SERVICE" 2>&1 | tee "$REPORT_DIR/service-status.txt" || true

# 2. Recent logs (last 100 lines)
echo "Collecting recent logs..."
journalctl -u "$SERVICE" --since "1 hour ago" --no-pager 2>&1 \
  | tail -100 > "$REPORT_DIR/recent-logs.txt" || true

# 3. Resource utilization
echo "Checking resource utilization..."
{
  echo "=== CPU ==="
  top -bn1 | head -20
  echo ""
  echo "=== Memory ==="
  free -h
  echo ""
  echo "=== Disk ==="
  df -h
  echo ""
  echo "=== Top processes by CPU ==="
  ps aux --sort=-%cpu | head -10
  echo ""
  echo "=== Top processes by Memory ==="
  ps aux --sort=-%mem | head -10
} > "$REPORT_DIR/resources.txt"

# 4. Network connectivity
echo "Checking network..."
{
  echo "=== Listening ports ==="
  ss -tlnp 2>/dev/null || netstat -tlnp 2>/dev/null
  echo ""
  echo "=== Active connections ==="
  ss -tn state established 2>/dev/null | head -20
} > "$REPORT_DIR/network.txt"

# 5. Recent deployments
echo "Checking recent deployments..."
{
  echo "=== Docker containers ==="
  docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}" 2>/dev/null || echo "Docker not available"
  echo ""
  echo "=== Kubernetes pods ==="
  kubectl get pods -l app="$SERVICE" 2>/dev/null || echo "kubectl not available or no pods found"
} > "$REPORT_DIR/deployments.txt"

# 6. Health check
echo "Running health check..."
curl -sS -o "$REPORT_DIR/health-response.txt" -w "%{http_code}" \
  "http://localhost:8080/health" 2>&1 | tee "$REPORT_DIR/health-status.txt" || true

echo ""
echo "=== Diagnostics complete ==="
echo "Report saved to: $REPORT_DIR"
echo "Review files and attach to incident ticket."

Comandos de diagnóstico específicos para Kubernetes

Para entornos containerizados, incluye one-liners de kubectl que los ingenieros de guardia pueden copiar y pegar:

# Quick pod status check
kubectl get pods -n production -o wide | grep -v Running

# Get logs from a crashing pod
kubectl logs -n production <pod-name> --previous --tail=50

# Describe a pod for events and conditions
kubectl describe pod -n production <pod-name>

# Check resource usage across nodes
kubectl top nodes
kubectl top pods -n production --sort-by=memory

# Execute into a pod for network debugging
kubectl exec -it -n production <pod-name> -- /bin/sh -c "nslookup <dependency>"

# Check recent events in namespace
kubectl get events -n production --sort-by='.lastTimestamp' | tail -20

# Port-forward for local debugging
kubectl port-forward -n production svc/<service-name> 8080:80

Vinculación alerta-a-runbook con anotaciones de Prometheus

Vincula alertas directamente a secciones del runbook usando etiquetas de alerta de Prometheus para que los ingenieros nunca busquen el procedimiento correcto:

# prometheus/alerts.yml
groups:
  - name: service-alerts
    rules:
      - alert: HighErrorRate
        expr: |
          rate(http_requests_total{status=~"5.."}[5m])
          / rate(http_requests_total[5m]) > 0.01
        for: 5m
        labels:
          severity: warning
          team: platform
        annotations:
          summary: "High error rate on {{ $labels.service }}"
          description: "Error rate is {{ $value | humanizePercentage }} for {{ $labels.service }}"
          runbook: "https://wiki.internal/runbooks/on-call#21-high-error-rate"
          dashboard: "https://grafana.internal/d/service-overview?var-service={{ $labels.service }}"

      - alert: DiskUsageHigh
        expr: |
          (1 - node_filesystem_avail_bytes / node_filesystem_size_bytes) * 100 > 85
        for: 10m
        labels:
          severity: warning
          team: platform
        annotations:
          summary: "Disk usage > 85% on {{ $labels.instance }}"
          description: "Disk usage is {{ $value }}% on {{ $labels.instance }}"
          runbook: "https://wiki.internal/runbooks/on-call#23-disk-usage--85"
          dashboard: "https://grafana.internal/d/node-overview?var-node={{ $labels.instance }}"

Checklist de actualización de runbook post-incidente

Después de cada incidente, verifica que el runbook se actualice con las lecciones aprendidas:

## Actualización del Runbook Post-Incidente

- [ ] ¿La alerta estaba en el runbook? Si no, añádela ahora
- [ ] ¿Los pasos de diagnóstico eran correctos? Actualízalos si no encontraron la causa raíz
- [ ] ¿Los pasos de resolución funcionaron? Actualízalos si fallaron
- [ ] ¿El umbral de escalado era apropiado? Ajústalo si era muy alto o muy bajo
- [ ] ¿El enlace al runbook desde la alerta funcionó? Arréglalo si está roto
- [ ] ¿Hay comandos nuevos que habrían ayudado? Añádelos
- [ ] ¿Se actualizó la fecha de "última verificación"? Pon la de hoy
- [ ] ¿El ingeniero de guardia encontró útil el runbook? Anota el feedback

## Anti-patrones — 2.1 Alta Tasa de Error

- NO reinicies todos los pods a la vez (causa fallos en cascada)
- NO escales sin comprobar si el problema es una dependencia
- NO despliegues un fix sin probarlo antes en staging
- NO cierres la alerta hasta que la tasa de error esté bajo el umbral 15 minutos

Ver También

Código complementario: recursos del runbook de guardia: la plantilla de runbook, diagnose.sh, el archivo de alertas de Prometheus, el cheatsheet de diagnóstico kubectl y el checklist post-incidente de esta página.

Preguntas frecuentes

¿Qué tan detallado debe ser un runbook?

Cada procedimiento de alerta debe caber en una pantalla. Incluye: qué significa, 3–5 comandos de diagnóstico, 2–3 resoluciones comunes, y cuándo escalar. No incluyas explicaciones de arquitectura — eso pertenece a la documentación. El runbook es una lista de verificación para la acción, no un libro de texto.

¿Debería tener un runbook por servicio o uno por equipo?

Uno por servicio es más claro, pero consolida si tienes > 10 microservicios. En ese caso, crea un runbook de equipo con un índice de alertas que enlace a sub-páginas específicas por servicio. La clave es que el ingeniero de guardia encuentre el procedimiento correcto en menos de 30 segundos.

¿Qué pasa si la alerta no está en el runbook?

Sigue un procedimiento genérico de "alerta desconocida": clasifica severidad, recopila métricas básicas (CPU, memoria, tasa de error, latencia), verifica el último despliegue, y escala si no emerge una hipótesis en 15 minutos. Después del incidente, agrega la nueva alerta al runbook. La primera vez que una alerta se dispara es una oportunidad para documentarla.

¿En qué se diferencia un runbook de un SOP o un playbook?

Un runbook se dispara por alertas: "sonó esta alarma, sigue estos pasos". Un SOP documenta un procedimiento rutinario que corres en calendario (deploys, backups, rotación de certificados). Un playbook cubre un escenario, no un disparador — "failover de base de datos" o "incidente de seguridad" — y suele abarcar varias entradas del runbook. Los tres se solapan; mantén el runbook limitado a "la página que te acaba de despertar".

¿Con qué frecuencia deberían revisarse los runbooks?

Dos ritmos: después de cada incidente (el checklist post-incidente de abajo) y en una barrida trimestral donde el responsable re-verifica que cada comando y enlace sigue funcionando. La columna "Última Verificación" del índice de alertas es lo que hace honesta la barrida — cualquier cosa de más de un trimestre es sospechosa por definición.