Módulo 6: Rollback And Safety Nets

2. Qué significa rollback para infraestructura

Descripción

Esta lección desarrolla, con precisión completa, la distinción que la introducción del módulo dejó planteada: el rollback de infraestructura no es una operación de Terraform, es un patrón que combina Git (revertir un commit) con el pipeline que ya construiste (dejar que ci.yml/apply.yml corran de nuevo, en sentido contrario). Vas a ver el mecanismo completo, paso a paso, antes de ejecutarlo de verdad en la lección 3.

Conexión con el módulo

La lección 1 nombró la diferencia entre rollback de aplicación y rollback de infraestructura, en general. Esta lección la desarrolla a fondo: qué significa exactamente "revertir un commit de HCL", por qué eso es suficiente para deshacer un cambio de infraestructura, y dónde termina la responsabilidad de esta guía frente al rollback de una aplicación que corre sobre esa infraestructura. La lección 3 toma este mecanismo y lo corre de verdad, sobre un commit real de andes-cargo-infra/.


Analogía: deshacer una remodelación siguiendo los planos al revés, no apretar Ctrl+Z

Imagina que un arquitecto entrega los planos de una remodelación de oficina: mover una pared, agregar una puerta, cerrar una ventana. El contratista construye exactamente eso. Una semana después, alguien decide que la pared nunca debió moverse. No existe un botón "deshacer" en la obra física — nadie puede apretar Ctrl+Z sobre una pared de verdad. Lo que sí existe es un segundo juego de planos: la versión anterior de los planos, la que describía la oficina antes del cambio. El contratista vuelve a esa oficina con esos planos viejos, y construye exactamente lo que describen — que, en este caso, significa deshacer la pared nueva y devolver todo a como estaba.

Eso es, con precisión, lo que hace git revert sobre un commit de infraestructura. No existe un mecanismo que le diga a AWS (o a LocalStack) "olvida lo último que hiciste" — lo que sí existe es el commit anterior de HCL, la descripción de cómo debía verse la infraestructura antes del cambio. git revert no anula el cambio directamente sobre la nube: crea un nuevo commit, cuyo contenido es exactamente el opuesto del commit que se quiere deshacer, y deja que el mismo pipeline —el mismo contratista, con el mismo proceso— construya lo que ese nuevo commit describe.


El mecanismo completo, en cuatro pasos

   ①  Un commit malo ya está en main
       (ej: se agregó un tag que resulta ser incorrecto)
            │
            ▼
   ②  git revert <hash-del-commit-malo>
       crea un COMMIT NUEVO, cuyo diff es el OPUESTO exacto
       (no borra el commit malo del historial — lo compensa)
            │
            ▼
   ③  ese commit nuevo pasa por ci.yml, como cualquier otro
       terraform plan calcula: "esto es lo que hace falta
       cambiar para volver al estado anterior"
            │
            ▼
   ④  una persona revisa ese plan (el mismo proceso de siempre)
       y, si lo aprueba, apply.yml lo aplica
       → la infraestructura vuelve al estado que tenía
         antes del commit original

Fíjate en el detalle más importante de este diagrama, el que distingue git revert de otras formas de "deshacer" en Git: el commit original nunca desaparece del historial. git revert no es lo mismo que git reset (que mueve el puntero de la rama hacia atrás, como si el commit nunca hubiera existido) ni lo mismo que editar el historial a mano (git rebase -i, reescribiendo commits pasados). git revert agrega un commit nuevo, hacia adelante, que compensa el anterior — el historial completo, incluido el error, queda intacto y auditable para siempre. Esto no es un detalle técnico menor: es, literalmente, la misma razón por la que este módulo insiste tanto en la auditabilidad (lección 5) — un historial que nunca se reescribe es un historial que se puede confiar.


Por qué esto es suficiente: el plan calcula el camino de vuelta por ti

Aquí está el punto que hace que este patrón funcione sin que tengas que pensar en "cómo deshacer" cada tipo de cambio distinto: no tienes que calcular manualmente qué comandos deshacen un cambio. Terraform ya sabe comparar el HCL contra el state y calcular la diferencia — es exactamente lo que hace terraform plan en cada corrida de ci.yml, desde el Módulo 3. Si el HCL revertido describe el estado anterior, el plan sobre ese HCL revertido automáticamente calcula "lo que hace falta cambiar para llegar ahí" — sin que nadie tenga que escribir, a mano, el comando inverso de "agregar el tag" (que sería "quitar el tag") para cada tipo de cambio posible.

Esto es, en el fondo, la misma ventaja declarativa que ya aprendiste en terraform-and-iac-guide: describes el estado deseado, no la secuencia de pasos para llegar ahí. Un rollback, bajo este modelo, no es más que "cambiar cuál es el estado deseado, de vuelta al anterior" — y dejar que la misma maquinaria (el mismo plan, el mismo apply) haga el resto.


Frontera: esto NO es rollback de aplicación

Vale la pena ser preciso aquí, porque el mismo término —"rollback"— significa algo estructuralmente distinto en el mundo de las aplicaciones que corren sobre esta infraestructura:

Rollback de infraestructura (este módulo)Rollback de aplicación
Qué se revierteEl HCL que describe recursos (buckets, tablas, roles)El artefacto que corre (una imagen de contenedor, un binario desplegado)
Mecanismogit revert del commit de HCL + el mismo pipeline (plan/apply)Volver a apuntar el runtime a una versión anterior ya construida (v41 en vez de v42)
Qué hace falta que ya existaNada nuevo — el HCL revertido describe todo lo necesarioEl artefacto anterior (la imagen v41) tiene que seguir disponible en algún registro
Dónde se enseñaAquí (cicd-and-gitops-on-aws-guide)kubernetes-and-eks-in-production-guide, aws-serverless-and-containers-guide

Andes Cargo, en esta guía, nunca despliega una "aplicación" en el sentido de un servicio corriendo con versiones — despliega infraestructura: un bucket, una tabla, roles IAM, una función Lambda empaquetada como parte del apply, no como un servicio versionado de forma independiente. Si en el futuro Andes Cargo agrega un servicio de backend corriendo en contenedores sobre EKS (el tema de kubernetes-and-eks-in-production-guide), ese servicio tendría su propio mecanismo de rollback —basado en volver a una imagen de contenedor anterior, no en revertir HCL—, coexistiendo con el mecanismo que aprendes aquí, sin reemplazarlo. Ambos mecanismos son reales, ambos importan, y ninguno sustituye al otro: el HCL de Andes Cargo seguiría necesitando su propio git revert incluso si esa aplicación adicional tuviera un rollback de contenedor completamente distinto.


Errores comunes

Pensar que git revert "restaura" la infraestructura directamente (conceptual, el error más importante de esta lección). Qué pasa: alguien corre git revert y espera que la infraestructura cambie en ese mismo instante, sin que nada más suceda. Cómo detectarlo: si esperas ver algo distinto en LocalStack/AWS inmediatamente después de correr git revert, antes de que cualquier pipeline haya corrido. Cómo corregirlo: git revert solo crea un commit nuevo — es exactamente tan "inerte" como cualquier otro commit de HCL hasta que ci.yml calcula un plan sobre él y apply.yml lo aplica de verdad. El cambio real en la infraestructura ocurre en el mismo punto de siempre: cuando apply.yml corre, no cuando se crea el commit.

Confundir git revert con git reset (de Git, general pero crítico en este contexto). Qué pasa: alguien, buscando "deshacer un commit" en Git, encuentra git reset --hard HEAD~1 y lo usa en vez de git revert. Cómo detectarlo: si el commit original desaparece del git log en vez de aparecer un commit nuevo que lo compensa. Cómo corregirlo: git reset mueve el puntero de la rama hacia atrás, como si el commit nunca hubiera existido —destruye el historial de lo que pasó, además de ser peligroso sobre una rama ya compartida/fusionada—. git revert es la elección correcta para este patrón porque preserva el historial completo: el error queda registrado, y también su corrección, ambos con autor y fecha, para siempre.

Buscar un comando de Terraform que "deshaga" el último apply (conceptual, revisita la lección 1). Qué pasa: alguien busca algo como terraform apply --undo o similar. Cómo corregirlo: como ya viste en la lección 1, ese comando no existe. El "deshacer" completo de este patrón vive en Git (el commit revertido), no en ningún flag nuevo de Terraform — Terraform simplemente calcula el plan/apply sobre el HCL que le des, sin importar si ese HCL es "nuevo" o "una versión anterior recreada por un revert".


Ejercicios

Ejercicio 1 — Explica por qué git revert no borra el error del historial, y por qué eso es una ventaja, no una limitación. En dos o tres frases, a un colega que preferiría "que el error simplemente desaparezca".

Ver solución

Una respuesta completa suena, más o menos, así: "Si el commit malo desapareciera del historial, también desaparecería la evidencia de qué pasó, quién lo propuso, quién lo aprobó, y cuándo — exactamente el tipo de información que la lección 5 de este módulo (y la lección 2 del Módulo 1) ya identificó como lo que un pipeline agrega sobre un cambio manual. git revert preserva ambos commits, el error y su corrección, como parte del mismo historial auditable — cualquiera puede reconstruir después qué pasó, sin depender de la memoria de nadie."

Ejercicio 2 — Predice el plan de un revert antes de correrlo. Si un commit agregó un tag Compliance a un bucket (como el que ya viste en el Módulo 3), y revertís ese commit, ¿qué tipo de cambio esperarías ver en el plan resultante: una creación, una actualización, o una destrucción? Justifica.

Ver solución

En un proyecto con infraestructura ya aplicada (un apply real completado), esperarías ver una actualización (~ update in-place): el atributo tags del bucket cambiaría, quitando Compliance, sin que el bucket completo se cree ni se destruya — el mismo tipo de símbolo ~ que ya viste en el Módulo 5 (lección 7) para un cambio de atributo sobre un recurso existente. Ojo con la trampa: en un proyecto sin ningún apply real completado (el caso de esta máquina, sin LOCALSTACK_AUTH_TOKEN), el plan seguiría mostrando una creación completa (+ create) para todos los recursos, porque el state no tiene nada contra qué comparar — la lección 3 confirma esto con salida literal.

Ejercicio 3 — Ubica un ejemplo de rollback de aplicación de tu propia experiencia (o imaginado) y compáralo con este patrón. Describe, en un párrafo corto, un caso donde "volver a una versión anterior" signifique reactivar un artefacto ya construido, y explica por qué ese mecanismo no serviría para deshacer un tag en un bucket de S3.

Ver solución

Un ejemplo típico: una aplicación web desplegada como imagen de contenedor en Kubernetes, donde un kubectl rollout undo vuelve a apuntar el Deployment a la imagen de la versión anterior, ya construida y disponible en el registro de contenedores. Ese mecanismo funciona porque existe un artefacto completo y listo para activarse de la versión anterior. No serviría para deshacer un tag de S3 porque no hay ningún "artefacto" de infraestructura: un bucket no es una imagen versionada que se pueda "reactivar" — es un recurso vivo, modificado en el lugar, cuya única descripción de "cómo se veía antes" vive en el HCL de un commit anterior, no en ningún registro de artefactos.


Resumen y siguiente paso

En esta lección desarrollaste el mecanismo completo del rollback de infraestructura: git revert crea un commit nuevo (no borra el original), ese commit pasa por el mismo ci.yml/apply.yml que cualquier otro cambio, y terraform plan calcula automáticamente el camino de vuelta al estado anterior, sin que nadie tenga que escribir a mano el comando inverso. También trazaste la frontera exacta con el rollback de aplicación —volver a un artefacto ya construido—, un mecanismo distinto que vive en kubernetes-and-eks-in-production-guide y aws-serverless-and-containers-guide.

Antes de avanzar deberías poder: explicar la diferencia entre git revert y git reset; predecir qué tipo de cambio (+/~/-) esperarías ver en el plan de un revert, según si hay o no infraestructura ya aplicada; y ubicar con precisión la frontera entre este módulo y el rollback de aplicación.

La lección 3 —manos a la obra— ejecuta todo esto de verdad: un git revert real sobre andes-cargo-infra/, con ci.yml calculando el plan del revert y apply.yml intentando aplicarlo.

Recursos

  1. Git Docs — git revert — documentación oficial, incluida la distinción con git reset.
  2. Git Docs — git reset — para comparar directamente los dos mecanismos.
  3. Terraform Docs — Command: plan — el mecanismo que calcula automáticamente el "camino de vuelta", ya citado desde el Módulo 3.
  4. Módulo 5 de esta guía (07-hands-on-running-the-drift-job-manually.md) — el ejemplo de ~ update in-place que la solución del Ejercicio 2 reutiliza.