Runbook de Rollback de Despliegues
Runbook para revertir despliegues fallidos: triggers, comandos de kubectl/Helm/ArgoCD, rollback de migraciones de base de datos y checklists de verificación.
Visión General
Cuando un despliegue rompe producción tienes minutos, no horas. Este runbook te da los criterios de decisión para saber cuándo revertir, los comandos exactos para cada estrategia de despliegue (kubectl, Helm, ArgoCD, blue-green, canary), las rutas de rollback de migraciones de base de datos y los pasos de verificación y comunicación para después del rollback. Cada procedimiento está listo para copiar y pegar — durante un incidente deberías estar ejecutando, no improvisando.
Este runbook cubre el procedimiento operativo de revertir un despliegue defectuoso. Para planificar la estrategia de despliegue en sí, consulta Despliegues Blue-Green y Canary; para incidentes centrados en migraciones, consulta el Runbook de Migración de Datos.
Cuándo Usarlo
Acude a este runbook cuando un despliegue degrada producción y necesitas la ruta segura más rápida de vuelta a un estado conocido:
- La tasa de errores o la latencia se disparan justo después de un despliegue
- Los health checks fallan en los pods nuevos
- Una migración rompió el contrato de la aplicación
- Un canary muestra métricas negativas y hay que abortarlo
No hagas rollback para cambios solo de configuración (corrige el ConfigMap y redespliega), para una funcionalidad que se puede desactivar con un feature flag (apágala), o cuando el despliegue “malo” solo expuso un bug que ya existía (fix-forward es más rápido y mantiene el historial lineal).
Una decisión antes de la tabla: el rollback no siempre es la respuesta correcta. Si el despliegue defectuoso es un bug pequeño y bien entendido con un arreglo a 15 minutos, fix-forward puede ser la opción de menor riesgo — evitas hacer rebotar producción dos veces. Revierte cuando el fallo es amplio, la causa no está clara o los usuarios están afectados; fix-forward cuando el defecto está aislado y puedes verificar el arreglo rápido. En duda durante un incidente en vivo, revierte — siempre puedes desplegar de nuevo cuando esté arreglado.
Elige la ruta de rollback que corresponde a cómo se publicó el cambio:
| Método de despliegue | Ruta de rollback | Qué revierte |
|---|---|---|
| kubectl apply / Deployment | kubectl rollout undo (§2) | Solo la plantilla de pods — no cambios de Service, Ingress ni ConfigMap |
| Release de Helm | helm rollback (§3) | Todos los recursos que rastrea la revisión del release |
| ArgoCD / GitOps | Git revert (§4.2) | Lo que cambió el commit revertido — la traza de auditoría más limpia |
| Blue-green | Cambio de tráfico de vuelta (§5) | Solo el enrutado; ambas versiones siguen desplegadas |
| Canary (Argo Rollouts / manual) | Abortar o escalar a cero (§6) | La división de tráfico; la versión estable no se toca |
| Migración de base de datos | Fix-forward / down migration / snapshot (§7) | Esquema y datos — la ruta más lenta y arriesgada |
Antes de Empezar
Treinta segundos de verificación valen más que un segundo despliegue fallido:
- Confirma tu contexto de kubectl y namespace —
kubectl config current-context. Revertir el clúster equivocado es peor que no revertir. - Comprueba que tienes permisos — necesitas
update/patchsobre deployments y, para Helm, acceso a los secrets del release. Descúbrelo ahora, no a mitad del incidente. - Conoce tu última versión buena — etiqueta los releases o mantén
revisionHistoryLimit≥ 10 en los Deployments para que la revisión que necesitas siga existiendo. - Haz un snapshot de la base de datos antes de despliegues arriesgados — si el release incluye una migración, un snapshot previo es el único deshacer real para cambios destructivos.
- Desactiva el auto-sync en apps gestionadas por GitOps — si ArgoCD sincroniza automáticamente mientras reviertes, volverá a desplegar el estado defectuoso sin problema alguno.
1. Triggers de Rollback
El rollback es una decisión tomada bajo presión. La tabla de triggers existe para que esa decisión se tome antes del incidente, no durante — acuerda los umbrales con tu equipo por adelantado y codifícalos en las alertas siempre que sea posible.
1.1 Criterios de Trigger
Trigger | Severity | Action | Timeline
───────────────────────────┼──────────┼─────────────────────┼──────────
Error rate > 5% | Critical | Rollback immediately | < 5 min
Error rate > 1% | High | Investigate, prepare | < 15 min
P99 latency > 2x baseline | High | Rollback if trending | < 15 min
P99 latency > 5x baseline | Critical | Rollback immediately | < 5 min
Health check failures | Critical | Rollback immediately | < 5 min
OOM kills increasing | High | Rollback if trending | < 10 min
Customer complaints > 10 | High | Investigate, prepare | < 15 min
Deployment job timeout | Medium | Investigate | < 30 min
Database connection errors | Critical | Rollback immediately | < 5 min
1.2 Árbol de Decisión de Rollback
El árbol es deliberadamente agresivo: revertir un despliegue que resultó estar bien te cuesta un redespliegue; no revertir uno malo te cuesta una caída.
2. Rollback de Deployment en Kubernetes
kubectl rollout undo revierte la plantilla de pods del Deployment a una revisión anterior. No revierte cambios en Services, Ingresses, ConfigMaps o Secrets aplicados en el mismo release — esos necesitan su propio kubectl apply con el manifiesto anterior.
Antes de empezar, asegúrate de que .spec.revisionHistoryLimit del Deployment es lo bastante alto para conservar la revisión que quieres (el valor por defecto es 10; si despliegas con frecuencia, la revisión buena puede haberse eliminado ya).
2.1 Rollback con kubectl
# Revisar el historial de rollout
kubectl rollout history deployment/my-app -n production
# Ver detalles de una revisión concreta
kubectl rollout history deployment/my-app -n production --revision=3
# Revertir a la revisión anterior
kubectl rollout undo deployment/my-app -n production
# Revertir a una revisión concreta
kubectl rollout undo deployment/my-app -n production --to-revision=3
# Comprobar el estado del rollout
kubectl rollout status deployment/my-app -n production
# Pausar el rollout (si es canary y hay que pararlo)
kubectl rollout pause deployment/my-app -n production
# Reanudar el rollout
kubectl rollout resume deployment/my-app -n production
2.2 Verificar el Rollback
# Comprobar la versión de imagen actual
kubectl get deployment my-app -n production -o jsonpath='{.spec.template.spec.containers[*].image}'
# Comprobar el estado de los pods
kubectl get pods -n production -l app=my-app -o wide
# Revisar logs de pods en busca de errores
kubectl logs deployment/my-app -n production --tail=50
# Revisar eventos por problemas del deployment
kubectl get events -n production --field-selector involvedObject.name=my-app --sort-by='.lastTimestamp'
# Ejecutar el health check
kubectl exec -it deployment/my-app -n production -- curl -s http://localhost:8080/health
3. Rollback de Helm
helm rollback restaura el release completo a una revisión anterior — a diferencia de kubectl rollout undo, revierte todos los recursos que rastrea el release, incluidos Services y ConfigMaps. Sigue sin tocar lo que está fuera del release: CRDs instalados aparte, datos escritos en volúmenes o recursos externos como registros DNS.
3.1 Comandos de Rollback de Helm
# Listar los releases de Helm
helm list -n production
# Revisar el historial del release
helm history my-app -n production
# Revertir a la revisión anterior
helm rollback my-app -n production
# Revertir a una revisión concreta
helm rollback my-app 5 -n production
# Revertir con timeout
helm rollback my-app 5 -n production --timeout 5m
# Verificar el rollback
helm status my-app -n production
kubectl get pods -n production -l app.kubernetes.io/instance=my-app
3.2 Rollback de Helm con Limpieza
Un rollback fallido suele significar recursos atascados, no un Helm roto — revisa los pods que no terminan y los secrets del release que hayan quedado en mal estado:
# Si el rollback falla, buscar recursos atascados
kubectl get all -n production -l app.kubernetes.io/instance=my-app
# Borrado forzado de pods atascados
kubectl delete pod <pod-name> -n production --force --grace-period=0
# Revisar PVCs pendientes
kubectl get pvc -n production -l app.kubernetes.io/instance=my-app
# Limpiar secrets de Helm de releases fallidos
kubectl get secrets -n production -l owner=helm,name=my-app
kubectl delete secret sh.helm.release.v1.my-app.v6 -n production
4. Rollback de ArgoCD
Con GitOps hay dos rutas: el rollback por CLI (rápido, imperativo) y el revert en Git (más lento, pero mantiene el estado deseado en Git — que es la razón de ser de GitOps). Prefiere el revert en Git cuando la presión inmediata lo permite.
Nota:
argocd app rollbackes imperativo — cambia el estado en vivo sin tocar Git. Con el auto-sync activo, Argo CD detectará el drift y volverá a desplegar el estado nuevo (el defectuoso), así que desactiva el auto-sync primero y sigue con un revert en Git en cuanto el incidente esté bajo control.
4.1 Rollback por CLI de ArgoCD
# Obtener el estado de la aplicación
argocd app get my-app
# Revisar el historial de sincronización
argocd app history my-app
# Revertir a la sincronización anterior
argocd app rollback my-app
# Revertir a una revisión concreta
argocd app rollback my-app 5
# Desactivar el auto-sync antes del rollback (si está activo)
argocd app set my-app --sync-policy none
# Ejecutar el rollback
argocd app rollback my-app 5
# Reactivar el auto-sync después del rollback
argocd app set my-app --sync-policy automated --auto-heal
4.2 Rollback de ArgoCD Basado en Git
# Rollback basado en Git — revertir el commit y hacer push
git revert <bad-commit-sha>
git push origin main
# ArgoCD detecta el cambio y sincroniza automáticamente (si el auto-sync está activo)
# Si el auto-sync está desactivado, sincronizar manualmente:
argocd app sync my-app
# Sincronización forzada si hace falta
argocd app sync my-app --force
5. Rollback de Despliegue Blue-Green
El rollback blue-green es un cambio de enrutado, no un redespliegue — el entorno antiguo sigue corriendo, así que revertir es casi instantáneo. Esa es la razón principal para pagar el coste de infraestructura doble. Una precondición que comprobar primero: el entorno blue tiene que seguir existiendo de verdad. Si tu pipeline destruye el color anterior tras un switch exitoso, el rollback se convierte en un redespliegue de la versión antigua — más lento, pero igual de seguro.
5.1 Switch Blue-Green
# Estado actual: blue está activo, green es el despliegue nuevo
# Para revertir: devolver el tráfico a blue
# Cambio del selector del Service de Kubernetes
kubectl patch service my-app -n production -p \
'{"spec":{"selector":{"version":"blue"}}}'
# Verificar que el tráfico cambió
kubectl get svc my-app -n production -o yaml | grep selector -A 3
# Comprobar que los pods reciben tráfico
kubectl get pods -n production -l version=blue -o wide
# Escalar a cero el deployment green (tras confirmar que blue está sano)
kubectl scale deployment my-app-green -n production --replicas=0
5.2 Rollback con VirtualService de Istio
# Rollback: enrutar el 100% del tráfico de vuelta a blue
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
name: my-app
namespace: production
spec:
http:
- route:
- destination:
host: my-app-blue
port:
number: 8080
weight: 100
# Aplicar el VirtualService de rollback
kubectl apply -f virtualservice-rollback.yaml -n production
# Verificar el enrutado del tráfico
kubectl get virtualservice my-app -n production -o yaml
6. Rollback de Canary
El rollback de canary es una decisión de tráfico: dejar de mover tráfico a la versión nueva y que la estable vuelva a recibir el 100%. Con Argo Rollouts el controlador lo hace por ti cuando falla el análisis — define umbrales de tasa de errores y latencia en un AnalysisTemplate y el abort pasa a ser automático en lugar de una decisión del pager. Sin análisis automatizado, el procedimiento de abajo es manual y la tabla de triggers de la sección 1 son tus criterios de aborto.
6.1 Rollback de Canary con Argo Rollouts
# Comprobar el estado del rollout
kubectl argo rollouts get rollout my-app -n production --watch
# Abortar el canary y revertir a stable
kubectl argo rollouts abort my-app -n production
# Promover el canary a stable (si el canary va bien)
kubectl argo rollouts promote my-app -n production
# Reintentar el rollout tras un abort
kubectl argo rollouts retry my-app -n production
6.2 Rollback de Canary Manual
# Estado actual: 20% del tráfico en la versión nueva, 80% en la estable
# Para revertir: escalar la versión nueva a 0 y restaurar la estable al 100%
# Escalar a cero el deployment canary
kubectl scale deployment my-app-canary -n production --replicas=0
# Escalar el deployment estable
kubectl scale deployment my-app-stable -n production --replicas=10
# Actualizar el service para que apunte solo a stable
kubectl patch service my-app -n production -p \
'{"spec":{"selector":{"track":"stable"}}}'
# Verificar
kubectl get endpoints my-app -n production
kubectl get pods -n production -l track=stable
7. Rollback de Migraciones de Base de Datos
Los rollbacks de base de datos son la parte más lenta y arriesgada — el código se revierte en segundos, los datos no. Si puedes revertir o no depende de cómo se diseñó la migración, así que el trabajo real ocurre antes del despliegue: prefiere expand-contract para cualquier cosa que elimine o renombre columnas.
El orden importa cuando la aplicación y el esquema cambian a la vez: si la versión antigua de la aplicación no puede correr contra el esquema nuevo, revierte primero la base de datos (o tumbarás también la versión antigua que funcionaba). Si el esquema nuevo es retrocompatible — que es lo que expand-contract te da por diseño — revierte primero la aplicación y arregla el esquema después, sin presión.
Para incidentes centrados en migraciones que van más allá de un cambio de esquema, usa el Runbook de Migración de Datos.
7.1 Estrategia de Rollback por Tipo de Migración
Tipo de migración | Estrategia de rollback
──────────────────────┼──────────────────────────────────────────
Forward-only | Sin rollback — escribir migración fix-forward
Reversible | Ejecutar la down migration (inversa de up)
Expand-contract | Revertir la fase contract, conservar el expand
Restaurar snapshot | Restaurar desde backup (último recurso, pérdida de datos)
7.2 Rollback con Flyway
# Comprobar el estado de las migraciones
flyway -url=jdbc:postgresql://db:5432/mydb info
# Deshacer la última migración (solo Flyway Teams)
flyway -url=jdbc:postgresql://db:5432/mydb undo
# Para la edición community — escribir una migración fix-forward
# Crear V20260704_2__rollback_add_column.sql
-- Migración fix-forward para deshacer un cambio defectuoso
-- V20260704_1__add_status_column.sql añadió una columna que rompió la app
-- V20260704_2__remove_status_column.sql la revierte
ALTER TABLE orders DROP COLUMN IF EXISTS status;
7.3 Rollback con Liquibase
# Comprobar el estado de las migraciones
liquibase --url=jdbc:postgresql://db:5432/mydb status
# Rollback por número (últimos N changesets)
liquibase --url=jdbc:postgresql://db:5432/mydb rollbackCount 1
# Rollback por etiqueta
liquibase --url=jdbc:postgresql://db:5432/mydb rollback v2.3.0
# Rollback por fecha
liquibase --url=jdbc:postgresql://db:5432/mydb rollbackToDate 2026-07-04
7.4 Patrón Expand-Contract
Fase 1 — Expand (añadir columna nueva, conservar la vieja)
ALTER TABLE orders ADD COLUMN status_new VARCHAR(20);
Fase 2 — Migrate (escritura dual a ambas columnas)
-- La aplicación escribe en status y en status_new
-- Backfill: UPDATE orders SET status_new = status WHERE status_new IS NULL;
Fase 3 — Contract (cambiar lecturas a la columna nueva, eliminar la vieja)
-- La aplicación lee de status_new
ALTER TABLE orders DROP COLUMN status;
ALTER TABLE orders RENAME COLUMN status_new TO status;
Rollback:
- Tras la Fase 1: DROP COLUMN status_new (sin pérdida de datos)
- Tras la Fase 2: DROP COLUMN status_new (la columna vieja sigue intacta)
- Tras la Fase 3: no se puede revertir — hay que re-añadir la columna y hacer backfill
7.5 Restauración de Snapshot (Último Recurso)
Restaurar un snapshot implica pérdida de datos para todo lo escrito después del snapshot — mide esa ventana antes de apretar el gatillo:
# Restaurar desde el snapshot previo al despliegue
aws rds restore-db-instance-from-db-snapshot \
--db-instance-identifier myapp-db-rolled-back \
--db-snapshot-identifier pre-deploy-snapshot-2026-07-04
# O usar point-in-time recovery
aws rds restore-db-instance-to-point-in-time \
--source-db-instance-identifier myapp-db \
--target-db-instance-identifier myapp-db-rolled-back \
--restore-time 2026-07-04T09:00:00Z
8. Procedimientos Post-Rollback
El rollback no termina cuando la versión antigua está sirviendo — termina cuando has verificado la salud del servicio, avisado a los stakeholders y capturado lo necesario para el post-mortem. Saltarse la checklist de verificación es cómo los equipos acaban “revirtiendo” a una versión que estaba rota de otra manera.
8.1 Checklist de Verificación
- [ ] El health check de la aplicación pasa
- [ ] La tasa de errores vuelve al baseline (< 0.1%)
- [ ] La latencia P99 vuelve al baseline
- [ ] Todos los pods corriendo y listos
- [ ] Conexiones de base de datos sanas
- [ ] No hay OOM kills nuevos
- [ ] Los dashboards de monitoreo muestran patrones normales
- [ ] Las quejas de clientes paran o bajan
- [ ] Los logs no muestran errores nuevos
- [ ] Las alertas vuelven al estado normal
8.2 Acciones Post-Rollback
1. Verificar el rollback con la checklist anterior
2. Notificar a los stakeholders (Slack, email, status page)
3. Crear el ticket de incidente si aún no existe
4. Capturar la línea de tiempo (hora de deploy, detección, rollback)
5. Preservar logs y métricas para el post-mortem
6. NO redesplegar la misma versión sin un fix
7. Identificar la causa raíz del fallo
8. Escribir el fix y probarlo en staging
9. Programar la reunión de post-mortem en un plazo de 48 horas
10. Actualizar el runbook de despliegue con las lecciones aprendidas
8.3 Plantilla de Comunicación
[RESUELTO] Rollback de despliegue en producción — my-app
Línea de tiempo:
- 14:00 UTC: Despliegue de v2.3.1 iniciado
- 14:05 UTC: La tasa de errores subió al 8%
- 14:07 UTC: Rollback iniciado
- 14:10 UTC: Rollback completado, tasa de errores de vuelta al 0.1%
Impacto:
- Los usuarios vieron errores 500 durante unos 10 minutos
- ~5% de las peticiones fallaron durante el incidente
- Sin pérdida ni corrupción de datos
Causa raíz (preliminar):
- Configuración errónea del pool de conexiones de base de datos en v2.3.1
Acciones:
- Corregir la configuración del pool de conexiones
- Añadir un test de conexión a base de datos pre-despliegue
- Actualizar el pipeline de CI para detectar este error de configuración
Estado actual:
- Producción está corriendo v2.3.0 (versión estable anterior)
- Todos los servicios están sanos
- Próximo despliegue programado tras verificar el fix en staging
Lectura Adicional
- Guía Completa de GitOps con ArgoCD
- Helm Charts: Estructura, Templating, Dependencias, Registry
- Despliegues Blue-Green y Canary
- Despliegues Canary con Istio Service Mesh
- Empaquetar Manifiestos de Kubernetes con Helm Charts
- Kubernetes Deployments — documentación oficial
- Helm rollback — documentación oficial
- Argo CD — documentación oficial
Preguntas frecuentes
¿Con qué rapidez debería hacer rollback?
Inmediatamente cuando la tasa de errores supera el 5% o los health checks fallan — revierte primero, investiga después. Un rollback en Kubernetes tarda 2-5 minutos; el análisis de causa raíz tarda horas. Hazlo con la versión fallida corriendo en staging, no mientras los clientes ven errores.
¿Qué pasa si el propio rollback falla?
Borra a la fuerza los pods atascados (kubectl delete pod <name> --force --grace-period=0) y luego prueba un --to-revision concreto del historial de rollout. Si ninguna revisión funciona, fija directamente la última imagen buena conocida: kubectl set image deployment/my-app container=myorg/my-app:v2.3.0.
¿Se puede revertir una migración de base de datos?
Solo si se diseñó para ello. Las migraciones reversibles llevan script down; las forward-only necesitan una migración fix-forward; expand-contract se puede revertir antes de la fase contract pero no después. Los cambios destructivos (DROP TABLE, DELETE) solo se recuperan desde un backup — último recurso.
¿Debería usar despliegues blue-green o canary?
Blue-green es más simple y revierte al instante, pero necesita infraestructura doble. Canary mueve el tráfico gradualmente y puede auto-revertir según métricas, pero necesita maquinaria de división de tráfico (Istio, Argo Rollouts). Los servicios de producción con mucho tráfico favorecen canary; los servicios pequeños funcionan bien con blue-green.
¿Cómo evito que los despliegues malos lleguen a producción?
Apila las barreras: tests en CI, escaneo de seguridad, canary con análisis automatizado, health checks pre-despliegue y feature flags para desacoplar despliegue de release. Ninguna sustituye a un plan de rollback — reducen cuántas veces lo necesitas.
Recursos Relacionados
Checklist de Hardening de Docker Images
Checklist para hardening de Docker container images para production: base image selection, user permissions, filesystem restrictions, network isolation, resource limits, secret management, vulnerability scanning y CI/CD integration con Dockerfile examples.
DocPlantilla de Kubernetes Resource Quotas
Plantilla para definir Kubernetes resource quotas por namespace: CPU y memory limits, object count quotas, storage quotas, LimitRanges para default requests, priority class integration y monitoring con ejemplos para multi-tenant clusters.
GuideDespliegues Blue-Green y Canary
Guía práctica de estrategias de deploy: blue-green, canary, rolling y feature flags. Minimiza riesgo y tiempo de rollback al liberar a producción.
DocPlantilla de Runbook de Migración de Datos con Rollback
Usa esta plantilla de runbook para migrar datos de forma segura. Incluye pre-chequeos, pasos de ejecución, rollback y validación post-migración.
DocPlan de Prueba de Recuperacion ante Desastres
Una plantilla para planificar y ejecutar pruebas de recuperacion ante desastres incluyendo validacion de failover, verificacion de integridad de datos y medicion de tiempo de recuperacion.
DocRunbook de Failover de Base de Datos
Un runbook paso a paso para ejecutar procedimientos de failover de base de datos de forma segura con tiempo de inactividad y perdida de datos minimos.