En la última entrada, hablamos sobre Terraform como herramienta para para gestionar nuestra infraestructura mediante código. También hemos hablado hace poco sobre el despliegue continuo desde Azure Pipeline con ARM. Como pudimos comprobar, trabajar con Terraform nos facilita la vida respecto a lo que es el trabajo con ARM directamente. Hoy vamos a unir las dos cosas utilizando Terraform desde Azure Pipelines.
En su momento comentábamos que una de las grandes ventajas de Terraform es que mantiene el estado de los recursos. Esto es algo muy útil y que con trabajo local no supone ningún problema, pero eso se nos queda corto si trabajamos desde el agente de Azure Pipelines. Esto es porque cuando el agente termine va a borrar los recursos, y esto incluye el fichero de estado del despliegue. Para solucionar este «inconveniente» y persistir el estado entre despliegues, vamos a utilizar un Azure Storage donde guardar el fichero.
Una vez aclarado esto, ¡vamos a crear una WebApp en Linux y conectarla a una base de datos Sql Server!
Codificando la infraestructura
Para poder generar la infraestructura y conectarla entre si sin revisión manual, vamos a utilizar la potencia que nos ofrece Terraform para relacionar recursos y así añadir datos como la cadena de conexión. En GitHub está el proyecto completo, dividido en secciones para facilitar su mantenimiento, y utilizando la posibilidad de modular partes para crear la Web App y el Sql Server.
Utilizando estas ventajas, vamos a generar la cadena de conexión de la base de datos utilizando los datos de salida y se lo vamos a pasar a la configuración de la webapp. Para eso, vamos a crear una salida en el módulo de sql server donde vamos a generar la cadena de conexión:
output "conection_string_value" {
description = "Sql Server ConnectionString"
value = "Server=${azurerm_sql_server.sqlServer.fully_qualified_domain_name};Initial Catalog=${azurerm_sql_database.sqlServerDb.name};User Id=${var.SQL_ADMIN_ID};Password=${var.SQL_PASSWORD};"
}
Con esto, vamos a poder utilizarla más adelante:
module "linuxwebapp" {
//...
conection_string_value = "${module.sqlserver.conection_string_value}"
}
El código de la infraestructura es fácil de seguir, pero aun así recomiendo echarle un ojo en profundidad para entender el concepto anterior.
Creando la integración continua
Para poder desplegar Terraform desde Azure Pipelines, el primer paso es crear el pipeline de integración. De esto hablamos hace algún tiempo en una entrada sobre CI, pero esta vez vamos a utilizar la interfaz gráfica en vez de yml. Como se pueden ver, los pasos son los mismos que cuando utilizábamos yml:
Aquí solo hay un pequeño cambio respecto a lo que vimos anteriormente, y es que tenemos que meter los ficheros de Terraform al artefacto para poder utilizarlos más adelante:
Para configurar esta nueva tarea, basta con decirle el nombre de la carpeta donde está el código Terraform que queremos desplegar, ponerle el filtro de selección (** para seleccionarlo todo), y por último crear una carpeta en el directorio del artefacto y pegar los ficheros Terraform en él.
El hecho de utilizar la interfaz gráfica para la integración es solo por cambiar, pero para el despliegue solo se puede utilizar la interfaz gráfica de momento.
Ejecutar Terraform desde Azure Pipelines
Una vez que tenemos la integración lista, vamos a crear una Release para que despliegue la infraestructura y el proyecto. Para ahorrarnos trabajo, vamos a utilizar el Task «Terraform Build & Release Tasks«, así que vamos a instalarlo en el pipeline:
Una vez que lo tenemos instalado, vamos a crear el pipeline donde instalaremos Terraform, lo inicializaremos y aplicaremos para desplegar los recursos, y por último publicaremos la web:
Al igual que hacíamos con ARM, lo ideal sería tener diferentes ranuras donde tengamos las diferentes etapas de dev, pre, pro, etc.
Además, vamos a necesitar diferentes variables, que vamos a registrar también en el pipeline, para eso, vamos a la pestaña «Variables»:
Y vamos a registrar las variables que necesitamos para nuestro Terraform:
Por convención, el pipeline le pasa directamente las variables que coincidan y empiecen por TF_VAR a Terraform siempre que no sean secretos. Esto es algo a tener en cuenta para evitarnos un comando apply larguísimo donde le pasemos muchísimas variables.
Volviendo al pipeline, lo primero que tenemos que hacer es instalar Terraform, para eso, vamos a utilizar la Task «Terraform Installer» y le vamos a indicar la versión de Terraform que queremos utilizar:
El siguiente paso, es configurar una Task de tipo «Terraform CLI» para ejecutar el comando init:
Dentro de esta Task, vamos a seleccionar el comando «init», y vamos a indicar la ruta donde está el código Terraform, por último, vamos a seleccionar el tipo de backend, que como dijimos al principio, será en Azure Storage, por lo tanto, seleccionamos «azurerm». Esto nos permite ampliar la configuración pulsando sobre «AzureRM Backend Configuration», y así indicarle los datos de configuración:
Con esto listo, el último paso con Terraform es crear una tercera Task de tipo «Terraform CLI». Esta vez vamos a elegir el tipo de comando «apply», le vamos a indicar la ruta a donde están los ficheros de código Terrafom, y por último le vamos a indicar las opciones. Entre las opciones, vamos a indicarle «-auto-approve» para que no pida confirmación antes de desplegar los cambios, y le vamos a pasar todas las variables de tipo «secrets» mediante «-var VARIABLE=VARIABLE_PIPELINE» (recordemos que las demás variables se le pasan por convención):
Un ejemplo de las opciones utilizadas es:
-auto-approve -var AZURE_SUBSCRIPTION_ID=$(TF_VAR_AZURE_SUBSCRIPTION_ID) -var AZURE_CLIENT_ID=$(TF_VAR_AZURE_CLIENT_ID) -var AZURE_CLIENT_SECRET=$(TF_VAR_AZURE_CLIENT_SECRET) -var AZURE_TENANT_ID=$(TF_VAR_AZURE_TENANT_ID) -var SQL_PASSWORD=$(TF_VAR_SQL_PASSWORD)
Con esto, y si todo ha ido bien, ya vamos a conseguir desplegar los recursos en Azure. Para desplegar la Web, solo nos queda añadir un Task de tipo «Azure App Service Deploy» tal cual hicimos en el caso de ARM para desplegar la web.
Tras lanzar una release, dentro de nuestro portal en azure podremos encontrar algo como esto:
Para este ejemplo, hemos utilizado el template de ASP NET Core y le hemos añadido que ejecute las migraciones de la base de datos al iniciar, para que la web este lista para funcionar directamente.
Como siempre, he dejado el código fuente completo (tanto Terraform como la Web) en GitHub.
Conclusión
Como hemos podido comprobar, Terraform es una herramienta muy potente que nos facilita mucho la vida manejando infraestructura como código (IaC), además de permitirnos trabajar con múltiples proveedores. Podemos integrar perfectamente Terraform y Azure Pipelines, o cualquier otro servicio CI/CD utilizando los comandos directamente, por lo que es algo que vale la pena revisar y conocer.