Checklist de Despliegue sin Downtime
Un checklist para garantizar que los despliegues en producción se completen sin interrumpir el servicio usando patrones de rollout seguros.
Descripción General
Un solo despliegue defectuoso puede dejar fuera de servicio un sistema crítico en segundos. Los despliegues sin tiempo de inactividad actualizan producción mientras los usuarios siguen conectados, pero solo funcionan cuando los health checks realmente controlan el tráfico, los cambios de base de datos son compatibles con ambas versiones del código, y el rollback es un procedimiento probado en lugar de una esperanza. Este checklist cubre toda la ventana de release: qué verificar antes de desplegar, cómo enrutar el tráfico durante el rollout y las señales exactas que deben activar un rollback.
Está orientado a despliegues que no pueden interrumpir el tráfico. Para una lista de verificación general de pre-release, consulta la Plantilla de Checklist de Despliegue.
El checklist asume Kubernetes o un orquestador comparable, pero las mismas puertas aplican a cualquier plataforma: demuestra que la versión nueva está sana antes de que reciba tráfico, mantén la versión antigua viva hasta que la nueva se haya ganado todo el tráfico, y haz que la ruta de rollback sea más corta que el tiempo que tardan los usuarios en notar una caída.
Cuándo Usarlo
- Lanzar una nueva versión de un servicio de cara al usuario donde las peticiones caídas cuestan ingresos o confianza.
- Desplegar migraciones de esquema o datos mientras el código antiguo y el nuevo conviven.
- Cambiar load balancers, reglas de ingress u otra infraestructura que puede cortar la disponibilidad.
- Introducir por primera vez una estrategia de rollout como canary o blue-green.
- Desplegar antes de un pico de tráfico donde una caída parcial sería visible.
No lo uses para un job batch o una herramienta interna donde una ventana de mantenimiento es aceptable, ni para cambios de esquema destructivos que nunca fueron diseñados para ser compatibles hacia atrás — corrige primero la estrategia de migración.
Prerequisitos
- Un pipeline de CI/CD que produce un artefacto etiquetado e inmutable sin pasos manuales.
- Endpoints de health check que reportan el estado real de las dependencias, no solo que el proceso está vivo.
- Un load balancer, ingress o service mesh que permita desplazar el tráfico gradualmente.
- Migraciones de base de datos escritas para ser compatibles hacia atrás (expand-contract).
- Una ruta de rollback documentada con un artefacto y estado de datos conocidos.
- Dashboards y alertas que cubran tasa de errores, percentiles de latencia y métricas de negocio.
- Un canal de comunicación acordado y un responsable on-call para la ventana de release.
El Checklist
Trabaja las siete fases en orden — cada una asume que la anterior pasó. El checklist está pensado para imprimirse o pegarse en un ticket de release; cada casilla sin marcar es una decisión deliberada que deberías poder defender en un postmortem.
1. Preparación Previa al Despliegue
- El cambio está aprobado y documentado, con un responsable del despliegue y del on-call asignados.
- El código está mergeado y el artefacto compilado, etiquetado e inmutable.
- Los tests unitarios, de integración y de contrato pasan en CI.
- Las migraciones de base de datos fueron revisadas para compatibilidad hacia atrás.
- Los feature flags están configurados para poder desactivar el comportamiento nuevo sin redesplegar.
- La capacidad cubre el tráfico esperado más el pico de instancias duplicadas durante el rollout.
- Los dashboards y alertas están activos y enlazados en el ticket de release.
- La rotación de guardia conoce la ventana de despliegue y la ruta de escalado.
- Los pasos de rollback se probaron en staging en el último trimestre, no solo están escritos.
- La comunicación al cliente está redactada si el cambio es visible para el usuario.
2. Configuración de Health Checks
| Check | Endpoint | Criterio de Éxito | Acción ante Fallo |
|---|---|---|---|
| Liveness | /health/live | HTTP 200 | Reiniciar contenedor |
| Readiness | /health/ready | HTTP 200 y dependencias accesibles | Detener enrutado de tráfico |
| Startup | /health/startup | HTTP 200 | Retrasar rollout |
| Dependencias | /health/deps | Base de datos, caché y cola responden | Alertar y detener |
| Negocio | /health/business | Flujo crítico devuelve el valor esperado | Avisar al on-call |
Una sonda de readiness que devuelve 200 sin verificar la base de datos es la causa más común de despliegues “exitosos” que fallan inmediatamente para los usuarios. La sonda debe fallar cuando una dependencia está caída, aunque el proceso esté sano.
3. Selección de Estrategia de Rollout
| Estrategia | Caso de Uso | Nivel de Riesgo | Velocidad de Rollback |
|---|---|---|---|
| Rolling update | Servicios sin estado, bajo riesgo | Bajo | Media (terminar pods nuevos) |
| Blue-green | Sesiones con estado, releases predecibles | Medio | Rápido (revertir tráfico) |
| Canary | Alto riesgo, métricas medibles | Medio | Rápido (drenar canary) |
| Feature flag | Exposición gradual a usuarios | Bajo | Instantáneo (desactivar flag) |
| A/B deployment | Validar comportamiento de usuario | Medio | Rápido (re-enrutar tráfico) |
Elige canary cuando puedas definir una puerta de métricas, blue-green cuando las sesiones o cachés hagan riesgoso el tráfico con versiones mixtas, y rolling updates para servicios sin estado de bajo riesgo. La Guía de Despliegue Canary cubre el gating por métricas en profundidad; para dividir tráfico con Istio consulta Despliegue Canary con Istio.
4. Pasos de Ejecución del Despliegue
| Paso | Acción | Verificación |
|---|---|---|
| 1 | Desplegar en staging y ejecutar smoke tests | Tests de staging pasan |
| 2 | Desplegar canary o un subconjunto pequeño | Health checks pasan, tasa de errores estable |
| 3 | Monitorear métricas clave durante la duración del canary | Latencia, errores y métricas de negocio dentro de la línea base |
| 4 | Aumentar el porcentaje de tráfico gradualmente | Cada etapa pasa health checks y métricas |
| 5 | Completar el rollout al 100% | Todas las instancias sanas y sirviendo tráfico |
| 6 | Validar endpoints de producción | Smoke tests y flujos críticos pasan |
| 7 | Mantener la versión anterior disponible para rollback | Retener durante la ventana de rollback definida |
| 8 | Confirmar que la ventana de rollback ha pasado | Eliminar la versión antigua o actualizar el baseline |
5. Seguridad en Migraciones de Base de Datos
- Las migraciones son aditivas y funcionan con la versión anterior de la aplicación.
- El código antiguo puede leer el esquema nuevo sin errores.
- El código nuevo puede leer el esquema antiguo si hay que hacer rollback.
- Los índices se crean de forma concurrente cuando el motor lo permite.
- Las migraciones grandes se dividen en lotes suficientemente pequeños para no superar los timeouts de lock.
- Los jobs de backfill y migración son idempotentes y reanudables.
- Existe un script de rollback u operación compensatoria y está probado.
- Los cambios de esquema se probaron en staging con volumen de datos similar al de producción.
6. Disparadores de Rollback
| Disparador | Umbral | Acción |
|---|---|---|
| Pico en tasa de errores | > 0,5% durante 2 minutos | Pausar rollout e investigar |
| Aumento de latencia | p99 > línea base + 30% durante 5 minutos | Revertir tráfico |
| Caída en métrica de negocio | Conversión baja > 5% | Rollback inmediato |
| Fallo de health check | > 10% de instancias fallando | Rollback inmediato |
| Alerta crítica | Cualquier incidente P1 | Rollback y avisar al on-call |
| Timeout del canary | La etapa canary supera su duración sin pasar | Rollback del canary |
Vincula estos umbrales a tus SLOs en lugar de copiarlos a ciegas. Un servicio con objetivo de disponibilidad del 99,9% tolera una quema de error budget menor que estos valores por defecto. Para el procedimiento de rollback en sí, ten abierto el Runbook de Rollback de Despliegues durante el release.
7. Validación Post-Despliegue
- Los logs de la aplicación no muestran errores inesperados ni nuevos tipos de excepción.
- La tasa de errores y la latencia se mantienen en la línea base durante al menos 30 minutos.
- Las métricas de negocio están estables o mejorando.
- Los feature flags están en el estado previsto.
- Los recursos antiguos siguen disponibles hasta que cierre la ventana de rollback y luego se eliminan.
- Se envía un resumen del despliegue al equipo con enlaces a los dashboards.
- Cualquier incidencia encontrada queda registrada en el tracker con responsable.
Cómo Funciona
El despliegue sin downtime se apoya en tres pilares. La mecánica segura de rollout mantiene las versiones antigua y nueva sirviendo tráfico al mismo tiempo. Las señales de salud fiables le dicen al controlador de tráfico cuándo una instancia nueva está realmente lista. El rollback rápido reduce el radio de impacto cuando alguno de los dos primeros falla. El checklist existe porque el modo de fallo es siempre el mismo: un paso que “normalmente funciona” se omite bajo presión de tiempo, y justo en el release donde importaba, el servicio se cae.
El argumento económico es directo. Un canary al 10% que detecta una regresión la expone a una décima parte de tus usuarios durante unos minutos. La misma regresión enviada al 100% del tráfico de golpe se convierte en una caída completa, un tiempo de detección más largo y un rollback ejecutado bajo presión de incidente — exactamente las condiciones en las que los errores se multiplican. Medido en downtime total visible para el usuario, el camino por etapas es el rápido.
Configuración de Rolling Update en Kubernetes
apiVersion: apps/v1
kind: Deployment
metadata:
name: api-gateway
spec:
replicas: 10
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 3
maxUnavailable: 0
template:
spec:
containers:
- name: api
image: registry.example.com/api:v2.3.1
readinessProbe:
httpGet:
path: /health/ready
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
failureThreshold: 3
livenessProbe:
httpGet:
path: /health/live
port: 8080
initialDelaySeconds: 10
periodSeconds: 10
failureThreshold: 3
lifecycle:
preStop:
exec:
command: ["sh", "-c", "sleep 15 && kill -SIGTERM 1"]
terminationGracePeriodSeconds: 60
maxUnavailable: 0 mantiene todas las réplicas sirviendo mientras maxSurge: 3 levanta pods nuevos en paralelo. El hook preStop duerme antes del SIGTERM para que el kubelet tenga tiempo de quitar el pod de los endpoints — sin él, las peticiones en vuelo llegan a un pod que ya se está apagando.
Configuración de Canary con Argo Rollouts
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
name: api-gateway
spec:
replicas: 10
strategy:
canary:
steps:
- setWeight: 10
- pause: { duration: 5m }
- analysis:
templates:
- templateName: success-rate
args:
- name: service-name
value: api-gateway
- setWeight: 30
- pause: { duration: 5m }
- analysis:
templates:
- templateName: success-rate
args:
- name: service-name
value: api-gateway
- setWeight: 50
- pause: { duration: 10m }
- setWeight: 100
selector:
matchLabels:
app: api-gateway
template:
metadata:
labels:
app: api-gateway
spec:
containers:
- name: api
image: registry.example.com/api:v2.3.1
ports:
- containerPort: 8080
Cada paso analysis ejecuta un AnalysisTemplate (aquí success-rate) contra tu proveedor de métricas; un análisis fallido aborta el rollout y devuelve el tráfico automáticamente. Ajusta pesos y pausas a tu volumen de tráfico — un canary al 10% necesita suficientes peticiones por minuto para que las métricas sean estadísticamente significativas.
Flujo de Rollout Canary
Drenaje de Conexiones y DNS
Dos detalles rompen silenciosamente despliegues por lo demás limpios. Primero, el drenaje de conexiones: cuando el load balancer retira una instancia, mantén terminationGracePeriodSeconds por encima de la petición más larga que esperes — 60 segundos sirve para APIs HTTP típicas pero no para WebSocket o endpoints de streaming, donde debes enviar un frame de cierre del lado del servidor y esperar a que el contador de conexiones activas llegue a cero. En AWS ajusta el deregistration delay del target group; en GCP usa el connection draining timeout del backend service.
Segundo, el DNS. Si tu switch blue-green depende de DNS, baja el TTL del registro a 30-60 segundos al menos un día antes del cutover — los resolvers cachean agresivamente y un switch “instantáneo” puede tardar la vida del TTL antiguo para algunos clientes. Prefiere el enrutado ponderado en el load balancer o en el mesh siempre que sea posible, para que el switch no dependa del comportamiento del cliente.
Migraciones de Base de Datos con Expand-Contract
Expand-contract divide un cambio de esquema rompedor en tres despliegues seguros:
-- Fase 1 (expand): añadir la nueva forma junto a la antigua
ALTER TABLE orders ADD COLUMN total_cents BIGINT;
CREATE INDEX CONCURRENTLY idx_orders_total_cents ON orders(total_cents);
-- Fase 2 (migrate): dual-write desde la app, backfill por lotes
UPDATE orders SET total_cents = ROUND(total * 100)
WHERE id BETWEEN :lo AND :hi AND total_cents IS NULL;
-- Fase 3 (contract): un despliegue posterior elimina la columna vieja
ALTER TABLE orders DROP COLUMN total;
Las reglas que lo hacen seguro: nunca renombres ni elimines una columna en el mismo release que despliega el código nuevo, mantén los backfills idempotentes y por lotes para que un job fallido pueda reanudarse, y crea los índices con CONCURRENTLY en Postgres para evitar locks de tabla. Ejecuta cada fase como un despliegue separado con su propia ventana de validación.
Runbook Canary Minuto a Minuto
| Tiempo | Acción | Puerta |
|---|---|---|
| T-0 | Desplegar canary al 10% de peso | Pods listos, sin pico de errores |
| T+5m | Revisar tasa de errores, p99 y métricas de negocio | Todo dentro de la línea base |
| T+10m | Escalar al 30% | El análisis pasa |
| T+15m | Revisar métricas de nuevo | Todo dentro de la línea base |
| T+20m | Escalar al 50% | El análisis pasa |
| T+30m | Escalar al 100% | El análisis pasa |
| T+60m | Checklist de validación post-despliegue | Todos los ítems marcados |
| T+24h | Cerrar la ventana de rollback, eliminar versión antigua | Sin incidentes registrados |
Trata las puertas como paradas duras, no como sugerencias — si una métrica cruza un umbral disparador, pausa o haz rollback e investiga antes de reintentar.
Variantes
- Checklist de rolling update en Kubernetes: readiness probes,
maxSurge,maxUnavailabley pod disruption budgets. - Checklist de blue-green: mecánica del switch de tráfico, compatibilidad de base de datos y retención de versiones.
- Checklist de canary: umbrales de métricas, pesos de tráfico progresivos y puertas de rollback automático.
- Checklist de despliegue serverless: versionado de funciones, enrutado por alias y gestión de stages de API Gateway.
- Checklist de despliegue con base de datos intensiva: compatibilidad de esquema, orden de migraciones y scripts de rollback probados.
- Checklist de despliegue móvil o de cliente: rollout por fases, gestión de actualización forzada y compatibilidad de API.
Lo que Funciona
- Mantén los despliegues pequeños y frecuentes — un diff de 20 líneas es más fácil de revertir que uno de 2.000.
- Mantén los cambios de base de datos legibles tanto por la ruta de código antigua como por la nueva.
- Usa health checks que verifiquen dependencias reales, no solo que el proceso está vivo.
- Automatiza el rollback sobre umbrales de métricas en lugar de depender de que alguien mire un dashboard.
- Monitorea métricas de negocio junto a las técnicas; un despliegue puede pasar todos los health checks y aun así romper el checkout.
- Mantén un artefacto baseline conocido para que el rollback sea un redespliegue, no una recompilación.
- Practica los rollbacks en staging o game days — un plan de rollback sin probar es una hipótesis.
- Registra las decisiones y resultados del despliegue para que el checklist mejore después de cada incidente.
Errores Comunes
- Tratar un health check HTTP 200 como prueba de que el servicio funciona.
- Desplegar un cambio de esquema destructivo en el mismo release que el código que lo necesita.
- Enviar el 100% del tráfico antes de validar las métricas del canary.
- Empezar un despliegue sin una ruta de rollback probada.
- Mirar solo la tasa de errores mientras la latencia p99 se triplica en silencio.
- Limpiar la versión antigua antes de que cierre la ventana de rollback.
- Desplegar en hora punta sin margen para la capacidad duplicada durante el rollout.
- Confiar en DNS para un switch instantáneo mientras los clientes cachean el registro antiguo.
Troubleshooting
- El canary pasa los health checks pero los usuarios ven errores: la sonda de readiness no está cubriendo la dependencia que falla. Añade la dependencia real a
/health/readyy repite el rollout en staging. - El rollback termina pero la caída continúa: el cambio de esquema no era compatible hacia atrás, así que el código antiguo crashea contra el esquema nuevo. Restaura la compatibilidad primero y luego haz rollback — por eso existe expand-contract.
- Los pods terminan con peticiones en vuelo: falta el hook
preStopo la eliminación del endpoint, así que el pod muere antes de que el load balancer deje de enrutarle. Añade el hook de sleep-then-SIGTERM y revisa el retardo de propagación del ingress. - Las métricas del canary se ven bien pero el rollout al 100% falla: la muestra del canary era demasiado pequeña para sacar a la luz el modo de fallo, normalmente un límite de recursos o una ruta de caché fría que solo aparece a tráfico completo. Compara los perfiles de recursos del canary y de la flota completa.
- El rollback de feature flag deja datos inconsistentes: el flag desactivó escrituras pero no lecturas, o al revés. Despliega los cambios de flag para que las rutas de lectura y escritura cambien juntas, y mantén el flag al menos un release después de la activación completa.
Lectura Adicional
- Documentación de Kubernetes sobre rolling updates y sondas — la referencia autorizada de
maxSurge,maxUnavailabley semántica de probes. - Documentación de Argo Rollouts — pasos canary,
AnalysisTemplatey proveedores de métricas. - Guía de Despliegue Blue-Green — la guía completa cuando tu rollout necesita un entorno paralelo.
- Postmortems de incidentes públicos — modos de fallo reales que vale la pena añadir a tu propio checklist.
Preguntas frecuentes
¿Cuál es la diferencia entre rolling y canary deployment?
Los rolling updates van reemplazando las instancias antiguas de forma gradual, unos pocos pods cada vez, hasta que toda la flota corre la versión nueva. Un canary despliega primero un subconjunto pequeño, valida métricas y luego aumenta gradualmente el tráfico hacia la versión nueva.
¿Cómo hacemos seguros los cambios de base de datos para zero downtime?
Usa cambios aditivos primero (añade columnas, tablas, índices), despliega código que lea el esquema antiguo y el nuevo, y luego elimina el esquema viejo en un release posterior. Este es el patrón expand-contract.
¿Cuándo debemos hacer rollback inmediatamente?
Haz rollback cuando los health checks fallan de forma generalizada, la tasa de errores dispara, las métricas críticas de negocio caen o salta una alerta P1. Un rollback rápido preserva la confianza del usuario y los ingresos.
¿Cómo gestionamos conexiones de larga duración durante el despliegue?
Las conexiones de larga duración (WebSockets, SSE, streams gRPC) necesitan un hook preStop para drenarse con elegancia, un timeout de draining en el load balancer acorde, y un terminationGracePeriodSeconds suficientemente alto para la conexión más larga esperada. En WebSockets, envía un frame de cierre del servidor antes de terminar y espera a que el contador de conexiones activas llegue a cero antes de forzar el kill de los pods.
¿Qué es el patrón expand-contract para migraciones de base de datos?
Expand-contract es un patrón de tres fases para cambios de esquema sin downtime. En la fase expand añades columnas o tablas nuevas manteniendo las viejas. En la fase migrate la aplicación escribe en ambas y un backfill rellena las filas históricas. En la fase contract, un despliegue separado elimina las columnas viejas. Cada fase se publica con su propia ventana de validación.
¿Cómo probamos los despliegues zero-downtime antes de producción?
Prueba en staging bajo carga generada que imite el tráfico de producción. Despliega mientras corre la carga y mide tasa de errores, latencia p50/p95/p99, conexiones caídas y tasa de peticiones exitosas. Prueba también el rollback bajo carga, y alerta cuando los rollouts de producción se desvíen de los resultados de staging.
¿Cómo gestionamos los feature flags durante el despliegue?
Despliega con el flag desactivado, verifica estabilidad y luego actívalo para el 1-5% de usuarios monitorizando 10-15 minutos. Sube por 25%, 50% y 100% con monitorización en cada etapa. Si aparecen problemas, desactiva el flag al instante en lugar de hacer rollback. Mantén el flag en el código al menos un ciclo de release tras la activación completa.
¿Qué monitorización necesitamos durante despliegues zero-downtime?
Monitoriza tasa de errores, latencia p99, tasa de éxito de health checks, progreso del rollout, reinicios de pods y métricas de negocio, cada una con umbral de alerta. Un dashboard de despliegue que superponga los eventos de release sobre las métricas de la aplicación hace obvia la causa de una regresión de un vistazo.
Recursos Relacionados
Plantilla de Checklist de Despliegue
Una checklist de verificación pre-release para despliegues seguros en producción.
DocRunbook 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.
DocPlantilla de Runbook
Una plantilla reutilizable para runbooks operacionales: respuesta a incidentes, procedimientos de deployment y tareas rutinarias.
RecipeDespliegues Canary con Istio Service Mesh
Como usar el splitting de trafico de Istio para realizar despliegues canary seguros desplazando gradualmente usuarios entre versiones de aplicaciones
GuideDespliegue Canary: Rollouts Graduales y Seguros
Guía práctica de despliegues canary: división de tráfico, promoción automatizada, disparadores de rollback y releases seguros a un subconjunto de usuarios.
DocPlantilla de Configuracion de Entornos
Una plantilla para documentar variables de entorno, secretos, endpoints y configuraciones de infraestructura para cada entorno de despliegue.