Be Software Architecture Wise
Be Wise Apps

Read in English · Lire en français · Auf Deutsch lesen

Sección 10.5 de 10.8 · Intermedio · 22 min de lectura

Pipelines de CI/CD y estrategias de despliegue

Videolección

5 min · narrado en inglés, con subtítulos
Solo escuchar (audio)
Leer la transcripción

¿Con qué rapidez y seguridad puede tu equipo cambiar cualquier cosa? Lo decide el pipeline de despliegue. En esta lección seguirás un cambio desde el commit hasta producción y aprenderás las estrategias que limitan el daño que puede hacer una versión defectuosa.

Piensa en una cadena de panaderías que lanza un pan nuevo. Hornea un lote de prueba y lo comprueba en su propio obrador. Luego lo vende en una sola tienda durante una mañana, antes de enviarlo a todas las tiendas. Si los clientes se quejan, solo se ha visto afectada una tienda, y el pan de siempre sigue en los estantes. Un pipeline es esa rutina, automatizada: cada cambio se compila una vez, se comprueba por etapas, se prueba con unos pocos usuarios y solo se extiende cuando las pruebas son buenas. Y un interruptor aparte decide cuándo ven los clientes una nueva funcionalidad.

El pipeline de despliegue, descrito por Jez Humble y David Farley en 2010, hace pasar cada commit por etapas automatizadas, las más rápidas primero. La etapa de commit compila, ejecuta las pruebas unitarias y las comprobaciones, y debería tardar menos de diez minutos. La etapa de empaquetado construye una imagen de contenedor, con una lista de materiales de software, la firma y la sube al repositorio de artefactos, una sola vez. Después, las pruebas de aceptación, staging y producción despliegan exactamente esa misma imagen. Un cambio avanza a la derecha solo si la etapa anterior se superó. Esto es build once, deploy many: compilar una vez, desplegar muchas. Entre entornos solo cambia la configuración. Si recompilas para producción, lo que probaste no es lo que entregas. Y cualquier fallo detiene la línea y vuelve directamente al autor, mientras aún tiene el cambio fresco en la mente.

Una estrategia de despliegue decide a cuántos usuarios puede perjudicar una versión defectuosa antes de que se detenga. La recreación detiene todas las instancias antiguas y luego arranca las nuevas: es sencilla, pero tiene tiempo de inactividad, y todos se encuentran a la vez con una versión defectuosa. El despliegue gradual sustituye las instancias unas pocas a la vez, y es la opción por defecto de Kubernetes. Revertir tarda tanto como el despliegue. El azul-verde ejecuta un entorno nuevo completo junto al que está en producción, lo prueba y luego cambia todo el tráfico en el router. Revertir es rápido, pero necesitas hasta el doble de capacidad durante el cambio. Un canario envía una pequeña parte del tráfico, por ejemplo del uno al cinco por ciento, a la nueva versión, compara sus métricas y luego amplía por pasos. Un despliegue en sombra copia solicitudes reales a la nueva versión, pero nunca devuelve sus respuestas, así que hay que suprimir los efectos secundarios, como los pagos. Siempre que se ejecutan dos versiones a la vez, deben ser compatibles con los datos y los mensajes de la otra.

Aquí tienes un canario con análisis automatizado. Los usuarios llegan a un router de tráfico: un balanceador de carga o un service mesh. El noventa por ciento del tráfico va a la flota de producción, que ejecuta la versión uno. El cinco por ciento va a una línea base nueva de la versión uno, y otro cinco por ciento al canario, la versión dos. Comparar con una línea base nueva elimina las diferencias causadas solo por las cachés calientes y el largo tiempo de actividad. Un paso de análisis compara errores, latencia y saturación, y luego amplía el canario al veinticinco por ciento o lo revierte. Decide el sistema, no una persona que mira paneles. Eso es la entrega progresiva.

El despliegue instala una nueva versión en un entorno. El lanzamiento pone un comportamiento a disposición de los usuarios. Los feature flags los separan: el código se despliega desactivado y se lanza más tarde, de forma gradual y reversible. Cada flag tiene un costo de mantenimiento, así que da a los flags fechas de caducidad y elimínalos una vez decididos. Y como los datos no se pueden revertir como el código, los cambios de esquema deben ser compatibles hacia atrás: primero se expande, y solo se contrae en un lanzamiento posterior.

Juntémoslo todo. El servicio de pedidos va a cambiar la forma de calcular las tarifas de envío. El nuevo calculador está detrás de un flag de lanzamiento, desactivado, y una migración solo de expansión añade una columna nueva. El cambio se fusiona a las diez y dos minutos. Lint, pruebas unitarias y escaneos tardan seis minutos, y una imagen firmada se sube a las diez y nueve. La migración aditiva se ejecuta como paso propio a las diez y cuarto. La versión en ejecución ignora la nueva columna, así que nada se rompe. Después, la misma imagen supera las pruebas de staging. A las diez y treinta y cinco, el cinco por ciento del tráfico de producción va a la nueva versión, con el flag todavía desactivado. Veinte minutos de análisis frente a una línea base nueva: pasa. El tráfico pasa al veinticinco, al cincuenta y al cien por ciento en pasos de quince minutos, y termina a las once y cuarenta. El despliegue está completo y, sin embargo, ningún cliente ha visto la nueva tarifa. Al día siguiente, el responsable de producto activa el flag para el diez por ciento de los clientes de una ciudad y luego lo amplía a todas las ciudades a lo largo de una semana. El riesgo del despliegue y el del lanzamiento se gestionaron por separado, cada uno con un radio de impacto reducido.

La sección completa trata el desarrollo basado en trunk, los cuatro tipos de feature flag y cuándo revertir o corregir hacia adelante. A continuación, en la Sección diez punto seis, veremos cómo operar en varias regiones. Nos vemos allí.

Lo que necesitas saber

Del commit a producción: para qué sirve un pipeline

La Sección 0.8 (cómo se hace el software) presentó la integración continua (cada cambio se fusiona y se verifica automáticamente), la entrega continua (la rama principal está siempre lista para lanzarse) y el despliegue continuo (cada cambio que supera las comprobaciones pasa a producción sin una decisión humana). Esta sección los trata como arquitectura: el diseño del camino que sigue un cambio y las estrategias que lo llevan a producción sin perjudicar a los usuarios.

La idea central es el pipeline de despliegue, descrito por Jez Humble y David Farley en Continuous Delivery (2010). Cada commit desencadena una secuencia automatizada de etapas. Las primeras etapas son rápidas y baratas y detectan la mayoría de los problemas; las posteriores son más lentas, más realistas y más caras. Un cambio pasa a la siguiente etapa solo si la anterior se superó, de modo que cuanto más avanza una compilación, más confianza se ha ganado. Un fallo en cualquier punto detiene esa compilación y vuelve directamente a la persona que hizo el cambio, mientras aún lo tiene fresco en la mente.

El pipeline importa a los arquitectos por tres razones. Primero, es donde la desplegabilidad, un atributo de calidad de la sección 2.6, se logra o se pierde de verdad. Segundo, su velocidad limita la rapidez con la que la organización puede responder a un cambio del mercado o a una vulnerabilidad de seguridad: si una corrección de una línea tarda dos días en llegar a producción, la arquitectura tiene dos días de lentitud, se vea como se vea el código. Tercero, la forma del sistema condiciona la forma del pipeline: los servicios desplegables de forma independiente pueden tener pipelines independientes, pero un monolito distribuido obliga a lanzamientos coordinados por muy ingeniosas que sean las herramientas.

Las etapas de un pipeline típico

Un pipeline de despliegue: commit, compilación, empaquetado, pruebas de aceptación, staging y producción, con un artefacto subido una vez a un repositorio y bajado por cada etapa posteriorCommitpush a maino fusión de PRBuildcompilar, testsunit. y lintPaqueteimagen + SBOMfirma, pushAceptacióntests deAPI y contratoStagingdesplegar, testde humoProduccióncanario, luegoal 100%Cada etapa está automatizada; un cambio avanza a la derecha solo si la etapa anterior pasóRepo. de artefactosuna imagen inmutable por commit, identificada por digestsubir 1 vezbajar la misma imagenCualquier fallo detiene la línea y avisa al autor en minutos
Un artefacto se compila y se sube una sola vez; cada etapa posterior despliega exactamente ese artefacto, y cualquier fallo detiene la línea.

Qué hace cada etapa y cuánto debería tardar

  1. Etapa de commit (objetivo: menos de 10 minutos)Compila, ejecuta las pruebas unitarias, los linters, el análisis estático y los escaneos de vulnerabilidades de las dependencias. Es la etapa que esperan los desarrolladores, así que debe ser rápida; las pruebas lentas van después.
  2. EmpaquetadoConstruye el artefacto desplegable (normalmente una imagen de contenedor), genera una lista de materiales de software (SBOM), fírmalo y súbelo al repositorio de artefactos. Los controles de la cadena de suministro se tratan en la sección 8.6.
  3. Aceptación e integraciónDespliega el artefacto en un entorno de pruebas temporal o compartido y ejecuta pruebas de API, pruebas de contrato dirigidas por el consumidor y unos pocos recorridos de extremo a extremo. Las pruebas de rendimiento y de seguridad pueden ejecutarse aquí en paralelo o de forma programada.
  4. StagingDespliega en un entorno configurado como producción, aplica las migraciones de base de datos y ejecuta pruebas de humo. Su valor depende de lo mucho que se parezca a producción en configuración, forma de los datos y dependencias.
  5. ProducciónDespliega con una estrategia que limite la exposición (gradual, azul-verde o canario), verifica con métricas reales frente a los objetivos de nivel de servicio y luego completa o revierte automáticamente.

Build once, deploy many y el repositorio de artefactos

Una regla de Continuous Delivery que se sigue incumpliendo con sorprendente frecuencia es build once, deploy many (compilar una vez, desplegar muchas): compila y empaqueta cada cambio exactamente una vez y luego promueve ese mismo artefacto por todos los entornos. Si un equipo recompila para staging y otra vez para producción, lo que probó no es lo que entregó. Un parche distinto del compilador, una dependencia resuelta durante la noche a una versión más reciente o una imagen base cambiada pueden hacer que las dos compilaciones difieran, y las pruebas no demuestran nada sobre la segunda.

Lo que cambia entre entornos es la configuración, proporcionada en el momento del despliegue o del arranque (direcciones de bases de datos, credenciales, ajustes de los feature flags), nunca incorporada al artefacto. Es el factor de configuración de la aplicación de doce factores. Una imagen de contenedor etiquetada orders:4f1c2ab (el hash del commit) se despliega en pruebas, staging y producción; solo cambian sus variables de entorno y los secretos montados.

El repositorio de artefactos es el almacén entre la compilación y el despliegue: un registro de contenedores (Amazon ECR, Azure Container Registry, Google Artifact Registry, GitHub Container Registry, Harbor) o un repositorio universal como JFrog Artifactory o Sonatype Nexus para paquetes y binarios. Trátalo como infraestructura crítica. Despliega por digest inmutable (sha256:...) en lugar de por una etiqueta mutable como latest, que puede moverse para apuntar a otra imagen; conserva los artefactos que están o estuvieron en producción durante todo el tiempo que puedas necesitar volver a ellos o investigarlos; y registra la procedencia, es decir, qué commit, qué ejecución del pipeline y qué dependencias produjeron cada artefacto.

Desarrollo basado en trunk y lotes pequeños

La forma de usar las ramas decide con qué frecuencia se integra realmente el código. En el desarrollo basado en trunk (trunk-based development) todos integran cambios pequeños en una única rama principal (el trunk) al menos una vez al día, ya sea haciendo commit directamente o mediante ramas de corta duración y pull requests que viven horas, no semanas. El programa de investigación DORA ha asociado repetidamente las ramas de corta duración y las fusiones frecuentes con un mayor rendimiento de entrega, y es una condición previa para la integración continua en sentido literal: el código que pasa tres semanas en una rama no se está integrando de forma continua.

Las ramas de funcionalidad de larga duración parecen más seguras porque el trabajo sin terminar se mantiene aparte, pero el riesgo solo se aplaza: cuanto más divergen dos ramas, mayor y más arriesgada es la fusión final, y más tiempo ve el pipeline un código que no es el que se va a entregar. GitFlow, un modelo de ramas con ramas develop y release de larga duración publicado por Vincent Driessen en 2010, se adoptó ampliamente; en 2020 Driessen añadió una nota según la cual los equipos que entregan de forma continua, como los de aplicaciones web, deberían considerar un flujo de trabajo más sencillo. Los equipos que sí necesitan trabajar en cambios grandes en el trunk usan dos técnicas: los feature flags, que ocultan el comportamiento sin terminar, y branch by abstraction, que introduce una interfaz delante de la implementación antigua, construye la nueva detrás de ella y hace el cambio cuando está lista.

Los profesionales discrepan de verdad en los extremos. Los proyectos de código abierto con muchos colaboradores no fiables dependen de pull requests más largos y de la revisión, y los equipos regulados a veces necesitan ramas de lanzamiento explícitas para la auditoría. El principio que sobrevive al desacuerdo es el tamaño del lote: cuanto más pequeño es cada cambio, más fácil es revisarlo, probarlo, desplegarlo, diagnosticarlo y deshacerlo.

name: delivery
on:
  push:
    branches: [main]
env:
  IMAGE: registry.example.com/food/orders:${{ github.sha }}
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: make lint test              # fast feedback first
      - run: docker build -t "$IMAGE" . && docker push "$IMAGE"
  staging:
    needs: build
    runs-on: ubuntu-latest
    environment: staging
    steps:
      - uses: actions/checkout@v4
      - run: ./deploy.sh staging "$IMAGE" && ./smoke-test.sh staging
  production:
    needs: staging
    runs-on: ubuntu-latest
    environment: production            # can require an approval
    steps:
      - uses: actions/checkout@v4
      - run: ./deploy.sh production "$IMAGE" --canary 5
Un flujo de trabajo mínimo de entrega continua con la sintaxis de GitHub Actions: compilar y probar una vez, subir una imagen nombrada por el commit, desplegar esa imagen en staging y después en producción como canario. GitLab CI, Azure Pipelines, Jenkins y otros expresan las mismas etapas. Se omiten el inicio de sesión en el registro y los scripts de despliegue.

Estrategias de despliegue

Una estrategia de despliegue decide cómo sustituye la nueva versión a la antigua en producción y, por tanto, a cuántos usuarios puede perjudicar una versión defectuosa antes de que se detenga. Las estrategias difieren en la infraestructura adicional que necesitan, en la rapidez del rollback y en si se ejecutan dos versiones a la vez. Siempre que se ejecutan dos versiones a la vez, deben ser compatibles con los datos y los mensajes de la otra, y ese es el precio de todas las estrategias salvo la recreación.

Comparación de las estrategias de despliegue

EstrategiaCómo funcionaRiesgo para los usuariosRollbackCosto y complejidad adicionales
Recreación (recreate)Detener todas las instancias antiguas y luego arrancar las nuevas.Tiempo de inactividad durante el cambio; todos los usuarios se encuentran a la vez con una versión defectuosa.Volver a desplegar la versión antigua, con más tiempo de inactividad.Ninguno. Aceptable para herramientas internas, trabajos por lotes y ventanas de mantenimiento.
Gradual (rolling)Sustituir las instancias unas pocas a la vez (la opción por defecto de Kubernetes para los Deployments, con maxSurge y maxUnavailable ambos en un 25% por defecto).La exposición crece a medida que avanza el despliegue; las comprobaciones de estado detectan las caídas, pero no los errores sutiles.Se revierte desplegando de nuevo gradualmente la versión antigua, lo que tarda tanto como el despliegue.Bajo. Las versiones antigua y nueva se ejecutan en paralelo, así que deben ser compatibles.
Azul-verde (blue-green)Ejecutar un entorno nuevo completo (verde) junto al que está en producción (azul), probarlo y luego cambiar todo el tráfico en el router.Todos los usuarios pasan a la vez, pero el entorno nuevo se verificó antes del cambio.Rápido: volver a cambiar el router mientras el azul sigue en marcha.Hasta el doble de capacidad durante el cambio; las bases de datos compartidas deben funcionar con ambas versiones.
Canario (canary)Enviar una pequeña parte del tráfico (por ejemplo, un 1-5%) a la nueva versión, comparar sus métricas y luego ampliar por pasos.Solo la parte de usuarios del canario se encuentra con una versión defectuosa, y solo hasta que el análisis la detiene.Rápido: poner a cero el peso del canario.Necesita enrutamiento ponderado, buenas métricas y suficiente tráfico para que la comparación tenga sentido.
En sombra (dark launch)Copiar solicitudes reales a la nueva versión; sus respuestas se comparan o se descartan, nunca se devuelven.Ninguno directamente, siempre que los efectos secundarios (pagos, correos electrónicos, escrituras) se supriman o se simulen.No hay nada que revertir; los usuarios nunca dependieron de ella.El doble de carga en la ruta en sombra y un manejo cuidadoso de los efectos secundarios; ideal para rutas de lectura y reescrituras.

Martin Fowler describió el despliegue azul-verde en 2010, atribuyéndolo a Dan North y Jez Humble; el lanzamiento canario, llamado así por los canarios que llevaban los mineros para detectar gas, lo documentó Danilo Sato en el mismo sitio en 2014. En Kubernetes, las actualizaciones graduales vienen integradas; los lanzamientos azul-verde y canario suelen venir de un controlador de entrega progresiva (Argo Rollouts, Flagger) o de un service mesh y del enrutamiento ponderado de la Gateway API. En las plataformas gestionadas, las funciones equivalentes se llaman división del tráfico (traffic splitting) o ranuras de despliegue (deployment slots).

Lanzamiento canario con análisis automatizado

Lanzamiento canario con análisis automatizado: un router envía el 90 por ciento del tráfico a producción, el 5 por ciento a una línea base nueva de la versión antigua y el 5 por ciento al canario; un paso de análisis compara las métricas de línea base y canario, y amplía o reviertePúblicoRouterbalanceadoro service meshProducción v1la mayoríaLínea base v1nueva, mismo tam.Canario v2versión nueva90%5%5%Análisis canariocompara errores,latencia, saturaciónmétricasDecisiónpasa: ampliar a 25%falla: revertirfija los pesos de tráfico automáticamente
Comparar el canario con una línea base nueva de la versión antigua, en lugar de con la flota que lleva tiempo en marcha, elimina las diferencias causadas solo por el tiempo de actividad y las cachés ya calientes.

Separar el despliegue del lanzamiento con feature flags

El despliegue instala una nueva versión del software en un entorno; el lanzamiento pone un comportamiento a disposición de los usuarios. Tratarlos como un solo acontecimiento convierte cada despliegue en un acontecimiento de negocio, con todo el nerviosismo que eso conlleva. Los feature flags (feature toggles) los separan: el código nuevo se despliega desactivado, y el comportamiento se lanza más tarde, de forma gradual y reversible, cambiando la configuración. El artículo de Pete Hodgson Feature Toggles (aka Feature Flags) en martinfowler.com (2017) distingue cuatro categorías según cuánto tiempo viven y con qué dinamismo deciden.

Las cuatro categorías de feature toggle de Hodgson

CategoríaPropósitoVida típicaGrado de dinamismo
Toggles de lanzamientoEntregar en el trunk funcionalidades incompletas o no lanzadas, desactivadas.De días a unas pocas semanas; se eliminan tras el lanzamiento.Mayormente estáticos en cada versión.
Toggles de experimentoPruebas A/B o multivariantes que dirigen a cada usuario a una cohorte.El tiempo suficiente para obtener resultados estadísticamente sólidos; luego se eliminan.Por solicitud, según la cohorte del usuario.
Toggles de operacionesControles operativos, como desactivar un costoso panel de recomendaciones cuando hay mucha carga (interruptores de emergencia o kill switches).Mayormente cortos; unos pocos interruptores de emergencia se mantienen a largo plazo.Se cambian en tiempo de ejecución, a menudo durante un incidente.
Toggles de permisosFuncionalidades para usuarios concretos: niveles premium, probadores beta, personal interno.Pueden vivir años.Por solicitud, según el usuario.

Los flags tienen un costo de mantenimiento. Cada flag duplica los caminos por el código que protege, añade combinaciones de prueba y deja código muerto una vez que su decisión está tomada. Hodgson recomienda tratar los flags como un inventario: añadir una tarea de eliminación cuando se crea un toggle de lanzamiento, dar a los flags fechas de caducidad, añadir pruebas que fallen cuando un flag ha pasado su fecha y limitar cuántos pueden existir a la vez. La pérdida de Knight Capital en 2012, descrita en la sección 1.3, tuvo que ver con un flag reutilizado que reactivó código antiguo en un servidor que se había saltado un despliegue manual: un recordatorio de no reutilizar nunca los nombres de los flags y de borrar el código muerto que hay detrás de los flags ya decididos. A escala, los flags los sirve un servicio dedicado (opciones de código abierto como Unleash y Flagsmith, comerciales como LaunchDarkly, o la API neutral respecto al proveedor OpenFeature) para que un cambio se propague en segundos y quede auditado.

Cambios de base de datos en el pipeline

El código se puede revertir en segundos; los datos, no. Un despliegue que renombra una columna y luego se revierte deja al código antiguo frente a un esquema que no entiende. La solución, tratada en profundidad en evolución de esquemas, es hacer que cada cambio de esquema sea compatible hacia atrás con la versión del código que se está ejecutando, usando expandir y contraer: añade primero la nueva estructura, despliega código que escriba en ambas y lea de cualquiera, rellena los datos (backfill), cambia los lectores y elimina la estructura antigua solo en un lanzamiento posterior, cuando ya nada la use.

En el pipeline, esto significa que las migraciones son artefactos versionados que se ejecutan como un paso propio, antes de desplegar el código que las necesita, y que se prueban con una copia de los datos del tamaño de producción, para que un bloqueo en una tabla grande se descubra en staging y no a la hora de comer. Los pasos destructivos (eliminar columnas o tablas) se retrasan y se ejecutan por separado, porque son el único tipo de cambio que un rollback no puede deshacer. Una comprobación útil del pipeline hace fallar la compilación cuando una migración no es aditiva, salvo que esté marcada explícitamente como paso de contracción.

Entrega progresiva y análisis canario automatizado

La entrega progresiva, un término popularizado por James Governor, de la firma de análisis RedMonk, en 2018, combina canarios, feature flags y verificación automatizada: un cambio llega a públicos cada vez mayores y, en cada paso, es el sistema, no una persona que mira paneles, quien decide si continuar. La decisión usa el análisis canario automatizado: las métricas del canario (tasa de errores, percentiles de latencia, saturación, señales de negocio como los pedidos realizados) se comparan estadísticamente con una línea base. Netflix y Google publicaron como código abierto su motor de análisis, Kayenta, en 2018; Argo Rollouts y Flagger ofrecen pasos de análisis similares en Kubernetes.

Tres detalles deciden si se puede confiar en el análisis. Compara lo comparable: una línea base nueva de la versión antigua que recibe la misma parte del tráfico evita culpar a la nueva versión de diferencias causadas por cachés frías o reinicios recientes. Ten suficiente tráfico: con el 5% de un servicio que atiende diez solicitudes por minuto, una hora de canario ve treinta solicitudes, demasiado pocas para detectar una tasa de errores del 1%, así que los servicios con poco tráfico necesitan pasos más largos, carga sintética o una estrategia distinta. Elige métricas ligadas a los objetivos de nivel de servicio y a los resultados de negocio, porque una versión puede ser rápida y no tener errores mientras cobra en silencio una tarifa de envío incorrecta.

Rollback o roll forward

Cuando un lanzamiento sale mal, hay dos salidas. El rollback vuelve al artefacto anterior, lo que es rápido y no necesita código nuevo, siempre que la versión anterior siga funcionando con los datos actuales y con las versiones de los demás servicios. El roll forward (corrección hacia adelante) entrega una corrección a través del pipeline, lo que es más lento, pero a veces es la única opción, por ejemplo tras una migración de datos que no se puede revertir o un cambio del que ya dependen otros servicios.

Un buen criterio por defecto es revertir primero, diagnosticar después: restablece el servicio con la acción segura más rápida y luego investiga sin presión. Corregir hacia adelante bajo presión tiende a saltarse las comprobaciones del pipeline, y una corrección precipitada de un incidente en producción es una fuente clásica del siguiente incidente. El rollback solo es una opción real si se diseña desde el principio: conservar los artefactos anteriores, hacer que los cambios de esquema sean compatibles en ambas direcciones durante al menos una versión, que los mensajes los puedan leer consumidores antiguos y nuevos, y ejercitar con regularidad el propio camino de rollback. Un equipo que nunca ha hecho un rollback debería suponer que no puede hacerlo.

Ejemplo práctico

Ejemplo práctico: lanzar una nueva regla de tarifa de envío

El servicio de pedidos de la plataforma de reparto de comida va a cambiar la forma de calcular las tarifas de envío, usando la distancia y la demanda en lugar de una tarifa fija. El equipo usa desarrollo basado en trunk, un despliegue canario y un flag de lanzamiento.

CambioNuevo calculador de tarifas detrás de un flag de lanzamiento dynamic-delivery-fee, desactivado por defecto; una migración solo de expansión añade una columna que admite nulos, fee_rule_version.
Del commit al artefactoSe fusiona en main a las 10:02. Lint, pruebas unitarias y escaneos tardan 6 minutos; la imagen orders:4f1c2ab, con su SBOM y su firma, se sube a las 10:09.
MigraciónLa migración aditiva se ejecuta a las 10:15 como paso propio del pipeline. La versión en ejecución ignora la nueva columna, así que nada se rompe.
StagingLa misma imagen se despliega a las 10:16; las pruebas de contrato con los servicios de pagos y de restaurantes y las pruebas de humo pasan a las 10:31.
CanarioA las 10:35, el 5% del tráfico de producción va a la nueva versión, todavía con el flag desactivado. El análisis durante 20 minutos compara la latencia p99, la tasa de 5xx y el éxito de los pedidos con una línea base nueva: pasa.
Despliegue progresivoLos pesos pasan al 25%, al 50% y al 100% en pasos de 15 minutos; termina a las 11:40. El despliegue está completo y, sin embargo, ningún cliente ha visto la nueva tarifa.
LanzamientoAl día siguiente, el responsable de producto activa el flag para el 10% de los clientes de una ciudad y vigila la conversión de pedidos y las quejas; luego lo amplía a todas las ciudades a lo largo de una semana.
LimpiezaEl flag y el código de la tarifa fija se eliminan en el sprint siguiente; una migración de contracción posterior hace obligatoria la columna.

El riesgo del despliegue (¿funciona el código?) y el riesgo del lanzamiento (¿les gustan a los clientes las nuevas tarifas?) se gestionaron por separado, cada uno con su propio radio de impacto reducido.

En cada paso hasta la migración de contracción, la recuperación era un cambio de configuración o de peso en el router, no una corrección de emergencia. Del commit al despliegue completo en producción pasaron alrededor de 1 hora y 40 minutos.

Medir el pipeline

Las métricas DORA de entrega de software presentadas en la sección 2.6 (tiempo de entrega de los cambios, frecuencia de despliegue, tasa de fallos de los cambios, tiempo de recuperación de un despliegue fallido y tasa de retrabajo de despliegues) son en gran medida propiedades del pipeline y de la arquitectura en conjunto. Los lotes pequeños y el desarrollo basado en trunk acortan el tiempo de entrega y aumentan la frecuencia; las pruebas automatizadas y el análisis canario reducen la tasa de fallos de los cambios; el rollback rápido y los flags acortan el tiempo de recuperación. Mídelas por servicio, observa las tendencias en lugar de valores aislados y nunca las conviertas en objetivos individuales, lo que solo invita a manipularlas.

Comprueba lo que has entendido

¿Por qué es un problema recompilar el artefacto por separado para producción aunque el código fuente sea idéntico?

Las dependencias, las imágenes base o las herramientas de compilación pueden haber cambiado entre compilaciones, así que el artefacto de producción no es el que se probó; compila una vez y promueve el mismo artefacto.

¿Cuál es la diferencia entre desplegar una funcionalidad y lanzarla?

El despliegue instala el código en un entorno; el lanzamiento pone el comportamiento a disposición de los usuarios. Los feature flags permiten desplegar el código desactivado y lanzarlo más tarde, de forma gradual y reversible.

¿Por qué un canario en un servicio con poco tráfico da a menudo resultados poco fiables?

Una pequeña parte de poco tráfico produce demasiado pocas solicitudes para detectar diferencias en la tasa de errores o en la latencia con confianza estadística, así que hay que alargar los pasos, usar tráfico sintético o elegir otra estrategia.

¿Cuándo puede ser corregir hacia adelante la única opción?

Cuando el lanzamiento incluyó un cambio irreversible, como una migración destructiva, o cuando otros servicios ya dependen del nuevo comportamiento, de modo que la versión anterior ya no puede funcionar correctamente.

Siguiente · 10.6Multirregión y edgeCuándo y cómo operar en varias regiones: latencia, recuperación ante desastres y residencia de datos, las cuatro estrategias de DR con su RTO, RPO y costo, los datos entre regiones, el failover, las células para limitar el radio de impacto, las CDN y las funciones en el borde (edge functions).Continuar →

Fuentes y lecturas recomendadas

¿Tienes una pregunta sobre esta sección? ArchitectBot, el asistente de estudio con IA del curso, responde primero a partir del curso.

Pregunta: “Nuestro equipo despliega cada dos semanas con una lista de comprobación manual. ¿Qué cambios en el pipeline y en el despliegue deberíamos hacer primero para desplegar de forma segura varias veces al día?”