Cloud Computing

Azure Bicep, el nuevo lenguaje para definir plantillas ARM

Te contamos qué es Azure Bicep y las ventajas que ofrece, además de cómo realizar los primeros pasos con este nuevo lenguaje desarrollado por Microsoft.

Publicado el 03 de Diciembre de 2021
Compartir

Cloud Computing es uno de los temas más relevantes y de mayor demanda en la actualidad, la adopción de la nube ha aumentado en los últimos años. Azure es una de las nubes públicas más utilizadas en el mundo. Hay muchas ventajas al trabajar con soluciones en la nube, y algo que nos interesa a todos es la automatización, por lo tanto, escribir infraestructura como código (IaC) es fundamental.

En Azure una de las alternativas para automatizar el aprovisionamiento de infraestructura son las plantillas Azure Resource Manager (ARM), hasta hace poco estas plantillas se escribían en JSON, pero Microsoft ha trabajo en un nuevo lenguaje llamado Bicep, con mejoras interesantes y que viene para hacernos la vida más fácil. En este artículo, te contaremos de que se trata este lenguaje, que ventajas ofrece y como empezar a trabajar con Bicep.

Qué es Azure Bicep

Bicep es un lenguaje desarrollado para automatizar el aprovisionamiento de recursos en Azure mediante la definición de plantillas ARM, y eso es infraestructura como código. La infraestructura como código en Azure no es una novedad, siempre hemos tenido a disposición las plantillas ARM, la novedad es el lenguaje para escribir estas plantillas. Por otra parte, tenemos herramientas de terceros muy potentes como Pulumi o Terraform, esta última utiliza HCL, lenguaje nativo de Terraform. Hago esta mención porque HCL me parece más sencillo que JSON para escribir IaC, y ese es uno de los principales objetivos de Bicep, mejorar aún más la experiencia de desarrollo.

Como mencionaba al inicio, anteriormente se utilizaba JSON para definir plantillas ARM, todavía se sigue usando, pero la idea es que se adopte Bicep por la simplicidad. De hecho, podemos convertir las plantillas creadas en JSON a Bicep usando un comando de la CLI, esto con el fin de tener un estándar. Bicep utiliza una sintaxis declarativa, significa que los elementos pueden aparecer en cualquier orden, por lo cual, puedes declarar variables, parámetros, y outputs en cualquier parte de la plantilla. Con JSON esto no es posible, se deben declarar las variables, parámetros y salidas únicamente en las secciones correspondientes.

El detalle con JSON es que la sintaxis es más compleja, cuando las plantillas son grandes se vuelven más difícil por las expresiones que se manejan. En el caso de Bicep simplifica esa complejidad, ofreciendo una sintaxis más limpia, sencilla y concisa, que no hace más que beneficiarnos con una mejor experiencia, lo cual se traduce en agilidad y productividad. También permite reutilizar código, los módulos juegan un papel importante. La mejor forma de comprender es con ejemplos, veamos algo sencillo para identificar las diferencias entre JSON y Bicep.

Definir parámetros

En este ejemplo declaramos dos parámetros, el primero recibirá un nombre para la red virtual y el segundo recibirá un valor por defecto que corresponde a la región del grupo de recursos donde se realiza la implementación.

Bicep

param vNetName string
param location string = resourceGroup().location

JSON

"parameters": {
    "vNetName": {
        "type": "string"
    },
        "location": {
            "type": "string",
            "defaultValue": "[resourceGroup().location]"
        }
    }

Es verdad que la sintaxis ha cambiado, sin embargo, la funcionalidad sigue siendo la misma, las plantillas escritas en JSON siguen funcionando y siempre serán compatibles, en realidad, lo que hace la CLI es tomar el archivo Bicep y lo convierte a JSON, y al final es JSON el que hace la implementación. En AWS pasa algo similar con CloudFormation, anteriormente solo se definían en JSON, pero igual, Amazon entendió que se requería algo más simple, admitió que se escribiera en formato YAML, y al hacer la implementación hace una traducción de YAML a JSON.

Ventajas de Azure Bicep

Sintaxis simple: Como he recalcado antes, una de las principales ventajas es la simplicidad de la sintaxis, los archivos de Bicep son más concisos y fáciles de leer. No hay una gran curva de aprendizaje, para escribir infraestructura como código con Bicep no es necesario ser desarrollador o tener conocimientos en algún lenguaje de programación, aunque por supuesto, siempre viene bien.

Actualizaciones: Bicep es compatible con todos los recursos en Azure y las versiones de API. Desde el momento que se libera una versión para los servicios de Azure, ya sea versión preliminar o versión completa con disponibilidad general, puedes utilizar los nuevos tipos de recursos y versiones en una plantilla de Bicep. Por tanto, no hay que esperar tiempo a que se actualicen completamente las herramientas.

Modularidad: Se puede dividir el código de una solución completa en módulos. Un módulo de Bicep es un conjunto de uno o más recursos relacionados que se crearán en la misma implementación. Esta es una característica que a todos nos encanta, desarrolladores y administradores de sistemas, ya que permite reutilizar código, y a su vez conseguimos plantillas más legibles.

Vista previa de la implementación: Similar a lo que hace Terraform (terraform plan), con Bicep puedes obtener una versión preliminar de los recursos que se implementarán, y de esa manera puedes comprobar si el plan de ejecución coincide con lo que tienes planeado antes de aprovisionar la infraestructura. Además, permite identificar errores, por ejemplo, un conflicto en las reglas de un grupo de seguridad que en el editor no lo vemos. Para ello, en Bicep se utiliza la operación what-if.

Integración con otras herramientas: Como es de esperar, herramientas de Microsoft se integran perfectamente, Bicep con Visual Studio Code no es la excepción. El editor te ayuda con la validación de sintaxis, con las sugerencias de código, y algo que me parece súper es la posibilidad de visualizar gráficamente los recursos que serán implementados. A continuación, te comparto ilustración de un ejemplo de implementación de una máquina virtual con sus recursos.

Visualización gráfica de los recursos - Bicep

Primero pasos con Bicep

Instalar extensión en Visual Studio Code

Para comenzar a trabajar con Bicep, lo primero es preparar las herramientas o lo que haga falta. Necesitarás un buen editor de código, y sin suda, Visual Studio Code es la mejor opción. Realmente es uno de los editores más populares, probablemente es tu favorito, también. En Visual Studio Code instalas la extensión de Bicep para que te ayude a completar código, validar las sintaxis, etc.

Instalar CLI de Bicep

Tenemos dos opciones: Azure CLI y PowerShell. La forma más fácil de obtener la CLI de Bicep es instalar la versión más reciente de Azure CLI. Con eso basta, no hay que hacer más cambios. Por otra parte, si prefieres PowerShell, puedes descargar el paquete de instalación de Bicep e instalarlo manualmente.

Elementos para crear plantillas ARM

En este apartado describiré brevemente con ejemplos sencillos los elementos básicos que puedes usar para crear plantillas ARM, hay otros elementos que no cubriremos en este artículo, pero creo que con esto puedes empezar. Importante, los archivos debes guardarlos con la extensión .bicep.

Resources

Los recursos son lo primordial porque precisamente es lo que hacemos en Azure, implementar recursos, me refiero a redes virtuales, cuentas de almacenamiento, máquinas virtuales, etc. Para ello, se debe declarar el recurso usando la palabra clave resource, seguido por un nombre simbólico, el tipo de recurso y la versión de la API.

A continuación, un ejemplo:

resource  vNet  'Microsoft.Network/VirtualNetworks@2019-09-01' = {
    name: 'ow-vnet'
    location: 'eastus'
    tags: {
        env: 'dev'
    }
    properties: {
        addressSpace: {
            addressPrefixes: [
                '10.0.0.0/16'
            ]
        }
        subnets: [
            {
                name: 'public-subnet'
                properties: {
                    addressPrefix: '10.0.1.0/24'
                }
            }  
        ]  
    } 
}

Pon atención a la primera línea, VNet es el nombre simbólico, puedes poner cualquier nombre, la única condición es que no se repita en otro recurso, variable o parámetro, dado que se puede utilizar para hacer referencia al recurso en otra parte de la plantilla, especialmente cuando son grandes implementaciones. Luego está el tipo de recurso (antes de @), en este caso es una red virtual y posteriormente la versión de la API (después de @). Este ejemplo contiene la declaración completa de un recurso, el nombre, las etiquetas y las propiedades. El ejemplo crea una red virtual con una subred.

Parameters

Los parámetros son utilizados para pasar valores opcionales no definidos en el código. Por ejemplo, puede ser que quieras pasar el nombre de un recurso al momento de hacer la implementación, o al crear una máquina virtual, puedes pasar el nombre de usuario y clave como parámetro. También es utilizado para tomar la región, normalmente del grupo de recursos donde aprovisionará la infraestructura. Para declarar un parámetro se debe especificar un nombre y un tipo, entre ellos: string, int, bool, Object y array. Veamos un ejemplo:

param vNetName string
param location string = resourceGroup().location

Seguimos con el mismo ejemplo. El primer parámetro pedirá que se ingrese el nombre para la red virtual que se creará. El segundo parámetro tomará un valor predeterminado utilizando una función para obtener la región del grupo de recursos donde se creará la red virtual. De esta manera ya no escribimos la región en la declaración del recurso que creará la red virtual. Ahora el código quedaría de la siguiente manera:

resource  vNet  'Microsoft.Network/VirtualNetworks@2019-09-01' = {
    name: vNetName
    location: location
    tags: {
        env: 'dev'
    }
    properties: {
        addressSpace: {
            addressPrefixes: [
                '10.0.0.0/16'
            ]
        }
        subnets: [
            {
                name: 'public-subnet'
                properties: {
                    addressPrefix: '10.0.1.0/24'
                }
            }
        ]
    }
}

Observa que en name y location se está llamando al nombre del parámetro correspondiente para obtener el valor.

Variables

Las variables tienen la misma funcionalidad que en cualquier lenguaje de programación, por supuesto, nos ayudan a simplificar el desarrollo de plantillas en Bicep, evitamos la repetición expresiones complejas. Al declarar variables en Bicep no es necesario especificar un tipo de datos. Continuando con el mismo ejemplo de la red virtual, vamos a declarar algunas variables:

var  env = 'dev'
var  vNetAddress = '10.0.0.0/16'
var  subnetName = 'public-subnet'
var  subnetAddress = '10.0.1.0/24'

La primera variable contiene el valor de la etiqueta ambiente, la segunda el prefijo de direcciones de la red virtual, la tercera el nombre de la subred y la última almacena el prefijo de direcciones para la subred. En la declaración completa del recurso usamos el nombre de las variables, quedaría de la siguiente forma:

resource  vNet  'Microsoft.Network/VirtualNetworks@2019-09-01' = {
    name: vNetName
    location: location
    tags: {
        env: env
    }
    properties: {
        addressSpace: {
            addressPrefixes: [
                vNetAddress
            ]
        }
        subnets: [
            {
                name: subnetName
                properties: {
                    addressPrefix: subnetAddress
                }
            }
        ]
    }
}

También, es posible utilizar el valor de un parámetro al crear una variable. Imagínate, que estás haciendo una implementación y quieres que el nombre de todos los recursos inicie con un prefijo igual, por ejemplo: nombre-vnet, nombre-ip, nombre-vm, nombre-disk, y así sucesivamente. En ese caso lo ideal es que pidas el nombre en un parámetro y luego lo uses en las variables. A continuación, te muestro:

param  Prefix  string
var  vNetName = '${Prefix}-vnet'

Outputs

En ocasiones es necesario devolver valores después hacer la implementación. Un ejemplo común, creamos una máquina virtual que será un servidor web y estará expuesto a Internet, necesitamos obtener la dirección IP pública sin tener que ir al portal de Azure.

output ip string = publicIP.properties.ipAddress

Este ejemplo también sirve para recordar el nombre simbólico que se les da a los recursos en la declaración, el cual puede ser reutilizado. En este caso publicIP corresponde a ese nombre, y a partir de ahí buscamos en las propiedades del recurso lo que necesitemos devolver.

Bien, estos son los elementos básicos, sirve a modo de introducción, pero hay muchas cosas más que podemos hacer con Bicep. Te invito a profundizar en el tema, las estructuras condicionales. También, investiga sobre los módulos que sirven para separar el código cuando trabajamos con soluciones complejas.

Implementar plantillas ARM

Hasta ahora hemos visto algunos elementos para crear plantillas ARM en Bicep, pero hace falta ver como implementar las plantillas. La instrucción sigue siendo la misma, en Azure CLI puedes hacerlo de la siguiente forma:

az deployment group create --resource-group NombreRG --template-file template.bicep

Donde NombreRG es el nombre de grupo de recursos y `template.bicep es el nombre del archivo que contiene la definición en Bicep.

Recuerda hacer la autenticación previamente en Azure con el comando az login.

Para obtener una vista previa de los cambios que se realizarán antes de hacer la implementación, agrega el parámetro –what-if.

az deployment group create --resource-group NombreRG --template-file template.bicep --what-if

La instrucción anterior únicamente muestra la vista previa de los cambios que se realizarán de acuerdo a la plantilla y la validación que hace contra Azure, y termina la ejecución. Para recibir una vista previa de los cambios y al mismo tiempo confirmar la implementación, ejecuta la siguiente instrucción:

az deployment group create --resource-group NombreRG --template-file template.bicep -c

El parámetro -c es un alias de --confirm-with-what-if

Convertir plantillas de JSON a Bicep

He mencionado que es posible convertir las plantillas ARM en JSON a Bicep, para quienes ya tienen implementaciones de plantillas ARM en JSON no será un problema hacer el cambio. Para descompilar el código JSON en Bicep, tan solo debes ejecutar la siguiente instrucción desde Azure CLI:

az bicep decompile --file template.json

Este comando creará un nuevo archivo con el mismo nombre y la extensión .bicep, en este caso sería template.bicep. Si utilizas PowerShell, ejecuta la instrucción:

bicep decompile template.json

Compartir este post

También te puede interesar...

AZ-500: Gestión de operaciones de seguridad

Curso AZ-500 Parte 7: Gestión de operaciones de seguridad

1 hora y 57 minutos · Empresas

Aprende a implementar Azure Monitor para monitorizar toda tu infraestructura, a recoger toda la información que ofrece el centro de seguridad de Azure y a …

  • Azure
AZ-104: Administración de Azure

Curso AZ-104 Parte 3: Administración de Azure

1 hora y 32 minutos · Empresas

Realizando este curso perteneciente al itinerario formativo de apoyo para obtener la certificación oficial AZ-104, aprenderás a utilizar las herramientas que usa un administrador de …

  • Azure
Tecnología

Qué es Azure: Introducción a la nube de Microsoft

28 Octubre 2019 Jesus Lucas
Artículos
Ver todos