Azure Resource Manager, el nuevo paradigma de Azure
Últimamente estamos escuchando hablar mucho de ARM en un contexto de Azure, y pese a que inicialmente nos sugiera la conocida arquitectura de procesadores, nada más lejos de la realidad, puesto que nos referimos a Azure Resource Manager, que es el nuevo paradigma sobre el que se estructura toda la administración de Microsoft Azure. Como hemos mencionado en otras ocasiones, Azure consta de una gran cantidad de componentes: máquinas virtuales, redes virtuales, almacenamiento, bases de datos, etc… que podemos combinar para ofrecer el servicio que queramos desplegar. Hasta ahora, en Azure estos distintos componentes constituían entidades discretas sin ninguna relación administrativa entre ellas, a pesar de que colaborasen entre sí para ofrecer una determinada solución; como lo es el caso en que un servidor web y una base de datos trabajan conjuntamente para hospedar un CMS como Drupal.
¿Qué es Azure Resource Manager?
Azure Resource Manager cambia este paradigma con el que hemos trabajado hasta ahora para componentenizar todos los elementos de Azure. Todos los componentes de Azure son ahora recursos, ya hablemos de una máquina virtual, su adaptador de red, una IP pública, una base de datos o un sitio web. Estos componentes se organizan en agrupaciones lógicas conocidas como grupos de recursos, que nos permiten aglutinarlos bajo una únidad administrativa que contiene la solución.
Así pues, imaginemos que queremos implementar un sistema de WordPress en IaaS. ¿Qué componentes necesitamos?
- 2 máquinas virtuales: az-wp-apache, az-wp-mysql
- 2 interfaces de red, una para cada máquina virtual: az-wp-apache-nic1, az-wp-mysql-nic2
- 1 red virtual: az-wp-vnet1
- 2 grupos de seguridad de red, uno para interfaz de red o máquina virtual: az-wp-apache-nsg1, az-wp-mysql-nsg2
- 1 cuenta de storage: az-wp-st01
- 1 dirección IP pública: az-wp-apache-pip
Todos estos componentes los podemos agrupar bajo un mismo grupo de recursos llamado az-wp-rg. Con ello hemos conseguido crear una unidad administrativa común para ellos. ¿Qué nos permite esta nueva unidad?
- Desplegar el mismo conjunto de recursos tantas veces como necesitemos, creando distintas instancias de WordPress con su correspondiente base de datos. Esto es posible gracias a que podemos extraer una plantilla con la definición completa de los elementos que hemos creado.
- Definir dependencias entre recursos de forma que se desplieguen en el orden correcto.
- Aplicar control de acceso basado en roles (RBAC) al grupo de recursos, de forma que podemos definir administradores de Azure sólo para esta solución, en lugar de para toda la suscripción como ocurría hasta ahora.
- Aplicar etiquetas a cada uno de los distintos recursos, lo que nos permite organizarlos mejor en la suscripción.
- Monitorizar el estado de salid de la solución completa que se encuentra contenida en el grupo de recursos.
- Ver los costes de la solución como conjunto, en lugar de la suma de los elementos separados.
- Eliminar todos los recursos de la implementación especificando a Azure que queremos borrar el grupo de recursos correspondiente. Hasta ahora, debíamos eliminar individualmente cada servicio y era fácil que se nos olvidase algo.
¿Cón qué hemos estado trabajando hasta ahora?
Hasta ahora el modelo de Azure con el que se trabajaba estaba orientado a servicio y se conoce como Azure Service Manager (ASM). Estas son las principales diferencias entre ambos modelos:
Azure Service Manager | Azure Resource Manager | |
Portal antiguo | Sí | No |
Portal nuevo | Sí | Sí |
API REST | XML | JSON |
RBAC | No | Sí |
Tags | No | Sí |
Automatización | Procedural (PowerShell y XML) | Declarativa (JSON) |
Grupos de recursos | No | Sí |
Recursos enlazados | Muy limitado | Sí |
A continuación podemos ver el aspecto de la administración de un grupo de recursos desde el nuevo portal de Azure. Como se observa en la captura, se trata de un grupo de recursos para hospedar un entorno de AD Connect y ADFS.
Plantillas JSON
Una de las grandes novedades y potencias del nuevo Azure Resource Manager son las plantillas JSON que nos permiten desplegar recursos de Azure de forma declarativa, encargándose la propia plataforma de las tareas implicadas en su despliegue. Estas plantillas están descritas con gran nivel de detalle aquí y se pueden observar multitud de ejemplos en este repositorio oficial de Microsoft en Github. Otra alternativa es visitar la galería de plantillas JSON de Azure donde se nos muestra el repositorio organizado gráficamente y con descripciones de cada una de ellas; ¡incluso podemos desplegarlas en nuestra suscripción con un sencillo clic de ratón!
Si vamos a construir una plantilla desde 0, es posible que nos resulte algo indigesto, así que para hacerlo sencillo lo mejor es valernos de la Azure Tools para Visual Studio (válido también para la versión gratuita Community). Al crear un nuevo proyecto tenemos opción a crear un nuevo Grupo de Recursos de Azure.
Tras lo cual se nos mostrará una serie de plantillas predefinidas en las que podemos basarnos para construir nuestro entorno. Si elegimos la de desplegar una máquina virtual con Ubuntu Server…
Veremos que en el Solution Explorer se nos crea la plantilla predefinida para llevar a cabo la implementación:
Con el siguiente código, que podemos modificar a nuestro gusto:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 |
{ "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", "contentVersion": "1.0.0.0", "parameters": { "adminUsername": { "type": "string", "minLength": 1, "metadata": { "description": "User name for the Virtual Machine." } }, "adminPassword": { "type": "securestring", "metadata": { "description": "Password for the Virtual Machine." } }, "dnsNameForPublicIP": { "type": "string", "minLength": 1, "metadata": { "description": "Globally unique DNS Name for the Public IP used to access the Virtual Machine." } }, "ubuntuOSVersion": { "type": "string", "defaultValue": "14.04.2-LTS", "allowedValues": [ "12.04.5-LTS", "14.04.2-LTS", "15.04" ], "metadata": { "description": "The Ubuntu version for the VM. This will pick a fully patched image of this given Ubuntu version. Allowed values: 12.04.5-LTS, 14.04.2-LTS, 15.04." } } }, "variables": { "imagePublisher": "Canonical", "imageOffer": "UbuntuServer", "OSDiskName": "osdiskforlinuxsimple", "nicName": "myVMNic", "addressPrefix": "10.0.0.0/16", "subnetName": "Subnet", "subnetPrefix": "10.0.0.0/24", "vhdStorageType": "Standard_LRS", "publicIPAddressType": "Dynamic", "vhdStorageContainerName": "vhds", "vmName": "MyUbuntuVM", "vmSize": "Standard_D1", "virtualNetworkName": "MyVNET", "vnetId": "[resourceId('Microsoft.Network/virtualNetworks', variables('virtualNetworkName'))]", "subnetRef": "[concat(variables('vnetId'), '/subnets/', variables('subnetName'))]", "vhdStorageName": "[concat('vhdstorage', uniqueString(resourceGroup().id))]" }, "resources": [ { "type": "Microsoft.Storage/storageAccounts", "name": "[variables('vhdStorageName')]", "apiVersion": "2015-06-15", "location": "[resourceGroup().location]", "tags": { "displayName": "StorageAccount" }, "properties": { "accountType": "[variables('vhdStorageType')]" } }, { "apiVersion": "2015-06-15", "type": "Microsoft.Network/publicIPAddresses", "name": "[parameters('dnsNameForPublicIP')]", "location": "[resourceGroup().location]", "tags": { "displayName": "PublicIPAddress" }, "properties": { "publicIPAllocationMethod": "[variables('publicIPAddressType')]", "dnsSettings": { "domainNameLabel": "[parameters('dnsNameForPublicIP')]" } } }, { "apiVersion": "2015-06-15", "type": "Microsoft.Network/virtualNetworks", "name": "[variables('virtualNetworkName')]", "location": "[resourceGroup().location]", "tags": { "displayName": "VirtualNetwork" }, "properties": { "addressSpace": { "addressPrefixes": [ "[variables('addressPrefix')]" ] }, "subnets": [ { "name": "[variables('subnetName')]", "properties": { "addressPrefix": "[variables('subnetPrefix')]" } } ] } }, { "apiVersion": "2015-06-15", "type": "Microsoft.Network/networkInterfaces", "name": "[variables('nicName')]", "location": "[resourceGroup().location]", "tags": { "displayName": "NetworkInterface" }, "dependsOn": [ "[concat('Microsoft.Network/publicIPAddresses/', parameters('dnsNameForPublicIP'))]", "[concat('Microsoft.Network/virtualNetworks/', variables('virtualNetworkName'))]" ], "properties": { "ipConfigurations": [ { "name": "ipconfig1", "properties": { "privateIPAllocationMethod": "Dynamic", "publicIPAddress": { "id": "[resourceId('Microsoft.Network/publicIPAddresses', parameters('dnsNameForPublicIP'))]" }, "subnet": { "id": "[variables('subnetRef')]" } } } ] } }, { "apiVersion": "2015-06-15", "type": "Microsoft.Compute/virtualMachines", "name": "[variables('vmName')]", "location": "[resourceGroup().location]", "tags": { "displayName": "VirtualMachine" }, "dependsOn": [ "[concat('Microsoft.Storage/storageAccounts/', variables('vhdStorageName'))]", "[concat('Microsoft.Network/networkInterfaces/', variables('nicName'))]" ], "properties": { "hardwareProfile": { "vmSize": "[variables('vmSize')]" }, "osProfile": { "computerName": "[variables('vmName')]", "adminUsername": "[parameters('adminUsername')]", "adminPassword": "[parameters('adminPassword')]" }, "storageProfile": { "imageReference": { "publisher": "[variables('imagePublisher')]", "offer": "[variables('imageOffer')]", "sku": "[parameters('ubuntuOSVersion')]", "version": "latest" }, "osDisk": { "name": "osdisk", "vhd": { "uri": "[concat('http://', variables('vhdStorageName'), '.blob.core.windows.net/', variables('vhdStorageContainerName'), '/', variables('OSDiskName'), '.vhd')]" }, "caching": "ReadWrite", "createOption": "FromImage" } }, "networkProfile": { "networkInterfaces": [ { "id": "[resourceId('Microsoft.Network/networkInterfaces', variables('nicName'))]" } ] } } } ] } |
Trabajar con ello desde Notepad o Vim podría ser indigesto, pero Visual Studio nos da una serie de ayudas para que la experiencia sea mucho más llevadera, como el explorador JSON, que nos muestra todos los parámetros, variables y recursos de Azure presentes en el código. ¡Anímate a probarlo!
Azure Resource Explorer
Aunque no sea especialmente conocido y se encuentre el Preview, Azure Resource Manager dispone de una herramienta llamada Azure Resource Explorer, a la que podemos acceder desde https://resources.azure.com. Tras validarnos con nuestras credenciales, la herramienta nos permite navegar por todos y cada uno de los recursos de nuestras subscripciones y hacer pruebas de llamadas a la API REST para realizar operaciones. Si ya tienes grupos de recursos en tu suscripción de Azure y quieres obtener el JSON para desplegarlos en otros entornos (todavía no disponible), esta herramienta resulta realmente útil. Pinta tal que así:
Azure Service Manager o Azure Resource Manager, ¿con cuál trabajo?
La opción por defecto debería ser Azure Resource Manager. El modelo ASM es a extinguir y aunque por razones obvias va a continuar teniendo soporte por parte de Microsoft durante mucho tiempo, todos los nuevos trabajos deberíamos hacerlos mediante ARM. Sin embargo, si hasta ahora has trabajado con ASM y quieres pasar a ARM, es importante que hagas las dos siguientes lecturas:
- Comprender las diferencias entre la implementación del Administrador de Recursos y la Implementación Clásica.
- Arquitectura del Administrador de Recursos.
Y eso ha sido todo por ahora. Espero que este post os sirva para ilustraros el mar de posibilidades que el nuevo modelo basado en recursos de Azure nos provee tanto a los profesionales de infraestructura como a los desarrolladores a la hora de sacar el máximo partido de la nube.
¡Felices Fiestas!