Saltar a contenido

Retirada, conservación y recuperación

El pipeline implementa destrucción mediante planes guardados y aprobación manual, en orden inverso al aprovisionamiento. La retirada de un laboratorio debe considerar tanto los recursos del estado como los creados por controladores Kubernetes o procedimientos externos.

Antes de planificar la retirada

  1. Identificar la cuenta o proyecto, proveedor, ENVIRONMENT, cuatro nombres de estado y el propietario de los recursos. Comprobarlos contra los recursos reales, no solo contra el nombre de un pipeline.
  2. Detener despliegues concurrentes de la aplicación y nuevas ejecuciones de infraestructura sobre ese entorno.
  3. Decidir qué datos deben conservarse. Crear y comprobar las copias de seguridad/exportaciones SQL necesarias antes de eliminar la base de datos.
  4. Conservar copias protegidas de los estados y de la configuración efectiva, incluyendo las versiones resueltas de proveedores y charts. No guardarlas en este sitio público.
  5. Retirar los recursos de entrada creados por controladores mientras esos controladores sigan funcionando. En AWS, revisar el Ingress de aplicación y esperar a que se eliminen ALB, targets y recursos asociados antes de retirar el controlador.
  6. Comprobar que ningún recurso ajeno a esta aplicación comparte los namespaces que se van a borrar. Eliminar el namespace app elimina también sus objetos no gestionados directamente por Terraform.

La contraseña de SQL, los tokens y los estados merecen controles de acceso, pero no sustituyen una copia de seguridad de los datos. Una copia del estado describe recursos; no contiene una restauración operativa de las tablas de la aplicación.

Comportamiento normal de los jobs

Ejecutar el pipeline de infraestructura sobre main, con PIPELINE_ACTION=destroy, CLOUD_PROVIDER explícito y el mismo ENVIRONMENT que identifica los estados correctos. Revisar cada plan antes de lanzar su apply manual.

Paso Plan y apply Dependencia que debe conservarse hasta terminar
1 plan_destroy_platform → apply_destroy_platform API del clúster y credenciales de acceso disponibles
2 plan_destroy_database → apply_destroy_database Red accesible y decisiones de conservación cerradas
3 plan_destroy_kubernetes → apply_destroy_kubernetes Red y permisos cloud disponibles
4 plan_destroy_network → apply_destroy_network Recursos dependientes ya retirados

No cambiar de nombre de estado ni de proveedor entre plan y apply. No reutilizar un plan si el estado cambió, si se reparó manualmente o si otro pipeline aplicó cambios. Si expiran los artefactos de una semana, generar y revisar un plan nuevo.

destroy no hace rollback de una versión de aplicación. Para volver a una imagen anterior, usar el proceso de despliegue y sus manifiestos; borrar la infraestructura elimina las bases de datos y la capacidad de ejecución.

Conservación configurada y sus límites

Servicio Defaults relacionados con retirada Consecuencia operativa
RDS deletion_protection=false, skip_final_snapshot=true, retención automática de 1 día El código permite eliminar la instancia sin snapshot final; preservar los datos necesarios antes del apply
Cloud SQL deletion_protection=false, backups y binary logs activos No se declara una exportación ni un proceso de conservación final independiente de la instancia
GKE deletion_protection=false El clúster no tiene este freno adicional en el código
Namespaces app y gitlab-agent gestionados por Terraform Su eliminación afecta a todos los objetos dentro de ellos
Certificado/DNS AWS Externos a las raíces inspeccionadas Necesitan revisión separada; no asumir que el destroy los gestiona

En RDS, poner solamente skip_final_snapshot=false no completa aquí una estrategia de snapshot final: el recurso no define un final_snapshot_identifier. Si se adopta esa política, añadir y validar la configuración necesaria antes de iniciar la retirada. No presentar un cambio aislado de variable como un mecanismo ya probado.

Caso excepcional: Private Service Access en GCP

El job force_unlock_gcp_database_private_service_access elimina del estado la dirección google_service_networking_connection.private_service_access. Su nombre es engañoso: no ejecuta tofu force-unlock. El comportamiento de state rm es olvidar la relación entre dirección de recurso y objeto remoto; el objeto remoto puede seguir existiendo.

Esto puede dejar un peering sin seguimiento y hacer que un plan posterior intente recrearlo. El job tampoco usa el patrón normal de exclusión mutua: fija resource_group: dev-gcp-database, aunque el backend se calcula con el ENVIRONMENT elegido. Además, la expresión shell termina con un mensaje de “no presente” en ciertos fallos, por lo que el resultado del job no sustituye la inspección del estado.

No es un paso de limpieza rutinaria. Ante un fallo de retirada de Private Service Access:

  1. Capturar el error concreto y comprobar si siguen existiendo instancias o servicios que usan la conexión.
  2. Verificar que el borrado de Cloud SQL ha terminado realmente y consultar el diagnóstico del proveedor.
  3. Conservar una copia protegida del estado y detener otros planes/applies.
  4. Decidir si corresponde esperar, eliminar una dependencia real, reparar/importar el vínculo o realizar una operación excepcional sobre el estado. Registrar el motivo y el objeto remoto afectado.
  5. Tras cualquier modificación de estado, descartar planes previos y generar uno nuevo. Inventariar el objeto en Google Cloud aunque ya no aparezca en el estado.

El repositorio no documenta el error original que motivó ese workaround. La documentación conserva el hecho observable y deja su justificación como decisión pendiente de confirmar con el autor.

Evidencia histórica y validación posterior

El pipeline 2604650152, del 16 de junio de 2026, registra éxito de apply_destroy_platform, apply_destroy_database, apply_destroy_kubernetes, apply_destroy_network y del job de Private Service Access. También aparecen dos ejecuciones de plan_destroy_database. Se ejecutó en un commit anterior al HEAD analizado.

Estos estados de jobs demuestran una ejecución histórica de retirada; no prueban el inventario cloud actual ni la ausencia de recursos huérfanos. Al cerrar una retirada se debe contrastar el estado con el inventario de la cuenta/proyecto, incluidos recursos creados indirectamente o retirados del estado.

Recursos que revisar por coste residual

AWS GCP
Clúster EKS y nodos EC2 Clúster GKE y nodos Compute Engine
RDS, backups o snapshots conservados Cloud SQL, backups/exportaciones conservados
NAT Gateway y direcciones asociadas Cloud NAT, Router y direcciones reservadas
ALB, targets y recursos del controlador Balanceadores o direcciones creados externamente
Volúmenes EBS y recursos fuera de las raíces Discos y recursos fuera de las raíces

No se proporciona una cifra de coste: depende de región, uso, cuotas, conservación y recursos reales, que no se consultaron en las cuentas cloud. El objetivo del inventario es cerrar la retirada sin confundir un pipeline verde con la ausencia total de recursos facturables.

Fuentes