Article

El verde no es evidencia: las fallas de despliegue que nunca fallan

Seis defectos encontrados en una tarde en una plataforma. Ninguno falló de forma abrupta. Cada despliegue reportó éxito, y varios llevaban semanas ejecutándose así. Lo que tenían en común y los tres hábitos que los encontraron.
July 27, 2026
Topics:DeploymentCI/CDConfiguration ManagementObservabilityInfrastructure as Code

Una canalización de despliegue que falla de forma ruidosa está haciendo su trabajo. Los peligrosos son los despliegues que tienen éxito sin lograr nada.

Durante una sola tarde de mantenimiento en una plataforma, encontramos seis defectos distintos. Ninguno generó un error. Cada despliegue afectado terminó en verde. Varios llevaban semanas ejecutándose así; uno, más de un mes.

Resultaron ser el mismo error con seis disfraces.

Los seis

Un servidor DNS que se reiniciaba en cada despliegue. El archivo de zona interno derivaba su número de serie del reloj. Cualquier despliegue que cayera en una hora nueva generaba un archivo distinto en un byte, de modo que la herramienta de gestión de configuración reportaba un cambio y reiniciaba el resolutor. Ningún registro DNS había cambiado. Cada reinicio era una breve ventana en la que la resolución interna de nombres podía fallar, durante un despliegue, que es precisamente cuando otros pasos están resolviendo esos nombres.

Un contenedor de base de datos reemplazado en cada despliegue. Un paso de construcción se ejecutaba con la atestación de procedencia habilitada, que sella el manifiesto de la imagen en cada invocación. Una construcción completamente en caché, con cada capa reportando cero segundos, seguía produciendo un nuevo ID de imagen. El paso de convergencia hacía entonces exactamente aquello para lo que fue diseñado: adoptar la imagen cambiada y reemplazar el contenedor. El resultado era un arranque en frío de la base de datos en cada despliegue, en un sistema con una garantía explícita y documentada de que eso no ocurriría.

Un escaneo nocturno de seguridad que nunca se había ejecutado. El escáner de vulnerabilidades de contenedores resolvía su entorno de ejecución a través de una ruta de búsqueda que no lo contenía. Fallaba cada noche a las 4 a. m. en un registro que nadie leía. La corrección ya existía en un script hermano, completa con un comentario que explicaba la falla exacta. Nunca se había aplicado aquí.

Despliegues de staging que convergían producción. Una variable de configuración había sido renombrada. La automatización leía el nombre nuevo; las canalizaciones de despliegue seguían pasando el antiguo. La variable desconocida se ignoraba en silencio y el alcance volvía a su valor predeterminado, que era "todo". Los despliegues de staging habían estado convergiendo la pila de producción, y las promociones a producción la pila de staging, durante semanas. Ambos reportaban éxito.

Un indicador de configuración descartado al importar. Se agregó un ajuste nuevo, se validó contra su esquema y se exportó correctamente. El marco de contenido solo persiste las propiedades declaradas en la lista de exportación de una entidad, y la propiedad no se había agregado allí. El valor se escribía, se validaba y se desechaba. El comando de estado reportaba la entidad como permanentemente fuera de sincronía, lo que se lee como una advertencia sobre la que nadie actúa.

Una corrección aplicada a código que no se estaba ejecutando. Se hizo una mejora de seguridad en un complemento que resultó estar deshabilitado en la configuración. El cambio era correcto, estaba probado, revisado y era irrelevante. La ruta de código activa estaba en otro lugar por completo.

Lo que tienen en común

En cada caso el sistema reportó éxito, y el reporte era estrictamente cierto. El despliegue sí se ejecutó. La configuración sí se importó. La construcción sí se completó. El escáner sí se ejecutó.

Lo que ninguno reportó fue si el resultado previsto ocurrió.

Esa es la diferencia entre una verificación de proceso y una verificación de resultado, y la mayoría de la automatización solo hace la primera. Un código de salida le dice que un comando se ejecutó. No le dice que el comando hizo algo.

Las fallas ruidosas son las afortunadas

Un fallo abrupto se corrige. Interrumpe a alguien, produce un seguimiento de pila, cae en una alerta. El ciclo de retroalimentación se cierra en minutos.

Una operación nula silenciosa no tiene ciclo de retroalimentación. Se acumula. El escaneo de seguridad no se había ejecutado durante un número desconocido de semanas: el registro de errores se remontaba más atrás de lo que cualquiera había mirado. El error de staging-converge-producción era invisible precisamente porque el trabajo adicional solía ser inofensivo: la mayor parte del tiempo no cambiaba nada, así que no dejaba rastro.

Estos defectos también sobreviven a la revisión. Los revisores leen el cambio, no el tiempo de ejecución. Un parche aplicado a un complemento deshabilitado se ve idéntico en un diff a un parche aplicado a código activo.

La práctica que los detecta

Haga que "cambiado" signifique algo. En la gestión de configuración, un paso que reporta un cambio en cada ejecución no está reportando nada. Varios de estos errores se escondían detrás de pasos estructuralmente incapaces de reportar "sin cambios": un comando de shell sin condición adjunta siempre parece que hizo algo. Una vez corregidos, el cambio genuino se hizo visible de inmediato, porque era lo único que seguía moviéndose.

Haga que los artefactos generados sean funciones de sus entradas. El número de serie DNS se derivaba del reloj; la imagen del contenedor, de la marca de tiempo actual. Ninguno era una función de la cosa que describía. Cuando un archivo generado cambia solo cuando cambian sus entradas, "este archivo cambió" se convierte en una señal y no en ruido.

Verifique ejercitando el comportamiento, no leyendo códigos de salida. Esto es lo que más importa y lo que más se omite, porque es más lento. Para el indicador de configuración descartado, todos los indicadores disponibles estaban sanos: despliegue en verde, esquema válido, archivo correcto en disco. La única verificación que distinguía lo que funcionaba de lo que estaba roto era realizar una edición real de contenido y observar si el sistema respondía. No lo hizo.

Lo que cuesta

La verificación de resultados es más lenta que leer un código de estado. Ese es el intercambio honesto. Significa que alguien, o algo, hace lo que el sistema se supone que debe hacer y confirma el efecto, en lugar de confirmar que un comando terminó con cero.

La alternativa es un sistema en el que el tablero está en verde, las copias de seguridad están configuradas, el escáner está programado, los secretos están rotados, y algún subconjunto desconocido de todo eso no es cierto. La mayoría de las organizaciones no descubren cuál subconjunto hasta una auditoría, un incidente o una restauración.

Ninguno de estos seis causó una interrupción. Cada uno se encontró mirando más allá de una marca en verde. Cada uno seguiría ejecutándose de otro modo.