Hace poco vi una presentación sobre herramientas y técnicas de gestión de configuración que me dejó pensando una idea que vale la pena explorar.
Todos coinciden en que las herramientas de gestión de configuración basadas en infrastructure-as-code son esenciales y aportan mucho valor, pero al mismo tiempo, la frustración al usarlas es bastante alta. ¿Y si los mecanismos actuales de gestión de configuración o de infrastructure-as-code dejaran de ser un caos o un dolor de cabeza? ¿Cómo se verían?

El mapa no es el territorio, aunque la gente suele confundirlos.
Este artículo explora cómo DevOps y el desarrollo de software, en general, pueden beneficiarse de una nueva forma de ver el aprovisionamiento y la configuración de sistemas, replanteando la terminología habitual desde otra perspectiva.
Empecemos con algunos términos que nos ayudarán a entender mejor el panorama y a abordar varios de los problemas que tantos están enfrentando.
Terminología explicada
Operations: la práctica de garantizar que los sistemas de software funcionen correctamente y atiendan las necesidades de los usuarios. Al ingeniero de operations normalmente le interesa menos escribir código nuevo; su foco principal está en cómo se comporta el software existente dentro de un sistema en marcha.
Una vez definidos estos dos términos, podemos explicar en qué se diferencia el "forward engineering" del "reverse engineering".
Forward engineering
El forward engineering consiste en construir un sistema a partir de un modelo de lo que debería existir en él. En FE normalmente se crea primero el modelo y luego se despliega y configura esa plantilla para ponerla en operación. La expectativa es que el sistema resultante coincida estrechamente con el modelo.
En muchos casos, el modelo declarado es ambiguo y el sistema puede comportarse de formas inesperadas que no eran la intención del modelo inicial. Eso ya es un obstáculo importante al usar este tipo de técnicas, sobre todo para quienes recién empiezan.
Para colmo, el sistema mismo suele diferir del modelo por la interacción con su entorno; por ejemplo, cuando varias partes modifican la configuración entre sí, o cuando los procedimientos ad-hoc que ejecutan los Engineers desplazan al sistema en distintas direcciones.
En forward engineering no existe una noción fundamental de retroalimentación hacia el modelo inicial. El modelo se "graba en piedra" primero y se despliega después. Cualquier feedback que llegue luego del sistema sobre su comportamiento puede aprovecharse para nuevas iteraciones de modelos y despliegues futuros.
Reverse engineering
El reverse engineering consiste en desarrollar un modelo parcial a partir de un sistema existente y usarlo como base para modificarlo. No hay un modelo inicial, y es el estado actual del sistema lo que permite descubrir cómo deberían funcionar las cosas.
Hacer cambios en un sistema así, en muchos casos, se hace de forma ad-hoc directamente sobre el sistema, muchas veces sin un entendimiento completo del conjunto. Aquí la retroalimentación es inmediata, y explorar el sistema se hace principalmente provocándolo y observando el feedback que se genera.
¿Dónde encontramos el reverse engineering? Probablemente hayas oído que los expertos en seguridad usan prácticas de RE para escarbar en software existente y detectar agujeros en su seguridad. Por ejemplo, escanean servicios de red o memoria para detectar comportamientos anómalos en un sistema y aprovecharlos haciendo que el sistema actúe de manera no prevista.
El reverse engineering se trata de mirar un sistema o software existente y, a partir de lo que hace en la práctica, intentar entender dónde tiene brechas respecto a la intención original con la que se concibió ese software.
¿Dónde encontramos estas ideas en el mundo de DevOps?
Infrastructure as code
Desde que se lanzó la primera versión de CFEngine allá por 1993, la idea de modelar infrastructure-as-code tuvo un crecimiento explosivo dentro de la industria de la ingeniería de software. Empezó declarando cómo debería verse el contenido de un sistema operativo de servidor y rápidamente se adaptó para describir la disposición y configuración de los recursos cloud actuales. Empresas y herramientas han ido y venido a lo largo de los años, como Puppet, Chef, Salt, Ansible, CloudFormation, Terraform, CDK, Pulumi y muchas otras soluciones caseras.
Lo que tienen en común la mayoría de las herramientas mencionadas es que son declarativas. Las herramientas declarativas solo permiten especificar cómo deberían ser las cosas, sin detallar los pasos para llegar ahí. En los últimos años han surgido varias herramientas que se presentan como más imperativas. Sin embargo, siguen siendo principalmente declarativas y distintas de los lenguajes tradicionales de desarrollo imperativo que se usan para escribir código.
¿Por qué la mayoría de estas herramientas son declarativas?
La respuesta corta: porque es la forma más fácil de crear mapas, modelos y plantillas. Un Engineer solo tiene que declarar cómo deberían verse las cosas y dónde debería ir cada elemento, y delegar el trabajo difícil de averiguar cómo darle a cada uno la forma correcta. Esto permite mejoras iterativas con el tiempo y, a la larga, lleva a sistemas más robustos y estables.
Otra ventaja común de las herramientas declarativas de infrastructure-as-code es la propiedad de idempotencia. La idempotencia implica repetir una acción varias veces con un resultado consistente. Cuando se usa una herramienta idempotente para modificar un sistema varias veces, el sistema termina por llegar al estado declarado en la plantilla. Volver a aplicar esa misma plantilla después ya no tiene efecto sobre el sistema. La idempotencia es la propiedad que permite aplicar el modelo varias veces y que el sistema solo cambie cuando hay diferencias respecto al modelo.
Un enfoque imperativo requeriría primero encontrar todas las diferencias entre el modelo y el sistema, y luego implementar cada paso necesario para cada cambio. Las herramientas declarativas de infrastructure-as-code logran esto sin que el desarrollador tenga que escribir todas las acciones por su cuenta.
Las herramientas de infrastructure-as-code son populares y fundamentales; ahorran miles de horas-persona al crear plantillas reutilizables y al generar réplicas de sistemas casi idénticos en distintos entornos con un esfuerzo marginal mínimo.
Infrastructure-as-code promete que la mejora iterativa del modelo a lo largo del tiempo se traduce en sistemas robustos y estables basados en ese modelo.
Un artículo previo mío sobre configuración para múltiples sistemas explica por qué tener réplicas de sistemas casi idénticos resulta beneficioso para los negocios de software.
¡Pero! Estas herramientas operan con una mentalidad de forward engineering, ya que son declarativas y no tienen mecanismo para recibir retroalimentación de un sistema en vivo. Este enfoque ha generado, a lo largo de los años, muchos problemas y quejas entre los usuarios de estas herramientas, y vale la pena revisarlos.
Problemas del infra-as-code basado solo en forward engineering
¿Has escuchado el término Configuration Drift? Ocurre cuando el modelo declarado deja de coincidir con el estado del sistema. Todo sistema, con suficientes actualizaciones, casi siempre termina siendo distinto del modelo con el que se creó.
El drift puede ocurrir cuando un desarrollador cambia el código del modelo sin actualizar todos los sistemas construidos con él, o cuando un Engineer realiza operaciones exploratorias ad-hoc y modifica un sistema sin volver a la plantilla para actualizar su código. Ambas actividades son esenciales: los desarrolladores hacen lo primero para introducir mejoras en futuras iteraciones de despliegues, y los ingenieros de operations a menudo hacen lo segundo para descubrir problemas desconocidos y atenderlos.
El configuration drift es, por supuesto, una mina común esperando estallar, y por eso todo el mundo dice que hay que evitarlo. Pero ¿es realista prohibirles a los operadores operar los sistemas para impedir cualquier exploración ad-hoc? Sí. Algunas empresas adoptan la regla de que ningún operador ni desarrollador puede tocar un sistema en "producción en vivo". Te puedes imaginar lo que una política así le hace a la métrica Mean-time-to-Recover de esos sistemas. Por experiencia personal, cuando WTSHTF y un sistema de "producción" se rompe por cualquier motivo, esta es la primera regla que sale volando por la ventana, y la exploración ad-hoc se habilita de inmediato para cualquiera que pueda descifrar qué está pasando.
Los Engineers que se animan a adoptar infrastructure-as-code se quejan del exceso de trabajo que implica remodelar desde cero un sistema existente. Siempre hay alguien creando una herramienta para ayudar con esto. Google tiene GCP Terraformer, AWS tiene el descontinuado AWS CloudFormer, e incluso Azure tiene su ARM repartido por toda su consola cloud. Siempre hay alguien construyendo una herramienta así para tu lenguaje favorito de gestión de configuración, simplemente porque la demanda es altísima.
Pero, lamentablemente, una vez que un Engineer ha usado una de estas herramientas, suele quedar decepcionado. El resultado es demasiado ruido sin sentido o, en el mejor de los casos, ya está obsoleto al día siguiente. Lo más que se puede hacer con una plantilla generada por reverse engineering es copiar y pegar fragmentos de ella en una plantilla escrita a mano en otro lugar.
Mejorando el camino a seguir
Este artículo definió dos términos y explicó por qué el forward engineering por sí solo es subóptimo para la operación real de los sistemas, y cómo, en la mayoría de los casos, el reverse engineering sigue siendo obligatorio para encontrar y resolver problemas.
La propuesta ahora es crear una nueva generación de herramientas de Infrastructure-as-Code, herramientas que integren el reverse engineering como eje central y permitan que la retroalimentación de los sistemas en producción actualice los modelos que les dieron origen. Un operador puede entonces adoptar el cambio ad-hoc o rechazarlo para revertir el sistema al estado declarado en el modelo original.
Las herramientas estándar de la industria fallan a la hora de ayudar a los Engineers a resolver los problemas que surgen con la operación de los sistemas. Sí, existen varias herramientas que pueden auditar tus plantillas de Terraform y avisarte de errores o malas configuraciones. Esas auditorías son útiles, pero el verdadero valor está en inspeccionar un sistema vivo existente, no solo la plantilla que los Engineers usaron en algún momento para crearlo.
Hasta donde sé, no tenemos una herramienta lo bastante buena que permita integrar más prácticas de reverse engineering en el trabajo diario de los Engineers de operations. Por un lado tenemos un montón de herramientas de monitoreo y observabilidad, y por el otro muchas herramientas de infrastructure-as-code, con una brecha enorme entre ambos mundos.
¿Tienes ideas de cómo podríamos llenar esa brecha? ¡Cuéntanos!
Imagen de portada creada por Tabea Schimpf en Unsplash.