Administración de máquinas virtuales en Azure

No cabe duda que la virtualización presenta grandes ventajas. Por ejemplo, imaginemos el escenario en donde administramos una serie de servidores locales. Estos servidores sustentan la infraestructura de la empresa, desde controladores de dominio a servidores de bases de datos todo orquestado al detalle para un perfecto funcionamiento. Pero el hardware envejece y es necesario su reemplazo a medida que se va quedando obsoleto. Esto genera una serie de dificultades, como el tiempo que diariamente se debe invertir en este tipo de mantenimiento y la migración de nuestros servicios a nuevos servidores. En una empresa pequeña los servidores pueden estar ubicados en un mismo edificio pero en los entornos corporativos modernos, estos servidores se encuentran dispersos en diferentes localizaciones e incluso países muy distantes entre sí. ¿Cómo facilitar nuestra administración diaria? ¿Cómo podemos centralizar los procesos de mantenimiento y supervisión de nuestra infraestructura? ¿Y qué ocurre con la carga de trabajo? Si nuestros servidores reciben un aumento en su carga de trabajo. ¿Tenemos que comprar nuevos servidores?

Otro ejemplo, tenemos un laboratorio en donde vamos probando nuestras soluciones antes de ser implementadas finalmente. ¿Necesitamos replicar toda nuestra infraestructura de servidores? ¿Sólo una pequeña parte? ¿Qué recursos serán necesarios? ¿Qué coste añadido tendrá?

Virtualización

La virtualización no es algo nuevo. A todos nos suenan nombres como QEMU, VirtualBox, VMWare o Hyper-V.  A grandes líneas podría definirse como el proceso de crear una versión basada en software o "virtual" de un equipo, con cantidades dedicadas de CPU, memoria y almacenamiento que se "toman prestadas" de un equipo host físico, como su PC, o un servidor remoto, como un servidor en el centro de datos de un proveedor de nube.

La virtualización trae varias ventajas. Al ejecutarse como equipos individuales con aplicaciones y sistemas operativos individuales, las máquinas virtuales tienen la ventaja de que permanecen completamente independientes entre sí y respecto al equipo host físico. Un software denominado hipervisor, o administrador de máquinas virtuales, permite ejecutar diferentes sistemas operativos en varias máquinas virtuales al mismo tiempo. Esto permite ejecutar máquinas virtuales Linux, por ejemplo, en un sistema operativo Windows o ejecutar una versión anterior de Windows o incluso DOS en el sistema operativo Windows más actual.

  • Ahorro de costes: la ejecución de varios entornos virtuales en una única infraestructura reduce la necesidad de mantener un gran número de servidores y los costos de mantenimiento y electricidad.

  • Agilidad y velocidad: la puesta en marcha de una máquina virtual es relativamente fácil y rápida, y es mucho más sencilla para sus desarrolladores que el aprovisionamiento de un entorno nuevo completo.

  • Tiempo de inactividad reducido: las máquinas virtuales son muy portables y fáciles de migrar de un hipervisor a otro en un equipo diferente, por lo que son una solución excelente para copias de seguridad, en el caso de que el host deje de funcionar de forma inesperada.

  • Escalabilidad: las máquinas virtuales permiten escalar más fácilmente las aplicaciones agregando más servidores virtuales o físicos para distribuir la carga de trabajo entre varias máquinas virtuales.

Ventajas de seguridad: dado que las máquinas virtuales se ejecutan en varios sistemas operativos, el uso de un sistema operativo invitado en una máquina virtual permite ejecutar aplicaciones de una seguridad dudosa y proteger el sistema operativo host.

¿Para qué se usan las máquinas virtuales?

Estas son algunas formas de usar las máquinas virtuales:

  • Compilar e implementar aplicaciones en la nube.

  • Probar un nuevo sistema operativo (SO), incluidas las versiones beta.

  • Poner en marcha un nuevo entorno para que les resulte más sencillo y rápido a los desarrolladores ejecutar escenarios de desarrollo y pruebas.

  • Crear copias de seguridad del sistema operativo.

  • Acceder a datos infectados por virus o ejecutar una versión anterior de una aplicación con la instalación de un sistema operativo anterior.

  • Ejecutar software o aplicaciones en sistemas operativos para los que no se habían diseñado inicialmente.

Microsoft Azure

Microsoft Azure es un servicio de computación en la nube creado por Microsoft para construir, probar, desplegar y administrar aplicaciones y servicios mediante el uso de sus centros de datos. Microsoft ha apostado fuertemente en los servicios en la nube de Azure, incluida su infraestructura interna. Por este motivo, los esfuerzos de Microsoft le han llevado a desplegar todo tipo de posibilidades, tanto IaaS, PaaS o SaaS para la prestación de todo tipo de servicios para desarrolladores, productos para usuarios y, sorprendentemente, su propia arquitectura interna.

Azure Virtual Machines

Las máquinas virtuales de Azure permiten la implementación de una serie de aplicaciones y programas informáticos en un sistema virtualizado. Además, Azure también permite la virtualización de sistemas operativos Linux y de aplicaciones de Oracle, SAP o IBM, entre otros, por lo que también podemos migrar nuestros servidores físicos a un entorno virtual manteniendo un control total sobre la configuración e instalando todo aquello que sea necesario.

No es necesario, por tanto, comprar hardware físico para ampliar nuestro centros de datos. De todo esto se encarga Microsoft. Por último, Azure proporciona servicios adicionales para supervisar, proteger y administrar las actualizaciones y revisiones del sistema operativo.

Vamos a observar las decisiones tomadas antes de crear una máquina virtual, las opciones para crear y administrar la máquina virtual, y las extensiones y servicios que usa para us administración.

Crear una lista de comprobación para crear una máquina virtual de Azure

Si estamos pensando en migrar nuestros servidores, debemos prestar atención en que en muchas ocasiones la migración será de múltiples servidores locales al mismo tiempo. Es por eso que antes de comenzar debemos planificar el proceso para que ningún cabo quede suelto y esbozar el modelo de infraestructura actual y ver cómo puede asignarse a la nube. Muchas veces descubriremos que en la nube podemos ahorrar costes pues no siempre es necesario replicar nuestra infraestructura cuando por contra existen servicios que los pueden sustituir de una manera más eficiente.

Vamos a repasar una lista de comprobación con los elementos sobre los que hay que reflexionar.

  • Empezar por la red

  • Asignación de un nombre a la máquina virtual

  • Decidir la ubicación de la máquina virtual

  • Determinación del tamaño de la máquina virtual

  • Descripción del modelo de precios

  • Almacenamiento de la máquina virtual

  • Selección de un sistema operativo

La red

Las redes virtuales se usan en Azure para proporcionar conectividad privada entre Azure Virtual Machines y otros servicios de Azure. Las máquinas virtuales y servicios que forman parte de la misma red virtual tienen acceso mutuo. De forma predeterminada, los servicios fuera de la red virtual no pueden conectarse a los servicios dentro de la red virtual. No obstante, podemos configurar la red para permitir el acceso a un servicio externo, incluido el acceso a los servidores locales.

Esto último es el motivo por el que debemos invertir algún tiempo en reflexionar sobre la configuración de la red. Las direcciones de red y las subredes no son algo sencillo de cambiar una vez que se ha configurado y, si pretendemos conectar la red privada de la empresa a los servicios de Azure se tiene que tener en cuenta la topología antes de poner en marcha una máquina virtual.

Segregación de la red

Después de decidir los espacios de direcciones de la red virtual, podemos crear una o varias subredes. Esto se hace para dividir la red en secciones más fáciles de administrar. Por ejemplo, 10.1.0.0 a las máquinas virtuales, 10.2.0.0 a los servicios back-end y 10.3.0.0 a las máquinas virtuales con SQL Server.

Protección de la red

De forma predeterminada, no hay ningún límite de seguridad entre subredes, por lo que los servicios de cada una de estas subredes pueden comunicarse entre sí. Sin embargo, se pueden configurar grupos de seguridad de red (NSG), que permiten controlar el flujo de tráfico que llega y sale tanto de las subredes como de las máquinas virtuales. Los grupos de seguridad de red actúan como firewalls de software que aplican reglas personalizadas a cada solicitud entrante o saliente en el nivel de interfaz de red y de subred. Esto permite controlar completamente cada solicitud de red que entra o sale de la máquina virtual.

Planeamiento de la implementación de cada máquina virtual

Una vez que ha configurado la comunicación y los requisitos de red, ya podemos comenzar empezar a pensar en las máquinas virtuales que deseamos crear. Una buena idea es seleccionar un servidor y hacer un inventario:

  • ¿Con qué se comunica el servidor?

  • ¿Qué puertos están abiertos?

  • ¿Qué sistema operativo se usa?

  • ¿Cuánto espacio en disco está en uso?

  • ¿Qué tipo de datos usa? ¿Hay alguna restricción (legal o no) por no tenerlo en una ubicación local?

  • ¿Qué tipo de CPU, memoria y carga de E/S de disco tiene el servidor? ¿Hay picos de tráfico que se deban tener en cuenta?

Asignación de un nombre a la máquina virtual

Una parte de la información en la que los usuarios no suelen pensar mucho es el nombre de la máquina virtual. El nombre de la máquina virtual se usa como nombre del equipo, que está configurado como parte del sistema operativo. Puede especificar un nombre de hasta 15 caracteres en una máquina virtual Windows y hasta 64 caracteres en una máquina virtual Linux.

Este nombre también permite definir un recurso de Azure administrable y no es fácil de cambiar más tarde. Esto significa que debemos elegir nombres que sean significativos y coherentes para que pueda identificar fácilmente qué hace la máquina virtual. Una buena convención es incluir la siguiente información en el nombre:

  • Entorno: Identifica el entorno del recurso (desarrollo, producción, control de calidad)

  • Ubicación: Identifica la región en la que se implementa el recurso. uw (Oeste de EE. UU.), ue (este de EE. UU.)

  • Instancia: Para los recursos que tienen más de una instancia con nombre (servidores web, etc.)

  • Producto o servicio: Identifica el producto, la aplicación o el servicio que admite el recurso

  • Rol: Identifica el rol del recurso asociado (sql, web, mensajería)

Por ejemplo, devusc-webvm01 podría representar el primer servidor web de desarrollo hospedado en la ubicación Centro y Sur de EE. UU.

En este sentido, la recomendación es seguir la misma convención para cada recurso desplegado en Azure. Al igual que un equipo físico del centro de datos, las máquinas virtuales tienen varios elementos que son necesarios para realizar su trabajo:

  • La propia máquina virtual

  • Una cuenta de almacenamiento para los discos

  • Una red virtual (compartida con otras máquinas virtuales y servicios)

  • Una interfaz de red para comunicarse en la red virtual

  • Grupos de seguridad para proteger el tráfico de red

  • Una dirección pública de Internet (opcional)

Azure creará todos estos recursos si es necesario, o bien podemos  proporcionar los ya existentes como parte del proceso de implementación. Cada recurso necesita un nombre, que se utilizará para identificarlo. Si Azure crea el recurso, usará el nombre de la máquina virtual para generar un nombre de recurso. Esta es otra razón por la que es muy importante mantener la coherencia de los nombres de máquina virtual.

Determinación del tamaño de la máquina virtual

Una vez que se ha establecido el nombre y la ubicación, debemos decidir el tamaño de la máquina virtual. En lugar de especificar la capacidad de procesamiento, memoria y almacenamiento por separado, Azure proporciona una amplia gama de opciones de tamaño de máquina virtual, lo que le permite seleccionar la combinación adecuada de capacidad de proceso, memoria y almacenamiento para cada tarea.

La mejor manera de determinar el tamaño de máquina virtual adecuado es tener en cuenta el tipo de carga de trabajo que la máquina virtual debe ejecutar.

Desplegando nuestra máquina virtual en Azure

Creación de una máquina virtual de Windows en Azure Portal

Las máquinas virtuales de Azure pueden crearse mediante Azure Portal. Este método proporciona una interfaz de usuario basada en explorador para crear máquinas virtuales y sus recursos asociados. En esta guía de inicio rápido se muestra cómo usar Azure Portal para implementar una máquina virtual (VM) en Azure que ejecuta Windows Server 2019.

  1. Inicie sesión en Azure Portal en https://portal.azure.com.

  2. Escribe Virtual Machines en la búsqueda.

  3. En Servicios, selecciona Virtual Machines.

  4. En la página Máquinas virtuales, seleccionamos Agregar y, después, Máquina virtual.

En la pestaña Aspectos básicos, en Detalles del proyecto, debemos asegurarnos de que esté seleccionada la suscripción correcta y luego elija Crear nuevo grupo de recursos. Escriba myResourceGroup para el nombre.

En Detalles de instancia, escribe myVM en Nombre de máquina virtual y elija Este de EE. UU. como Región. Elija Windows Server 2019 Datacenter como la Imagen y Standard_DS1_v2 como Tamaño. Deja los demás valores predeterminados.

En Cuenta de administrador, proporciona un nombre de usuario, como azureuser, y una contraseña. La contraseña debe tener al menos 12 caracteres de largo y cumplir con los requisitos de complejidad definidos.

En Reglas de puerto de entrada, elije Permitir los puertos seleccionados y luego seleccione RDP (3389) y HTTP (80) en la lista desplegable.

Deja los valores predeterminados restantes y luego seleccione el botón “Review + create” en la parte inferior de la página.

  1. Después de que se ejecute la validación, selecciona el botón Create en la parte inferior de la página.

  2. Una vez finalizada la implementación, seleccione Ir al recurso.

Creación de una máquina virtual Windows en Azure con PowerShell

PowerShell es para muchos la navaja suiza que todo administrador de sistemas precisa. Es por ello que la creación de una máquina virtual en Azure mediante esta herramienta se torna muy interesante ya que podemos confeccionar un script que automatice la tarea hacia límites insospechados.

Creación de un grupo de recursos

Un grupo de recursos es un contenedor lógico en el que se implementan y se administran los recursos de Azure. Para crear  un grupo de recursos de Azure usaremos el comando New-AzResourceGroup.

New-AzResourceGroup -Name myResourceGroup -Location EastUS

Para crear una máquina virtual usaremos el comando New-AzVM. Ejecutando la siguiente instrucción, sustituyendo los campos entre comillas, podemos crear nuestra máquina:

New-AzVm `

-ResourceGroupName "myResourceGroup" `

-Name "myVM" `

-Location "East US" `

-VirtualNetworkName "myVnet" `

-SubnetName "mySubnet" `

-SecurityGroupName "myNetworkSecurityGroup" `

-PublicIpAddressName "myPublicIpAddress" `

-OpenPorts 80,3389

Cuando se  solicite, debemos proporcionar  un nombre de usuario y una contraseña que se usarán como credenciales de inicio de sesión para la máquina virtual.

Creación de una máquina virtual Windows con una plantilla de Resource Manager

Una plantilla de Resource Manager es un archivo de notación de objetos JavaScript (JSON) que define la infraestructura y la configuración del proyecto. La plantilla usa sintaxis declarativa. En la sintaxis declarativa, se describe la implementación deseada sin escribir la secuencia de comandos de programación para crearla.

Plantilla para VM Windows.

{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "metadata": {
    "_generator": {
      "name": "bicep",
      "version": "0.4.1.14562",
      "templateHash": "8381960602397537918"
    }
  },
  "parameters": {
    "adminUsername": {
      "type": "string",
      "metadata": {
        "description": "Username for the Virtual Machine."
      }
    },
    "adminPassword": {
      "type": "secureString",
      "minLength": 12,
      "metadata": {
        "description": "Password for the Virtual Machine."
      }
    },
    "dnsLabelPrefix": {
      "type": "string",
      "defaultValue": "[toLower(format('{0}-{1}', parameters('vmName'), uniqueString(resourceGroup().id, parameters('vmName'))))]",
      "metadata": {
        "description": "Unique DNS Name for the Public IP used to access the Virtual Machine."
      }
    },
    "publicIpName": {
      "type": "string",
      "defaultValue": "myPublicIP",
      "metadata": {
        "description": "Name for the Public IP used to access the Virtual Machine."
      }
    },
    "publicIPAllocationMethod": {
      "type": "string",
      "defaultValue": "Dynamic",
      "allowedValues": [
        "Dynamic",
        "Static"
      ],
      "metadata": {
        "description": "Allocation method for the Public IP used to access the Virtual Machine."
      }
    },
    "publicIpSku": {
      "type": "string",
      "defaultValue": "Basic",
      "allowedValues": [
        "Basic",
        "Standard"
      ],
      "metadata": {
        "description": "SKU for the Public IP used to access the Virtual Machine."
      }
    },
"OSVersion": {
      "type": "string",
      "defaultValue": "2019-Datacenter",
      "allowedValues": [
        "2008-R2-SP1",
        "2012-Datacenter",
        "2012-R2-Datacenter",
        "2016-Nano-Server",
        "2016-Datacenter-with-Containers",
        "2016-Datacenter",
        "2019-Datacenter",
        "2019-Datacenter-Core",
        "2019-Datacenter-Core-smalldisk",
        "2019-Datacenter-Core-with-Containers",
        "2019-Datacenter-Core-with-Containers-smalldisk",
        "2019-Datacenter-smalldisk",
        "2019-Datacenter-with-Containers",
        "2019-Datacenter-with-Containers-smalldisk"
      ],
      "metadata": {
        "description": "The Windows version for the VM. This will pick a fully patched image of this given Windows version."
      }
    },
    "vmSize": {
      "type": "string",
      "defaultValue": "Standard_D2_v3",
      "metadata": {
        "description": "Size of the virtual machine."
      }
    },
    "location": {
      "type": "string",
      "defaultValue": "[resourceGroup().location]",
      "metadata": {
        "description": "Location for all resources."
      }
    },
    "vmName": {
      "type": "string",
      "defaultValue": "simple-vm",
      "metadata": {
        "description": "Name of the virtual machine."
      }
    }
  },
  "functions": [],
  "variables": {
    "storageAccountName": "[format('bootdiags{0}', uniqueString(resourceGroup().id))]",
    "nicName": "myVMNic",
    "addressPrefix": "10.0.0.0/16",
    "subnetName": "Subnet",
    "subnetPrefix": "10.0.0.0/24",
    "virtualNetworkName": "MyVNET",
    "networkSecurityGroupName": "default-NSG"
  },
  "resources": [
    {
      "type": "Microsoft.Storage/storageAccounts",
      "apiVersion": "2021-04-01",
      "name": "[variables('storageAccountName')]",
      "location": "[parameters('location')]",
      "sku": {
"name": "Standard_LRS"
      },
      "kind": "Storage"
    },
    {
      "type": "Microsoft.Network/publicIPAddresses",
      "apiVersion": "2021-02-01",
      "name": "[parameters('publicIpName')]",
      "location": "[parameters('location')]",
      "sku": {
        "name": "[parameters('publicIpSku')]"
      },
      "properties": {
        "publicIPAllocationMethod": "[parameters('publicIPAllocationMethod')]",
        "dnsSettings": {
          "domainNameLabel": "[parameters('dnsLabelPrefix')]"
        }
      }
    },
    {
      "type": "Microsoft.Network/networkSecurityGroups",
      "apiVersion": "2021-02-01",
      "name": "[variables('networkSecurityGroupName')]",
      "location": "[parameters('location')]",
      "properties": {
        "securityRules": [
          {
            "name": "default-allow-3389",
            "properties": {
              "priority": 1000,
              "access": "Allow",
              "direction": "Inbound",
              "destinationPortRange": "3389",
              "protocol": "Tcp",
              "sourcePortRange": "*",
              "sourceAddressPrefix": "*",
              "destinationAddressPrefix": "*"
            }
          }
        ]
      }
    },
    {
      "type": "Microsoft.Network/virtualNetworks",
      "apiVersion": "2021-02-01",
      "name": "[variables('virtualNetworkName')]",
      "location": "[parameters('location')]",
      "properties": {
        "addressSpace": {
          "addressPrefixes": [
            "[variables('addressPrefix')]"
          ]
        }
      }
    },
    {
      "type": "Microsoft.Network/virtualNetworks/subnets",
      "apiVersion": "2021-02-01",
      "name": "[format('{0}/{1}', variables('virtualNetworkName'), variables('subnetName'))]",
      "properties": {
        "addressPrefix": "[variables('subnetPrefix')]",
        "networkSecurityGroup": {
          "id": "[resourceId('Microsoft.Network/networkSecurityGroups', variables('networkSecurityGroupName'))]"
        }
      },
      "dependsOn": [
        "[resourceId('Microsoft.Network/networkSecurityGroups', variables('networkSecurityGroupName'))]",
        "[resourceId('Microsoft.Network/virtualNetworks', variables('virtualNetworkName'))]"
      ]
    },
    {
      "type": "Microsoft.Network/networkInterfaces",
      "apiVersion": "2021-02-01",
      "name": "[variables('nicName')]",
      "location": "[parameters('location')]",
      "properties": {
        "ipConfigurations": [
          {
            "name": "ipconfig1",
            "properties": {
              "privateIPAllocationMethod": "Dynamic",
              "publicIPAddress": {
                "id": "[resourceId('Microsoft.Network/publicIPAddresses', parameters('publicIpName'))]"
              },
              "subnet": {
                "id": "[resourceId('Microsoft.Network/virtualNetworks/subnets', variables('virtualNetworkName'), variables('subnetName'))]"
              }
            }
          }
        ]
      },
      "dependsOn": [
        "[resourceId('Microsoft.Network/publicIPAddresses', parameters('publicIpName'))]",
        "[resourceId('Microsoft.Network/virtualNetworks/subnets', variables('virtualNetworkName'), variables('subnetName'))]"
      ]
    },
    {
      "type": "Microsoft.Compute/virtualMachines",
      "apiVersion": "2021-03-01",
      "name": "[parameters('vmName')]",
      "location": "[parameters('location')]",
      "properties": {
        "hardwareProfile": {
          "vmSize": "[parameters('vmSize')]"
        },
        "osProfile": {
          "computerName": "[parameters('vmName')]",
          "adminUsername": "[parameters('adminUsername')]",
          "adminPassword": "[parameters('adminPassword')]"
        },
        "storageProfile": {
          "imageReference": {
            "publisher": "MicrosoftWindowsServer",
            "offer": "WindowsServer",
            "sku": "[parameters('OSVersion')]",
            "version": "latest"
          },
          "osDisk": {
            "createOption": "FromImage",
            "managedDisk": {
              "storageAccountType": "StandardSSD_LRS"
            }
          },
          "dataDisks": [
            {
              "diskSizeGB": 1023,
"lun": 0,
              "createOption": "Empty"
            }
          ]
        },
        "networkProfile": {
          "networkInterfaces": [
            {
              "id": "[resourceId('Microsoft.Network/networkInterfaces', variables('nicName'))]"
            }
          ]
        },
        "diagnosticsProfile": {
          "bootDiagnostics": {
            "enabled": true,
            "storageUri": "[reference(resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName'))).primaryEndpoints.blob]"
          }
        }
      },
      "dependsOn": [
        "[resourceId('Microsoft.Network/networkInterfaces', variables('nicName'))]",
        "[resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName'))]"
      ]
    }
  ],
  "outputs": {
    "hostname": {
      "type": "string",
      "value": "[reference(resourceId('Microsoft.Network/publicIPAddresses', parameters('publicIpName'))).dnsSettings.fqdn]"
    }
  }
}

En la plantilla se definen varios recursos:

Plantilla para VM Linux

{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "projectName": {
      "type": "string",
      "metadata": {
        "description": "Specifies a name for generating resource names."
      }
    },
    "location": {
      "type": "string",
      "defaultValue": "[resourceGroup().location]",
      "metadata": {
        "description": "Specifies the location for all resources."
      }
    },
    "adminUsername": {
      "type": "string",
      "metadata": {
        "description": "Specifies a username for the Virtual Machine."
      }
    },
    "adminPublicKey": {
      "type": "string",
      "metadata": {
        "description": "Specifies the SSH rsa public key file as a string. Use \"ssh-keygen -t rsa -b 2048\" to generate your SSH key pairs."
      }
    },
    "vmSize": {
      "type": "string",
      "defaultValue": "Standard_D2s_v3",
      "metadata": {
        "description": "description"
      }
    }
  },
  "variables": {
    "vNetName": "[concat(parameters('projectName'), '-vnet')]",
    "vNetAddressPrefixes": "10.0.0.0/16",
    "vNetSubnetName": "default",
    "vNetSubnetAddressPrefix": "10.0.0.0/24",
    "vmName": "[concat(parameters('projectName'), '-vm')]",
    "publicIPAddressName": "[concat(parameters('projectName'), '-ip')]",
    "networkInterfaceName": "[concat(parameters('projectName'), '-nic')]",
    "networkSecurityGroupName": "[concat(parameters('projectName'), '-nsg')]",
    "networkSecurityGroupName2": "[concat(variables('vNetSubnetName'), '-nsg')]"
  },
  "resources": [
    {
      "type": "Microsoft.Network/networkSecurityGroups",
      "apiVersion": "2020-05-01",
      "name": "[variables('networkSecurityGroupName')]",
      "location": "[parameters('location')]",
      "properties": {
        "securityRules": [
          {
            "name": "ssh_rule",
            "properties": {
              "description": "Locks inbound down to ssh default port 22.",
              "protocol": "Tcp",
              "sourcePortRange": "*",
              "destinationPortRange": "22",
              "sourceAddressPrefix": "*",
              "destinationAddressPrefix": "*",
              "access": "Allow",
              "priority": 123,
              "direction": "Inbound"
            }
          }
        ]
      }
    },
    {
      "type": "Microsoft.Network/publicIPAddresses",
      "apiVersion": "2020-05-01",
      "name": "[variables('publicIPAddressName')]",
      "location": "[parameters('location')]",
      "properties": {
        "publicIPAllocationMethod": "Dynamic"
      },
      "sku": {
        "name": "Basic"
      }
    },
    {
      "comments": "Simple Network Security Group for subnet [variables('vNetSubnetName')]",
      "type": "Microsoft.Network/networkSecurityGroups",
      "apiVersion": "2020-05-01",
      "name": "[variables('networkSecurityGroupName2')]",
      "location": "[parameters('location')]",
      "properties": {
        "securityRules": [
          {
            "name": "default-allow-22",
"properties": {
              "priority": 1000,
              "access": "Allow",
              "direction": "Inbound",
              "destinationPortRange": "22",
              "protocol": "Tcp",
              "sourceAddressPrefix": "*",
              "sourcePortRange": "*",
              "destinationAddressPrefix": "*"
            }
          }
        ]
      }
    },
    {
      "type": "Microsoft.Network/virtualNetworks",
      "apiVersion": "2020-05-01",
      "name": "[variables('vNetName')]",
      "location": "[parameters('location')]",
      "dependsOn": [
        "[resourceId('Microsoft.Network/networkSecurityGroups', variables('networkSecurityGroupName2'))]"
      ],
      "properties": {
        "addressSpace": {
          "addressPrefixes": [
            "[variables('vNetAddressPrefixes')]"
          ]
        },
        "subnets": [
          {
            "name": "[variables('vNetSubnetName')]",
            "properties": {
              "addressPrefix": "[variables('vNetSubnetAddressPrefix')]",
              "networkSecurityGroup": {
                "id": "[resourceId('Microsoft.Network/networkSecurityGroups', variables('networkSecurityGroupName2'))]"
              }
            }
          }
        ]
      }
    },
    {
      "type": "Microsoft.Network/networkInterfaces",
      "apiVersion": "2020-05-01",
      "name": "[variables('networkInterfaceName')]",
      "location": "[parameters('location')]",
      "dependsOn": [
        "[resourceId('Microsoft.Network/publicIPAddresses', variables('publicIPAddressName'))]",
        "[resourceId('Microsoft.Network/virtualNetworks', variables('vNetName'))]",
        "[resourceId('Microsoft.Network/networkSecurityGroups', variables('networkSecurityGroupName'))]"
      ],
      "properties": {
        "ipConfigurations": [
          {
 "name": "ipconfig1",
            "properties": {
              "privateIPAllocationMethod": "Dynamic",
              "publicIPAddress": {
                "id": "[resourceId('Microsoft.Network/publicIPAddresses', variables('publicIPAddressName'))]"
              },
              "subnet": {
                "id": "[resourceId('Microsoft.Network/virtualNetworks/subnets', variables('vNetName'), variables('vNetSubnetName'))]"
              }
            }
          }
        ]
      }
    },
    {
      "type": "Microsoft.Compute/virtualMachines",
      "apiVersion": "2019-12-01",
      "name": "[variables('vmName')]",
      "location": "[parameters('location')]",
      "dependsOn": [
        "[resourceId('Microsoft.Network/networkInterfaces', variables('networkInterfaceName'))]"
      ],
      "properties": {
        "hardwareProfile": {
          "vmSize": "[parameters('vmSize')]"
        },
        "osProfile": {
          "computerName": "[variables('vmName')]",
          "adminUsername": "[parameters('adminUsername')]",
          "linuxConfiguration": {
            "disablePasswordAuthentication": true,
            "ssh": {
              "publicKeys": [
                {
                  "path": "[concat('/home/', parameters('adminUsername'), '/.ssh/authorized_keys')]",
                  "keyData": "[parameters('adminPublicKey')]"
                }
              ]
            }
          }
        },
        "storageProfile": {
          "imageReference": {
            "publisher": "Canonical",
            "offer": "UbuntuServer",
            "sku": "18.04-LTS",
            "version": "latest"
          },
          "osDisk": {
            "createOption": "fromImage"
          }
        },
        "networkProfile": {
          "networkInterfaces": [
            {
              "id": "[resourceId('Microsoft.Network/networkInterfaces', variables('networkInterfaceName'))]"
            }
          ]
        }
      }
    }
  ]
}

Implementación de la plantilla

Podemos implementar una plantilla desde la máquina local o una que esté almacenada externamente en otra ubicación en la nube. Como ejemplo aquí trataremos la implementación de una plantilla local.

Antes de comenzar debemos asegurarnos que el grupo de recursos donde se hará el despliegue existe. El nombre del grupo de recursos solo puede incluir caracteres alfanuméricos, puntos, guiones bajos, guiones y paréntesis. Puede tener hasta 90 caracteres. El nombre no puede terminar con un punto.

Para continuar usaremos el comando New-AzResourceGroupDeployment  tal como se describe en el presente ejemplo:

New-AzResourceGroupDeployment `

-Name ExampleDeployment `

-ResourceGroupName ExampleGroup `

-TemplateFile <path-to-template>

Alternativamente podemos usar una plantilla remota usando el parámetro  -TemplateUri. El siguiente Script puede servir de ejemplo para implementaciones más detalladas.

$resourceGroupName = Read-Host -Prompt "Enter the Resource Group name"

$location = Read-Host -Prompt "Enter the location (i.e. centralus)"

$adminUsername = Read-Host -Prompt "Enter the administrator username"

$adminPassword = Read-Host -Prompt "Enter the administrator password" -AsSecureString

$dnsLabelPrefix = Read-Host -Prompt "Enter an unique DNS name for the public IP"

New-AzResourceGroup -Name $resourceGroupName -Location "$location"

New-AzResourceGroupDeployment `

-ResourceGroupName $resourceGroupName `

-TemplateUri "https://raw.githubusercontent.com/Azure/azure-quickstart-templates/maste..." `

-adminUsername $adminUsername `

-adminPassword $adminPassword `

-dnsLabelPrefix $dnsLabelPrefix

(Get-AzVm -ResourceGroupName $resourceGroupName).name

Conexión a la máquina virtual

Una vez que la máquina virtual se encuentra desplegada seguramente necesitemos poder acceder a esta para continuar nuestro proceso de configuración. Dependiendo del tipo de máquina y su sistema operativo el proceso puede ser ligeramente diferente.

Conexión a una máquina virtual Linux:

Para realizar este tipo de conexión utilizaremos un enlace mediante SSH con la maquina virtual. Esto es muy fácil. En Mac o Linux solo necesitamos abrir el Bash en el terminal mientras que en Windows aunque podemos utilizar PowerShell quizá necesitemos apoyarnos en herramientas como Putty para hacer el proceso más simple en el futuro.

En el símbolo del sistema, abrimos una conexión SSH a la máquina virtual. Reemplazando  la dirección IP por la de la máquina virtual y reemplace la ruta de acceso al archivo .pem por la ruta de acceso a la ubicación en la que se descargó el archivo de clave.

ssh -i .\Downloads\myKey1.pem azureuser@10.111.12.123

Conexión a una máquina virtual Windows

Para crear una conexión a una máquina virtual Windows usaremos RDP. En Windows es muy sencillo puesto que disponemos de un cliente nativo para su uso, mientras, en Linux o Mac necesitaremos instalar un cliente RDP como este Cliente de Escritorio remoto disponible en la Mac App Store.

En la página de información general de la máquina virtual, seleccionamos el botón Conectar y, luego, RDP.

En la página Connect with RDP (Conectar con RDP), mantenemos las opciones predeterminadas para conectarse por la dirección IP, a través del puerto 3389, y hacemos clic en Descargar archivo RDP.

Ahora abrimos el archivo RDP que descargamos y hacemos clic en Conectar cuando el cliente lo solicite.

En la ventana Seguridad de Windows, seleccionamos Más opciones y, después, Usar otra cuenta. Escriba el nombre de usuario como localhost\username, escribimos la contraseña que se definió para la máquina virtual y, luego, clic en Aceptar.

Ahora recibiremos una advertencia de certificado durante el proceso de inicio de sesión. Hacemos clic en Sí o en Continuar para crear la conexión.

Conclusión

Y llegamos al final de este artículo. En éste hemos visto que es una Máquina Virtual y sus ventajas en Azure. Además hemos hablado de cómo hacer su despliegue tomando en cuenta diferentes consideraciones previas y realizando la acción usando métodos como el portal de usuario, Powershell o mediante el uso de plantillas ARM.  El artículo quizá ha resultado algo extenso pero hemos intentado resumirlo todo lo posible confiando que sirva de ayuda e introducción.

Si te ha gustado, no dudes en compartirlo en redes sociales o dejar tu comentario.