Infraestructura en un lenguaje de programación de verdad, y lo que te cuesta

Los bucles, los tipos y las pruebas vienen gratis con un lenguaje de propósito general. Lo que entregas a cambio es un plan que pueda revisar quien no programa, y un suelo bajo para quien tiene que mantenerlo a las tres de la madrugada.

El argumento de venta es genuinamente atractivo. Ya sabes TypeScript o Python, así que para qué aprender un lenguaje específico de dominio con bucles incómodos, sin funciones de verdad y con un sistema de tipos contra el que peleas. Escribe infraestructura en un lenguaje con entorno de desarrollo, depurador, gestor de paquetes y marco de pruebas.

Ese argumento es cierto. Lo que se deja fuera es que las propiedades que hacen potente a un lenguaje de programación son las mismas que hacen difícil de revisar el código de infraestructura, y el código de infraestructura lo lee bajo presión gente que no lo escribió.

Qué es igual en realidad

Las dos herramientas construyen un grafo de dependencias a partir de tus definiciones, lo comparan con el estado registrado y producen un plan de creaciones, actualizaciones y borrados antes de aplicar nada. Las dos guardan un estado que hay que proteger y bloquear. Las dos hablan con las APIs de la nube a través de proveedores, y Pulumi puede consumir proveedores de Terraform, así que la cobertura es comparable.

La disciplina de estado, los patrones de pipeline, el problema de la deriva y el requisito de revisión son idénticos. Si tu organización del estado y tu pipeline están mal, cambiar de herramienta no ayuda, que es por lo que los patrones de estado y pipelines de Terraform en AWS se aplican en los dos casos.

Así que esto no es una elección entre paradigmas de gestión de infraestructura. Es una elección de lenguaje de escritura sobre el mismo modelo.

Qué ganas

Bucles y condicionales que se comportan con normalidad. Generar veinte recursos parecidos a partir de una estructura de datos es un bucle. Filtrar una lista es un filtro. Nadie tiene que recordar qué metaargumento reordena recursos cuando se quita un elemento.

Abstracción de verdad. Funciones, clases e interfaces. Un componente que encapsula un patrón es un objeto con un constructor, y componer componentes es componer objetos. En un entorno grande con convenciones internas fuertes esto es genuinamente más expresivo que los módulos.

Tipos y entorno de desarrollo. Autocompletado de los argumentos del proveedor, errores en tiempo de compilación por una propiedad mal escrita, refactorización que funciona. Es el beneficio que la gente nota primero y es real.

Pruebas con herramientas normales. Pruebas unitarias sobre la lógica de tus componentes con el marco de pruebas que ya usas, simulando el proveedor. Comparado con la pirámide de probar el código de infraestructura, la capa unitaria es bastante más fácil.

Compartir código con la aplicación. Las mismas constantes, la misma validación, las mismas librerías cliente. Para un equipo que construye un producto de plataforma en vez de gestionar un entorno, esto importa.

Qué pierdes

El plan deja de ser trivialmente revisable. Este es el grave. Una configuración declarativa se parece a una descripción del resultado, así que quien revisa puede leer una diferencia y razonar sobre ella. Un programa que calcula recursos exige que quien revisa lo ejecute mentalmente. La salida del plan sigue ahí y sigue siendo el artefacto que revisas, pero la conexión entre el cambio en el código y el plan es menos directa, y el requisito de revisión es exactamente el que se describe en leer un plan de Terraform no es lo mismo que verlo.

El suelo sube. El código de infraestructura lo mantiene quien esté de guardia. Un fichero declarativo tiene una barrera baja: alguien que no escribe TypeScript puede encontrar igualmente el tamaño de instancia y cambiarlo. Un programa con herencia, genéricos y un módulo de utilidades no tiene esa propiedad.

La infraestructura se convierte en software, con los modos de fallo del software. Dependencias, dependencias transitivas, conflictos de versión, un paquete con un paso de compilación. La listeza está disponible, y se va a usar. El peor código de infraestructura que hemos visto lo escribió en un lenguaje de propósito general alguien que se lo estaba pasando bien.

El ecosistema es menor. Hay más módulos, más ejemplos, más respuestas en foros, más herramientas de política y de coste, y más ingenieros disponibles del lado declarativo. Esa asimetría es un coste real al contratar o al traspasar trabajo.

Elige por quién lo mantiene

La comparación técnica rara vez decide esto. Lo decide el equipo.

Elige la herramienta declarativa cuando quienes mantienen la infraestructura son un grupo mixto que incluye a ingenieros que no programan principalmente, cuando quieres revisiones que un responsable de plataforma pueda hacer rápido, cuando valoras la profundidad del ecosistema, o cuando auditores y revisores de seguridad leen tu configuración. La mayoría de las organizaciones están aquí.

Elige el lenguaje de programación cuando el equipo tiene una orientación fuerte de ingeniería de software, cuando estás construyendo una plataforma que genera infraestructura por programa para otros, cuando tus patrones necesitan genuinamente una abstracción que los módulos expresan mal, o cuando el mismo equipo es dueño de la aplicación y de la infraestructura y comparte código entre ambas.

Elige la opción nativa de la nube cuando estás en una sola nube y esperas quedarte. Bicep en Azure y CloudFormation en AWS tienen soporte de primera parte, aparecen el primer día para los servicios nuevos y no necesitan gestión de estado. El precio es la portabilidad, y la comparación honesta para uno de ellos está en Bicep o Terraform para Azure.

Si eliges el lenguaje de programación, impón restricciones

Todo lo que sale mal aquí sale mal por exceso. Unas pocas reglas lo mantienen mantenible.

Que sea aburrido. Bucles, funciones y un número pequeño de componentes. Nada de metaprogramación, nada de herencia profunda, nada de generación de recursos en tiempo de ejecución que quien lee no pueda seguir.

Pon el plan en el pull request y exígelo en la revisión. El plan es la fuente de verdad de lo que va a pasar, y el código es la fuente de verdad del porqué.

Fija todas las dependencias, incluidas las transitivas, y trata el árbol de dependencias como cadena de suministro. Código que se ejecuta en tu pipeline con credenciales para crear infraestructura merece el escrutinio que se describe en OSV-Scanner y SBOM.

Escribe las pruebas unitarias. Es la ventaja técnica principal de la elección, y los equipos con frecuencia no la aprovechan, lo que les deja con los costes y sin el beneficio.

Mantén los datos de configuración fuera del código. Las diferencias entre entornos van en ficheros de configuración, no en condicionales repartidos por el programa.

Lo que se olvida

  • Migrar entre ellas es posible y no es gratis. Las dos pueden importar recursos existentes y hay caminos de conversión, pero el trabajo está en reexpresar la estructura, no en traducir sintaxis.
  • El estado sigue siendo la joya de la corona. El servicio de estado gestionado es una dependencia alojada con su propia disponibilidad y su propio precio; el backend autogestionado es responsabilidad tuya.
  • Las herramientas de política difieren. Comprueba que tus comprobaciones de política y de coste admiten la herramienta antes de comprometerte, porque perder la puerta a nivel de plan es una regresión real.
  • Un monorepositorio de infraestructura en un lenguaje invita a importaciones cruzadas. Compartir una utilidad entre dos pilas que deberían ser independientes es más fácil de lo que debería.
  • El tiempo de incorporación es un coste real. Mide cuánto tarda un ingeniero nuevo en hacer un cambio seguro, en las dos.

Qué hacer esta semana

Coge una pila representativa y pídele a alguien que no la escribió que lea el código y prediga qué produciría un plan. Después ejecuta el plan. La diferencia entre la predicción y la salida es el coste de revisabilidad, y es el número que debería decidir esto por ti. Hacemos ese ejercicio durante la revisión 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.