La pirámide de pruebas del código de infraestructura

El formato y la validación son gratis, el análisis estático es casi gratis, la política sobre el plan es barata, y las pruebas reales que aplican y destruyen son caras y lentas. Gasta en consecuencia, y ten claro qué no caza cada capa.

El código de infraestructura tiene una propiedad inusual: lo que produce es caro de crear, caro de destruir e imposible de simular del todo. Eso hace inútil el consejo habitual sobre cobertura de pruebas, y es la razón de que la mayoría de los equipos acaben o sin nada o con una suite de integración elaborada que tarda cuarenta minutos y se acaba desactivando.

La versión viable es una pirámide, donde cada capa es aproximadamente diez veces más barata que la de encima y caza una clase distinta de error.

Capa uno: formato y validación, gratis

Comprobación de formato y validación en integración continua, en cada pull request. El formato elimina toda una categoría de ruido en las diferencias y la discusión sobre estilo. La validación caza errores de sintaxis, tipos que no encajan, variables sin declarar y argumentos obligatorios que faltan, sin tocar un proveedor de nube.

Esto cuesta segundos y ninguna credencial. No hay razón para no tenerlo, y un número sorprendente de repositorios no lo tiene.

Añade bloques de validación de variables en el propio código ya que estás. Una restricción de que el nombre de entorno tiene que ser uno de tres valores, o de que un número de instancias tiene que estar en un rango, convierte un fallo en tiempo de ejecución en uno inmediato con un mensaje legible.

Capa dos: análisis estático, casi gratis

Los escáneres de seguridad y corrección leen la configuración y marcan patrones conocidos como malos: un cubo sin cifrado, un grupo de seguridad abierto al mundo, una base de datos sin protección contra borrado, un volumen sin cifrar.

Checkov y sus equivalentes cubren bien los errores de configuración habituales y forman parte del conjunto estándar de ocho herramientas libres para postura cloud. Se ejecutan en segundos, no necesitan credenciales y cazan los errores que constituyen la mayoría de los hallazgos reales.

Dos prácticas deciden si esta capa sobrevive. Empieza en modo informe y arregla el atraso antes de bloquear, o la primera ejecución produce cuatrocientos hallazgos y todo el mundo aprende a ignorar la herramienta. Y gestiona bien las supresiones: una excepción en línea con un motivo escrito está bien, una lista global de saltos es la forma en que el escáner se vuelve decorativo.

Capa tres: política sobre el plan, barata y desaprovechada

Es la capa que a la mayoría de los equipos les falta, y donde está el mejor retorno.

La salida del plan en JSON es una descripción completa de lo que está a punto de cambiar, y puedes hacer aserciones contra ella sin aplicar nada. Eso te permite comprobar cosas que el análisis estático no puede ver, porque dependen de los valores resueltos: que no se esté destruyendo ningún recurso en producción, que el tipo de instancia esté en la lista aprobada, que todos los recursos lleven las etiquetas obligatorias, que el cambio no supere un umbral de coste.

Escribe las reglas con un motor de política, en el mismo lenguaje que tu control de admisión si ya tienes uno, que es el argumento de coherencia de Kyverno o Gatekeeper. O haz las aserciones directamente sobre el JSON con un script; la lógica importa más que la herramienta.

La regla de mayor valor para empezar: rompe la compilación si el plan destruye o reemplaza algo en un espacio de trabajo de producción sin una anulación explícita. Esa única comprobación evita el error más caro que esta herramienta es capaz de cometer, y lleva una tarde.

El coste pertenece también a esta capa, como una diferencia en el pull request y no como una sorpresa en la factura, que es el argumento de el coste se decide en el pull request.

Capa cuatro: pruebas unitarias sobre la lógica de los módulos

El marco de pruebas nativo de Terraform ejecuta aserciones basadas en el plan contra un módulo con unas entradas dadas, comprobando que el plan resultante tiene las propiedades que esperas. No se crea infraestructura.

Merece la pena para módulos con lógica real: creación condicional de recursos, expresiones de iteración complejas, nombres calculados, o una variable que cambia varios valores aguas abajo. No merece la pena para un módulo que crea un recurso a partir de una variable, donde la prueba repetiría el código.

Escribe las pruebas como escenarios que el directorio de ejemplos del módulo pueda compartir, para que los ejemplos sigan funcionando y las pruebas sigan siendo realistas.

Capa cinco: pruebas de integración que aplican de verdad

Crear la infraestructura, hacer aserciones contra la cosa real, destruirla. Es la única capa que caza los fallos que más importan: un comportamiento del proveedor distinto de la documentación, un permiso que falta en el momento de aplicar, dos recursos que no pueden coexistir, un problema de consistencia eventual que vuelve inestable una aplicación.

También es lenta y cara. Un ciclo completo de aplicar y destruir sobre un módulo de red son minutos, a veces decenas de minutos, y cuesta dinero real en cada ejecución.

Así que resérvala para el número pequeño de módulos fundacionales donde un defecto sale caro: el de red, el de clúster, el de identidad. Ejecútala al fusionar o por la noche, no en cada empuje.

Dos cosas marcan la diferencia entre una suite que sobrevive y una que se desactiva. Una limpieza fiable, porque una prueba fallida que deja recursos detrás cuesta dinero y acaba agotando una cuota; usa un desmontaje diferido y ejecuta un barredor programado que borre todo lo que haya en la cuenta de pruebas con más de un día. Y una cuenta o suscripción de pruebas dedicada, nunca un entorno compartido, para que el barredor pueda ser implacable.

Entornos efímeros y su coste real

Levantar un entorno completo por pull request es atractivo y funciona bien para cambios de aplicación sobre infraestructura estable.

Para cambios de infraestructura es más difícil de lo que parece. Algunos recursos tardan mucho en crearse, algunos tienen cuotas a nivel de cuenta que una docena de entornos simultáneos agota, algunos tienen nombres que deben ser únicos globalmente, y algunos no se pueden destruir limpiamente sin intervención manual.

Donde encaja, encaja bien. Donde no, un entorno de preproducción compartido y de larga vida que recibe los cambios primero es la alternativa honesta, y es con lo que acaban casi todos los entornos.

La deriva es la prueba que corre en producción

Nada de lo anterior te dice si la realidad sigue coincidiendo con el código. Un plan programado contra cada espacio de trabajo de producción, con alerta cuando el plan no sale vacío, es la prueba continua más barata que puedes ejecutar y caza el cambio por consola que nadie mencionó.

Espera ruido al principio de recursos que cambian legítimamente fuera de Terraform. Suprímelos a conciencia con la instrucción de ignorar cambios en vez de ignorar la alerta, y la señal se vuelve fiable. Los patrones de estado y pipeline de los que depende esto están en estado y pipelines de Terraform en AWS.

Lo que se olvida

  • El plan es el artefacto de revisión más importante. Publícalo en el pull request. Una persona leyendo un plan caza cosas que ninguna regla anticipa, que es el argumento de leer un plan de Terraform no es lo mismo que verlo.
  • Las pruebas necesitan credenciales, y eso es riesgo de cadena de suministro. Una suite con permiso para crear infraestructura es un objetivo. Usa credenciales federadas de vida corta, como en sacar las claves de larga vida de la integración continua.
  • Fijar la versión del proveedor es parte de la corrección. Un proveedor sin fijar que se actualiza solo cambia el comportamiento entre una prueba que pasa y una aplicación.
  • Prueba el camino de destrucción. Muchos módulos se aplican limpiamente y fallan al destruir, cosa que descubres cuando necesitas desmontar un entorno.
  • Las pruebas de infraestructura inestables acaban borradas. Invierte en reintentos y en limpieza, o la suite no sobrevivirá su segundo mes.

Qué hacer esta semana

Añade una comprobación: rompe el pipeline si un plan contra un espacio de trabajo de producción contiene una destrucción o un reemplazo, salvo que el pull request lleve una etiqueta concreta. Es una tarde de trabajo con el JSON del plan, no necesita herramienta nueva, y evita la categoría más cara de error de infraestructura. Lo cableamos en la fase de plataforma de un proyecto cloud.

ConsultorIA

¿Quieres esto en tu nube?

El diagnóstico de diez días en solo lectura es gratuito, y con Skyline puedes ver tu entorno en un mapa antes de escribirnos.

Artículos relacionados

Módulos que la gente reutiliza en vez de copiar

Los dos fracasos son un módulo que envuelve un recurso y no aporta nada, y un módulo que lo hace todo y que nadie se atreve a cambiar. Una interfaz mínima, valores por defecto seguros y un versionado honesto son lo que los separa.