Un enfoque interesante para aprovisionar los componentes usados para nuestras soluciones de nube, es el uso de la infraestructura como código, y para esto podemos echar mano de herramientas como Terraform, Bicep, entre otros.
Los recursos que necesitamos crear deben de usar infraestructura como código. Por tal motivo vamos a usar Terraform ya que facilitará la gestión de la configuración, el despliegue en distintos ambientes (desarrollo, pruebas y producción) y en caso de un desastre podemos aprovisionarlos en otras regiones.
Puedes acceder al repositorio de GitHub aqui
¡Manos a la obra!
Creación de repositorio en GitHub
Como prerrequisito necesitamos una suscripción de Azure, puedes crearla gratis en este enlace si no cuentas con una. Todo código, script o pieza de software en la que trabajemos debe de estar versionada y para esto usaremos GitHub para crear un repositorio donde resguardar nuestros scripts.
Vamos a nuestra cuenta de GitHub, al ingresar en la esquina superior derecha veremos un signo de “+” damos clic y procedemos a dar clic en el botón de “New Repository”
Ya que nos encontramos en la página de creación de repositorios especificamos el nombre, en nuestro caso es un repositorio público; sin embargo, si es un proyecto privado puedes especificarlo, agregamos un archivo README y damos clic en “Create Repository”
Una vez que tenemos nuestro repositorio creado, procedemos a clonar nuestro repositorio en nuestro ambiente local de desarrollo. Pero es importante contar previamente con las herramientas necesarias, aquí dejo una lista con algunos enlaces donde los puedes descargar:
- Visual Studio Code (puedes descargarlo totalmente gratis en el siguiente vinculo)
- Git (puedes descargarlo en el siguiente enlace)
- Terraform (descárgalo aquí)
- Azure CLI (descárgalo aquí)
Para clonar nuestro repositorio es muy sencillo, vamos al repositorio recién creado y le damos clic en el botón de “Code”, y copiamos la URL.
Procedemos a abrir cualquier consola, en mi caso abriré Visual Studio Code y usare la terminal que tenemos disponible en la herramienta (seleccione PowerShell).
Procedemos a clonar el repositorio con el siguiente comando en la terminal:
git clone “URL del Repositorio recién creado”
Este es el resultado de la ejecución de clonar el repositorio:
Cambiamos de directorio y lo abrimos con Visual Studio Code usando el comando “code .”
Creamos una carpeta en donde vamos a organizar los scripts de Terraform y de PowerShell con la siguiente estructura: “IaC/terraform/CognitiveService”. Al inicio de la configuración de nuestro repositorio no especificamos la plantilla de Git Ignore, para evitar que ciertos archivos que no deseamos sean versionados. Agregamos en la carpeta raíz de nuestro proyecto un archivo llamado “.gitignore”; es importante agregar las cuatro reglas que se ven en la imagen de bajo, para que cuando inicialicemos con los comando de “terraform init” y “terraform plan” los archivos y carpetas resultado de la ejecución de estos no sean versionados.
Configuración de mecanismos de gestión de estado de recursos de Terraform
Una de las características importante de Terraform es que podemos dar un tracking de los cambios que realizamos a los recursos que tenemos gestionados con la herramienta; por lo que, si vamos a usar Azure para desplegar nuestra infraestructura, tenemos que resguardar el estado de estos recursos en una cuenta de almacenamiento de Azure. Por tal motivo vamos a usar Azure CLI y un script de PowerShell para crear este recurso.
Procedemos a crear una carpeta dentro de “IaC\Terraform” llamada “ScriptsCLI” y dentro de la misma agregamos un archivo llamado “terraformSAState.ps1”
Automatizaremos este proceso agregando los siguientes comandos en el archivo recién creado.
Vamos a explicar el contenido de este script:
- Variables $RESOUCE_GROUP_NAME, $STORAGE_ACCOUNT_NAME, $CONTAINER_NAME: Estas variables permitirá especificar el nombre del grupo de recursos donde desplegaremos los recursos, el nombre de la cuenta de almacenamiento y el nombre del contenedor de la cuenta de almacenamiento donde se alojará el estado de los recursos.
- Comando “az group create”: crea el grupo de recursos en Azure.
- Comando “az storage account create”: crea el recurso de la cuenta de almacenamiento.
- Comando “az storage container create”: crea el contenedor que alojará el estado en la cuenta de almacenamiento creada.
Abrimos una terminal dentro de Visual Studio Code, ejecutamos el comando “az login”, en la siguiente imagen vemos el resultado esperado después de la ejecución del comando.
Aparecerá una ventana del navegador e ingresamos nuestras credenciales que usamos para ingresar al portal de Azure; una vez que la autenticación fue exitosa, podemos ver en la terminal toda la información de las suscripciones a las que tenemos acceso. Si tenemos múltiples suscripciones asociadas a nuestra cuenta procedemos a establecer la suscripción donde estaremos trabajando (en caso contrario puedes omitir este paso)
Ahora ejecutamos el script recién creado.
Si vamos a Azure podemos ver el recurso ya creado en la suscripción.
Para tener acceso a la cuenta de almacenamiento, necesitamos el Account key, especificarlo directamente en el script de Terraform no es una buena práctica, ya que exponemos información que es sensible. Entonces el enfoque que usaremos para que Terraform puede acceder a este recurso es asignar el Account Key a una variable de ambiente; entonces crearemos un script usando Azure CLI, lo nombramos “storageAccountkey.ps1” en la carpeta “Iac\Terraform\ScriptCLI”
Dentro del script tendremos como variables el nombre del grupo de recursos y el nombre de la cuenta de almacenamiento; usamos el comando “az storage account keys list” para obtener la llave correspondiente y con la instrucción “$env:ARM_ACCESS_KEY” lo asignamos a una variable de ambiente, tal y como se muestra en la imagen siguiente:
Ejecutamos el script en la terminal.
Aprovisionamiento de Servicios de Speech con Terraform
Ahora que ya tenemos todo listo, vamos a trabajar en nuestros scripts de terraform, para esto dentro de la carpeta de “IaC\Terraform” creamos un nuevo directorio con el nombre de “CognitiveService”, creamos un archivo llamado “providers.tf”. El objetivo de este archivo es determinar los siguiente:
- La versión de Terraform que usaremos para aprovisionar el recurso. Esto lo especificamos con la propiedad “required_version” que nos permite establecer una versión puntual o una versión mínima.
- Los providers necesarios para crear los recursos, en nuestro caso usamos Azure Resource Manager para ejecutar las acciones configuración y aprovisionamiento de nuestros recursos en Azure. Esto lo especificamos en las propiedades “required_providers” y “provider”; en el primero especificamos el tipo de provider y la fuente donde consumirlo, y en el segundo asociamos los features que vamos a usar del provider.
El mecanismo por medio de cual vamos a almacenar el estado de nuestros recursos y acciones que realizamos en ellos con Terraform. Esto esta detallado en la sección de “backend” donde necesitamos indicar la cuenta de almacenamiento de Azure que usaremos, el grupo de recursos donde se encuentra, el “blob container” que usaremos y el key con el cual identificará Terraform donde guardar el estado de los recursos.
Una buena práctica es que usemos archivos donde almacenemos nombres, tiers, regiones de centros de datos o propiedades de los recursos que pueden ser configurables para que podamos desplegarlos en otros ambientes. Para esto en el mismo directorio vamos a crear el archivo “variables.tf”; y creamos variables para lo siguiente:
- “cs_speech_name” con el nombre de recurso de Speech Services
- “resource_group_name” grupo de recursos donde estará asociado el recurso de Speech Services
- “resource_group_location” región de Azure donde se desplegarán los recursos
- “cs_speech_SKU” SKU que usaremos en el recurso de Speech Services
- “cs_speech_Kind” tipo de servicio que usaremos para Speech services.
Listo, vamos a la parte más interesante, creemos en el mismo directorio el archivo “speechcs.tf”, dentro de este crearemos 2 recursos:
- Grupo de recursos
- Servicio de Speech
Ambos los declaramos con la palabra reservada “resource”, especificamos el tipo, “azurerm_resource_group” para el grupo de recursos y “azurerm_cognitive_account”, el identificador correspondiente y las propiedades que vemos en la siguiente imagen.
Vamos a probar su correcto funcionamiento, el primer paso es inicializar el directorio para que Terraform pueda realizar el despliegue de forma correcta, para esto en la terminal ejecutamos el comando “terraform init”
El comando anterior crea la carpeta “.terraform” que contiene el ejecutable del AzureRM provider para aprovisionar y ejecutar la configuraciones de nuestros recurso, adicionalmente crear el archivo terraform.tfstate que contiene la configuración necesario para guardar en la cuenta de almacenamiento de Azure los cambios que realizamos en estos recursos.
Ahora Terraform requiere generar un plan para ejecutar de forma correcta la creación y configuración de los recursos, por lo que ejecutaremos el comando “terraform plan -out main.tfplan” en nuestra terminal. Esto generará el archivo main.tfplan con la acciones a ejecutar.
Una vez que tenemos el archivo “main.tfplan” necesitamos aplicar los cambio con el comando “terraform apply main.tfplan”.
Vamos al portal del azure y podemos ver que se creó el grupo de recursos y el recurso de Speech Services
Como estamos probando en un ambiente de desarrollo y vamos a automatizar posteriormente un flujo de CI – CD en GitHub, vamos a eliminar lo que acabamos de crear, para esto primero necesitamos crear el plan de eliminación con el comando “terraform plan -destroy -out main.destroy.tfplan”.
Para ejecutar finalmente la eliminación de los recursos ejecutamos en la terminal el comando “terraform apply ” al archivo “main.destroy.tfplan”
Versionamiento y Protección de rama main
Procedemos a guardar nuestros cambios, si utilizamos una extensión para gestionar cambios en el sistema de control de versión procedemos a realizar el commit y el push correspondiente. En caso contrario podemos usar la línea de comandos para enviar los cambios a GitHub con “git add . ” y “git push”.
Finalmente ejecutamos el comando “git push“
Una vez que tenemos esta versión funciona en nuestro repositorio procederemos a proteger nuestra rama para que no se integren cambios de forma desordenada. Vamos al sitio de Github, en el repositorio damos clic en “Settings”, posteriormente en el panel lateral izquierdo en la sección de “Code and automation” damos clic en “Branches”, y en la sección de “Branch protection rules” damos clic en el botón “add branch protection rule”
Procedemos a especificar la rama que protegeremos en el campo de “Branch name pattern” en nuestro caso es main; posteriormente activamos las siguientes opciones:
- Require a pull Request before merging, con el objetivo de integrar solamente un cambio a esa rama a través de un Pull Request.
- Require approval, para que alguien revise los cambios a ser integrados en la rama protegida.
- Require conversation resolution before merging, en caso de que el revisor realice algun comentario/observación el cambio no se integre hasta que sea resuelto.
Damos clic en el botón de “Create”.
Ahora vemos que la regla creada y la rama main esta protegida.
En la siguiente entrega estaremos configurando un proceso de CI – CD en GitHub. Esto fue todo por hoy espero que te haya gustado este articulo y te sea de mucha utilidad, puedes ver más contenido que estaré generando en este medio.
¡Saludos y disfruta estar en la nube!