Estrategias para desplegar con éxito en producción

Cuando se estudian las diferentes opciones a la hora de desplegar código en producción, uno de nuestros objetivos es que los despliegues se produzcan de forma ágil y fiable. De esta forma podremos desplegar con frecuencia manteniendo un proceso sencillo, controlado y nada traumático.

El hecho de aumentar la frecuencia de despliegue nos permitiría reducir la cantidad de nuevo código que se publica. Por eso, si hubiera algún problema, el error estaría lo más acotado posible (una de las ventajas de los ciclos de entrega y de despliegue continuo), además nos permitiría mejorar nuestra capacidad de reacción ante imprevistos.

En este post nos centraremos en el último paso de un ciclo de desarrollo: el momento en que se despliega el código testado correctamente en nuestro entorno de producción. Haremos hincapié en la estrategia, dando por supuesto que el escenario ideal es uno en el que los despliegues están automatizados.

Por desgracia, el modelo más habitual de despliegue es el de interrumpir el servicio, desplegar y restablecer el servicio esperando que todo funcione correctamente. Es de sentido común reconocer que no es la mejor forma de hacerlo

Sin embargo, antes de decantarse por una, hay que valorar el uso de una serie de estrategias en las que nos podemos basar para facilitar el despliegue. Veamos cada una de ellas.

Estrategias de despliegue

Rolling upgrade

Esta estrategia, de uso habitual en contenedores o con sistemas con orquestación como Kubernetes u Openshift, se basa en tener una capa de balanceo previa a la aplicación, ya sea con un F5, HAProxy o la propia capa integrada en el sistema de orquestación.

Al iniciar el proceso de despliegue, uno de los contenedores/instancias se saca del grupo de balanceo, se aplica la actualización (o se sustituye por otro contenedor/instancia actualizado) y se pasan los tests necesarios para garantizar que se ha actualizado correctamente y que todo funciona.

Una vez pasados los tests, se vuelve a incluir en el grupo de balanceo y se sigue con el siguiente.

Solo queda repetir el proceso hasta que todas las instancias/contenedores han sido actualizadas.

Los mayores inconvenientes de esta estrategia son:

  • En escenarios con muchas instancias/contenedores por actualizar puede ser un proceso muy lento.
  • Al ser un proceso simple repetido n veces, tiene más probabilidad de fallo y el rollback no es tan rápido como debería.
  • Puede haber un momento de inconsciencia al haber distintas versiones en producción. Por ejemplo, dos llamadas a un GET pueden devolvernos distintos valores, aunque es cierto que esta situación es puntual.

Blue/green

En los últimos años, gracias a la aparición de nuevas tecnologías, arquitecturas más flexibles y abaratamiento de costes, se está poniendo de moda el despliegue “blue/green”.

En esta estrategia de despliegue se tiene un entorno de producción oculto, a modo de entorno de staging, que es el que se utiliza para desplegar la nueva versión del código y, tras hacer las pruebas pertinentes de que todo se ha llevado a cabo correctamente, proceder a balancear todo el tráfico a este entorno dejando el anterior en oculto.

En caso de que algo saliera mal, volver a la versión anterior suele ser tan sencillo como volver a balancear la carga al anterior entorno.

Si todo va bien, el anterior entorno podrá reutilizarse para el despliegue de la siguiente versión.

Hay varias cosas que debemos tener en cuenta, pero el error más común es el de tratar de hacer la transición entre entornos con un cambio de DNS y el resultado más probable es el siguiente:

Esto puede ocurrir porque no todos los sistemas trabajan con servidores de DNS que respeten el TTL (time to live). Algunos, además, juegan con cachés, tienen sesiones abiertas, etc.

Para evitar estos posibles problemas, la estrategia más adecuada debe ser que el balanceador apunte a un set diferente de IPs correspondientes al entorno que pasa a ser producción.

No obstante, existen opciones válidas para hacerlo con DNS usando un DNS interno y forzando que todos los elementos internos sean fieles al TTL.

De esta forma, el cambio de entorno es responsabilidad del servidor interno de DNS.

Red/black

En 2013, Netflix escribió un post sobre cómo se hacían sus despliegues internamente. En él explican cómo usan un canary inicial para hacer una pequeña prueba en un entorno de producción (redirigiendo un 1% del tráfico y estudiando su comportamiento).

Red/black no deja de ser el nombre que le han dado a un blue/green deploy en Netflix pero, como la mayoría de cosas que hacen en Netflix, adaptado, mejorado y con ciertas peculiaridades.

De forma parecida a blue/green, teniendo en cuenta que en Netflix usan AWS como IaaS, lo que hacen es:

  1. Desplegar el nuevo código en un subset de instancias de producción, al que se redirige un pequeño porcentaje de tráfico de producción (~1%, por ejemplo). Esto es lo que se define como canary. Sobre este canary se comprobarán cosas como comportamiento ante carga, excepciones, códigos de respuesta, tiempos de respuesta, etc. En caso de que el comportamiento general sea adecuado (comparan más de 1000 métricas distintas), la AMI (Amazon Machine Images) correspondiente será la utilizada en los siguientes pasos.
  2. Generar un nuevo set de ASGs (Auto Scaling Group), con la AMI correspondiente al nuevo código. En esta fase solo está activo (red) el set de ASGs con el AMI de la versión v1.
  3. Dejar los dos sets de ASGs coexistiendo (red/red).
  4. Dejar de redirigir tráfico al set de ASGs antiguo, pero dejarlo encendido para minimizar el tiempo de rollback en caso de ser necesario (black).
  5. En caso de que todo vaya bien, eliminar el antiguo set de ASGs (red).

Conclusión

Hace poco recomendamos a un cliente una adaptación de rolling update y red/black. Debido a que tenía recursos muy limitados, era complicado poder implementar la estrategia de red/black y al tener un número muy reducido de instancias, una estrategia parecida a rolling upgrades no era descabellada.

La solución final fue proceder como en un rolling upgrades, pero controlando con QoS (Quality of Service) a nivel del balanceador, la cantidad de tráfico en producción que se le enviaba a cada nueva instancia actualizada aumentando gradualmente en caso de ir todo bien.

De este modo, éstas hacían de canary y en caso de error no se enviaba un porcentaje significativo de tráfico de producción a la instancia en fallo. Éste sería un buen ejemplo de adaptación de las estrategias al escenario.

Por lo tanto, llegamos a la conclusión de que no existe una única estrategia que sea óptima para todos los escenarios y siempre será mejor estudiar con calma nuestro caso concreto para ver cuál es la mejor forma de hacer los despliegues. Eso sí, tener en cuenta estas estrategias que acabamos de comentar como base nos ahorrará mucho tiempo y nos encaminará hacia el éxito.

Aunque acabé en el mundo de la administración de sistemas un poco de rebote, llevo ya 10 años de experiencia. Apasionado de las nuevas tecnologías, siempre he sido muy curioso y este sector es muy estimulante para cualquiera al que le encante aprender cada día.

Ver toda la actividad de Alfredo Espejel

2 comentarios

  1. Jose Huerta dice:

    Felicidades, por una explicación tan clara. Los gráficos ayudan mucho.

  2. Daniel Carretero dice:

    Sinceramente, bien explicado y sobre todo, bien definido. Aunque hay otras estrategias, que tienen un mayor porcentaje de errores, estas son muy validas para entornos Cloud. A nivel on premise, a veces, no es tan obvio ejecutarlo.

    Pero a mi particularmente, estas operaciones es el “how to” de cualquier administrador de un sistema en cloud.

    Felicidades por tan buen resumen!

Escribe un comentario