Curso exprés · No. 20

Dos ideas cambiaron cómo el software llega desde el portátil de un desarrollador hasta los usuarios reales. Primero, automatizar todo el camino desde el código hasta producción para que hacer un release sea aburrido en lugar de aterrador — eso es CI/CD. Segundo, empaquetar la app con todo lo que necesita para que funcione igual en todas partes — eso son los contenedores. Juntos convierten «funciona en mi máquina» de una excusa en el plan.

Solo lo esencial · Una imagen por idea · Aprende las palabras

§ 01

Escribir código es solo la mitad del trabajo; ponerlo de forma segura frente a los usuarios es la otra mitad. Durante mucho tiempo esa segunda mitad fue lenta, manual y aterradora — y entender por qué es la clave de todo lo que la arregla.

Los deploys manuales son lentos y aterradores

Un cirujano realizando una operación delicada a mano, de memoria, a medianoche, cansado — un solo resbalón y el paciente cae. Eso es un deploy manual a producción.

La vieja forma de enviar era un humano siguiendo pasos a mano: copiar archivos a un servidor, ejecutar algunos comandos, cruzar los dedos. Es lento, propenso a errores y tan arriesgado que los equipos hacen deploy rara vez — lo que hace que cada release sea enorme, lo que lo hace aún más arriesgado. Un deploy no es más que «poner en marcha la nueva versión», pero hecho a mano se convierte en el momento más estresante de la semana. Todo el campo de CI/CD existe para volver aburrido ese momento.

La trampa del 'funciona en mi máquina'

Una receta que sale perfecta en tu cocina y falla en la de otra persona — distinto horno, distinta harina, distinta altitud. La receta no era la historia completa.

El código que funciona bien en el portátil de un desarrollador a menudo se rompe en producción, porque los dos entornos difieren — distintas versiones, ajustes, librerías, sistema operativo. «Funciona en mi máquina» es el remate de toda una clase de bugs causados por estas brechas. El problema más profundo es que el portátil y el servidor no son el mismo lugar, así que «funcionó donde lo construí» no garantiza nada sobre dónde se ejecuta.

Hacer un release debería ser aburrido

Un ascensor en el que entras sin pensarlo, cien veces al día — porque está automatizado, probado y es seguro. Nunca usarías uno que necesitara un procedimiento manual y nervioso en cada viaje.

El objetivo de todo en este curso es volver el envío aburrido: tan automatizado, probado y repetible que haces releases de cambios pequeños muchas veces al día sin drama. De forma contraintuitiva, hacer deploy más a menudo es más seguro — cada release es diminuto, así que si algo se rompe, la causa es obvia y el arreglo es pequeño. Los releases raros, gigantes y manuales son los peligrosos. Aburrido es el mayor cumplido que un deploy puede ganar.

Los deploys manuales son lentos, arriesgados y raros — lo que los hace más arriesgados. El objetivo es lo contrario: un envío tan automatizado y pequeño que sea aburrido, hecho muchas veces al día.

§ 02

La primera mitad de CI/CD trata de detectar problemas en el instante en que aparecen, construyendo y probando automáticamente cada cambio a medida que llega — para que el código compartido siempre funcione.

Cada cambio se construye y se prueba automáticamente

Un corrector ortográfico que se ejecuta en cada frase mientras escribes, señalando el error de inmediato — no un revisor que encuentra cien errores un mes después, cuando todo está enredado.

Continuous integration (CI) significa que cada vez que alguien propone un cambio, un sistema automatizado construye el proyecto y ejecuta los tests sobre él — en minutos, sin que lo toque ninguna mano humana. Si el cambio rompe el build o falla un test, lo sabes al instante, mientras es pequeño y está fresco en tu mente. CI es un guardia siempre activo que revisa cada contribución antes de que pueda causar problemas.

Detecta la rotura mientras es pequeña

Notar un solo ladrillo colocado torcido es fácil de arreglar; descubrirlo solo después de construir tres pisos encima es un desastre. Temprano es barato; tarde es caro.

El valor de CI está en el momento. Un bug detectado en el instante en que se introduce es trivial de arreglar — sabes exactamente qué cambió. El mismo bug descubierto semanas después, enterrado bajo todo lo construido encima, puede llevar días desenredar. Al probar cada cambio de inmediato, CI mantiene los problemas diminutos y rastreables. Mueve el descubrimiento de la rotura de «mucho más tarde, mezclado con todo» a «ahora mismo, en aislamiento».

Mantén la rama main siempre funcionando

Una cocina compartida donde todos deben limpiar antes de irse — para que siempre esté lista para la siguiente persona, nunca un montón que alguien más tenga que ordenar primero.

El propósito más profundo de CI es mantener la rama main — la versión compartida y de confianza — siempre en estado funcional. Un cambio solo se une a main si construye y pasa los tests, así main nunca se convierte en un desastre roto que bloquea a todo el equipo. Esto es lo que hace posible un envío frecuente y seguro: cuando main siempre funciona, puedes hacer release desde ella en cualquier momento sin desenredar primero el trabajo roto y a medias de otra persona.

Continuous integration construye y prueba cada cambio en el momento en que llega, detectando la rotura mientras es pequeña y manteniendo la rama main siempre en estado funcional.

§ 03

Si CI se asegura de que cada cambio sea bueno, CD automatiza llevar ese cambio bueno a los usuarios — convirtiendo el release de un ritual manual en un botón, o en ningún botón.

Automatiza el release, no solo las pruebas

Una línea de fábrica que no se detiene en la inspección de calidad, sino que lleva el producto aprobado hasta el muelle de carga y al camión — sin nadie cargando cajas a mano.

Continuous delivery (CD) extiende CI: después de que un cambio pasa todas las comprobaciones automatizadas, el sistema además lo prepara automáticamente para el release y puede empujarlo a producción. Los pasos del deploy, manuales y propensos a errores, se vuelven código que se ejecuta igual cada vez. CI demuestra que el cambio es bueno; CD lleva ese cambio bueno a los usuarios sin que un humano teclee cuidadosamente comandos en un servidor a medianoche.

Delivery frente a deployment

Un paquete sellado, con dirección y esperando junto a la puerta frente a uno ya entregado al mensajero — ambos listos para salir, pero uno espera a que tú des la orden.

Hay una división sutil. Continuous delivery significa que cada cambio bueno se deja automáticamente listo para hacer deploy, pero un humano pulsa el botón para hacer el release. Continuous deployment va más allá: cada cambio que pasa se libera a producción automáticamente, sin botón alguno. Ambos son «CD»; la diferencia es si una persona aprueba el paso final. Los equipos eligen según cuánto confíen en sus comprobaciones automatizadas.

El artifact es lo que envías

Una caja sellada y etiquetada, empaquetada una vez y luego enviada, almacenada y entregada como una sola unidad — no rearmada a partir de piezas sueltas en cada parada.

El pipeline produce un artifact — un único paquete construido y versionado de tu aplicación, listo para ejecutarse. Lo construyes una vez y ese mismísimo artifact se mueve a través de testing, staging y producción, así que lo que probaste es exactamente lo que envías. Esto es clave para la fiabilidad: si reconstruyeras en cada etapa, podrían colarse diferencias sutiles. Un solo artifact, construido una vez, desplegado en todas partes, elimina toda una clase de sorpresas de «pero pasó en testing».

Continuous delivery automatiza el release de cada cambio bueno como un único artifact construido — ya sea que un humano pulse el botón final (delivery) o que se envíe solo (deployment).

§ 04

CI y CD los ejecuta un pipeline: una línea de ensamblaje automatizada por la que viaja un cambio, desde el commit hasta producción, deteniéndose si algo sale mal por el camino.

Un pipeline es una línea de ensamblaje automatizada

La línea de una fábrica de coches: el chasis avanza por soldadura, pintura e inspección en orden, cada estación haciendo su trabajo antes de pasarlo — ningún paso saltado, nada cargado a mano.

Un pipeline es la secuencia de etapas automatizadas por las que pasa un cambio en su camino a producción — normalmente build, luego test, luego deploy. Un commit entra por un extremo y, si todo está bien, sale un release en vivo por el otro, sin pasos humanos en medio. El pipeline es la máquina concreta que hace real a CI/CD: es donde «automatiza todo el camino» de verdad vive, como etapas definidas y repetibles.

Fail fast: detén la línea ante un problema

Una línea de ensamblaje con un cordón que cualquiera puede tirar para detenerlo todo en el instante en que aparece un defecto — mucho mejor que dejar que productos defectuosos rueden hasta el envío.

Un buen pipeline está construido para hacer fail fast: si el build se rompe o un test falla en cualquier etapa, el pipeline se detiene y el cambio no avanza más. Un cambio roto nunca llega a producción porque la línea se detiene en el momento en que se detecta. Esta es la propiedad de seguridad de todo el montaje — cada cambio debe pasar por cada puerta, y una sola luz roja detiene el release en seco. Nada defectuoso se cuela hasta los usuarios.

Verde es seguir, rojo es parar

Un semáforo en la línea: verde y el trabajo fluye; rojo y todo espera hasta que se resuelve el problema. Sin juicios de valor, solo una señal clara.

Los pipelines hablan en green (pasó) y red (falló). Un pipeline green significa que cada comprobación pasó y que el cambio es seguro para avanzar; uno red significa que algo se rompió y debe arreglarse antes de que nada se mueva. Esta señal sencilla reemplaza el juicio manual ansioso por una puerta inequívoca. La regla del equipo se vuelve fácil: nunca construir sobre red, nunca enviar sobre red — mantén el pipeline green y el envío se mantiene seguro por defecto.

El pipeline es la línea de ensamblaje automatizada del commit a producción — build, test, deploy — que hace fail fast y se detiene en red, para que ningún cambio roto se cuele.

§ 05

La otra mitad de la historia resuelve «funciona en mi máquina» directamente: empaqueta la app con todo lo que necesita en una unidad que funcione igual en todas partes. Esa unidad es un container.

Un container empaqueta la app con todo lo que necesita

El traje de un astronauta que lleva su propio aire, temperatura y presión — para que la persona trabaje igual ya sea en la estación o en el espacio abierto, llevando su entorno consigo.

Un container agrupa tu aplicación junto con todo lo que necesita para ejecutarse — el código, las librerías, los ajustes, las versiones correctas — en una sola unidad autocontenida. Como lleva su propio entorno, funciona igual donde sea que lo pongas: tu portátil, un servidor de pruebas, producción. El container no depende de lo que esté instalado en el host, así que las brechas que causan «funciona en mi máquina» simplemente se cierran.

El contenedor de carga que le dio nombre

El contenedor de carga de acero: cualquier puerto, barco o camión lo maneja igual porque la caja es estándar, sin importar lo que haya dentro. La carga del mundo se mueve sobre esa única idea.

El nombre es la metáfora. Antes de los contenedores de carga estándar, la mercancía se cargaba pieza a pieza de forma torpe; la caja estándar permitió que cualquier grúa y cualquier barco manejaran cualquier carga de forma idéntica. Los containers de software hacen lo mismo para las aplicaciones: una unidad estándar que cualquier sistema compatible puede ejecutar sin importarle lo que hay dentro. Docker es la herramienta que lo volvió mainstream. Estandarizar la caja es lo que hace que toda la cadena logística — tu pipeline — funcione con fluidez.

Image frente a container: receta y plato

Una receta frente a la comida cocinada a partir de ella: una es el conjunto fijo de instrucciones, la otra es una instancia concreta de la que puedes hacer muchas, todas idénticas.

Dos palabras se confunden. Una image es el plano congelado y empaquetado — el artifact construido que contiene tu app y su entorno, esperando en almacenamiento. Un container es una instancia en ejecución arrancada a partir de esa image. Una image puede lanzar muchos containers idénticos, igual que una receta hace muchos platos idénticos. Construyes la image una vez en tu pipeline, y luego ejecutas tantos containers a partir de ella como necesites — y cada uno es igual.

Un container empaqueta una app con todo lo que necesita, para que funcione igual en todas partes. Construyes una image una vez (la receta) y ejecutas containers idénticos a partir de ella (el plato).

§ 06

Ejecutar un container es fácil. Ejecutar cientos a través de muchas máquinas — mantenerlos sanos, escalarlos, actualizarlos sin downtime — necesita un director. Eso es orchestration.

Orchestration ejecuta muchos containers a través de muchas máquinas

Un controlador aéreo gestionando un cielo lleno de aviones — decidiendo cuál aterriza dónde, redirigiendo alrededor de los problemas, manteniendo cientos de piezas en movimiento seguras y coordinadas.

Una vez que tienes muchos containers repartidos por una flota de servidores, algo debe decidir dónde se ejecuta cada uno, reiniciar los que mueren y equilibrar la carga. Eso es orchestration, y la herramienta dominante es Kubernetes. Le dices el estado deseado — «ejecuta cinco copias de este servicio» — y trabaja de forma continua para que la realidad coincida, colocando containers, vigilándolos y corrigiendo la deriva. Es el director que coordina toda la orquesta de containers.

Self-healing y escalado vienen integrados

Un termostato que ajustas a una temperatura objetivo: detecta constantemente la habitación y se ajusta por su cuenta, sin que vuelvas a tocarlo. Declaras la meta; él la mantiene.

Orchestration es declarativo: describes la meta, no los pasos. Di «mantén siempre cinco copias sanas en ejecución», y si una se cae, el sistema arranca un reemplazo automáticamente — self-healing. Si el tráfico se dispara, puede añadir más copias y quitarlas cuando la demanda baja — auto-scaling. Dejas de cuidar servidores a mano y en su lugar declaras lo que quieres, dejando que el orchestrator mantenga el sistema ahí. Ese cambio de hacer a declarar es el corazón de todo esto.

Los rolling updates envían sin downtime

Cambiar los neumáticos de un camión en marcha uno a uno, para que nunca tenga que parar — el vehículo sigue rodando mientras cada pieza se reemplaza debajo de él.

Orchestration te permite actualizar sin downtime mediante un rolling update: reemplaza los containers viejos por nuevos de pocos en pocos, comprobando que cada uno está sano antes de continuar, así el servicio se mantiene arriba todo el tiempo. Si una nueva versión se comporta mal, puede detenerse y hacer rollback a la antigua automáticamente. Así es como los servicios modernos envían actualizaciones de forma continua sin una ventana de mantenimiento — el cambio ocurre en vivo, de forma gradual y reversible.

Orchestration (Kubernetes) ejecuta muchos containers a través de muchas máquinas: declaras el estado deseado, y hace self-healing, auto-scaling y despliega actualizaciones sin downtime.

§ 07

Toda esta maquinaria existe para hacer que el envío sea seguro y frecuente. Los hábitos finales tratan de reducir el radio de impacto de cualquier release — porque el deploy más seguro es uno que puedes deshacer.

Ten siempre un camino de vuelta: rollback

Un documento con deshacer: haces un cambio audaz sabiendo que una sola tecla restaura la versión anterior, así que experimentas con libertad en lugar de temer cada edición.

La propiedad de seguridad más importante es el rollback — la capacidad de volver al instante a la última versión buena conocida cuando un release sale mal. Como el pipeline envía artifacts versionados, volver atrás es simplemente volver a hacer deploy del anterior. Saber que puedes deshacer un deploy en segundos es lo que hace seguro el envío frecuente: una versión mala es un parpadeo menor y reversible en lugar de una crisis. Nunca envíes algo que no puedas retirar.

Reduce el radio de impacto: canary y blue-green

Probar un plato nuevo con unos pocos invitados dispuestos antes de servirlo a todo el banquete — si está mal, solo unos pocos lo notan, y no has perdido nada.

Dos patrones reducen el riesgo de un release. Un deploy canary envía la nueva versión primero a una pequeña porción de usuarios; si sus métricas se mantienen sanas, la despliegas a todos, y si no, la retiras habiendo afectado a casi nadie. Blue-green mantiene dos entornos de producción y cambia el tráfico del antiguo (blue) al nuevo (green) todo a la vez, con un cambio de vuelta instantáneo si hace falta. Ambos convierten un release de una apuesta de todo o nada en un paso controlado y reversible.

Describe tu infraestructura como código

Un plano con el que puedes reconstruir toda la casa exactamente, frente a una casa construida de memoria que nadie puede reproducir si se incendia.

La misma disciplina se extiende a los servidores mismos. Infrastructure as code (IaC) significa definir tus servidores, redes y configuración en archivos en lugar de hacer clic por una consola a mano. Ahora todo tu entorno está versionado, es revisable y reproducible — puedes reconstruirlo de forma idéntica, y los cambios pasan por el mismo pipeline que el código. Cierra la última brecha donde «alguien cambió un ajuste a mano y lo olvidó» podría deshacer todo el rigor de todo lo demás.

Antes de confiar en un proceso de deploy
  • ¿Está automatizado de extremo a extremo — del commit a producción a través de un pipeline, no a mano? - ¿CI construye y prueba cada cambio, manteniendo main siempre funcionando? - ¿Lo que envías es un único artifact o container, idéntico de test a prod? - ¿Puedes hacer rollback al instante a la última versión buena? - ¿Los releases arriesgados salen de forma gradual — canary o blue-green, no todo a la vez? - ¿La infraestructura misma es código — versionada y reproducible?
Las palabras que ahora dominas
  • deploy / release — poner en marcha una nueva versión para los usuarios. - CI (continuous integration) — construir y probar automáticamente cada cambio. - CD (continuous delivery / deployment) — automatizar el release; con botón, o sin botón. - pipeline / build / artifact / fail fast — la línea automatizada, su salida y su seguridad. - container / image / Docker — la app con su entorno, el plano, la herramienta. - orchestration / Kubernetes / self-healing / rolling update — ejecutar containers a escala, de forma segura. - rollback / canary / blue-green / infrastructure as code — los patrones de un deploy seguro.
Señales de que envías bien
  • Hacer un release es aburrido — pequeño, automatizado y hecho a menudo, no un evento raro y aterrador. - CI está green antes de que nada se fusione, y main siempre funciona. - Envías el mismo artifact/container que probaste, hasta producción. - Un release malo es un rollback rápido, no una crisis. - Los cambios arriesgados salen por canary o blue-green, y tu infra es código.

El envío seguro es envío reversible: automatiza el pipeline, envía un único artifact probado, mantén un rollback de un clic, libera los cambios arriesgados de forma gradual y define la infraestructura como código.

Fin del curso exprés · 7 capítulos · aprende las palabras

Después viene la práctica: toma un proyecto pequeño, escribe un Dockerfile para que se ejecute en un container, y monta un pipeline que lo construya y lo pruebe en cada cambio. Luego haz su deploy, rómpelo y haz rollback. Toda la filosofía encaja en el momento en que un release deja de dar miedo porque sabes que la línea lo detuvo y que puedes deshacerlo. Pero mantén una idea por encima del resto: enviar debería ser aburrido. Automatiza el camino para que cada cambio se construya, se pruebe y sea desplegable de la misma forma, y empaqueta la app para que funcione igual en todas partes — y «funciona en mi máquina» por fin se convierte en «funciona en todas partes».