Inicio rápido: Creación de un conjunto de escalado de máquinas virtuales Windows con una plantilla de Resource Manager

Se aplica a: ✔️ Máquinas virtuales Linux ✔️ Conjuntos de escalado uniformes

Nota

El siguiente artículo es para conjuntos de escalado de máquinas virtuales uniformes. Se recomienda usar conjuntos de escalado de máquinas virtuales del modo Flexible para nuevas cargas de trabajo. Para más información sobre este nuevo modo de orquestación, consulte Introducción a los conjuntos de escalado de máquinas virtuales flexibles.

El conjunto de escalado de máquinas virtuales le permite implementar y administrar un conjunto de máquinas virtuales de escalado automático. Puede escalar el número de máquinas virtuales del conjunto de escalado manualmente o definir reglas de escalado automático según el uso de recursos tales como la CPU, la demanda de memoria o el tráfico de red. Un equilibrador de carga de Azure distribuirá el tráfico a las instancias de máquina virtual del conjunto de escalado. En este inicio rápido, creará un conjunto de escalado de máquinas virtuales e implementará una aplicación de ejemplo con una plantilla de Azure Resource Manager.

Una plantilla de Azure Resource Manager es un archivo de notación de objetos JavaScript (JSON) que define tanto la infraestructura como la configuración de un proyecto. La plantilla usa sintaxis declarativa. Se describe la implementación deseada sin escribir la secuencia de comandos de programación para crear la implementación.

Las plantillas de Resource Manager permiten implementar grupos de recursos relacionados. En una única plantilla, puede crear el conjunto de escalado de máquinas virtuales, instalar aplicaciones y configurar reglas de escalado automático. Con el uso de variables y parámetros, esta plantilla se puede reutilizar para actualizar los conjuntos de escalado existentes o crear más. Puede implementar plantillas mediante Azure Portal, la CLI de Azure, Azure PowerShell, o bien desde las canalizaciones de integración continua o entrega continua (CI/CD).

Si su entorno cumple los requisitos previos y está familiarizado con el uso de plantillas de Resource Manager, seleccione el botón Implementar en Azure. La plantilla se abrirá en Azure Portal.

Button to deploy the Resource Manager template to Azure.

Requisitos previos

Si no tiene una suscripción a Azure, cree una cuenta gratuita antes de empezar.

Revisión de la plantilla

La plantilla usada en este inicio rápido forma parte de las plantillas de inicio rápido de Azure.

{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "metadata": {
    "_generator": {
      "name": "bicep",
      "version": "0.25.53.49325",
      "templateHash": "9083237914224042883"
    }
  },
  "parameters": {
    "vmssName": {
      "type": "string",
      "minLength": 3,
      "maxLength": 61,
      "metadata": {
        "description": "String used as a base for naming resources. Must be 3-61 characters in length and globally unique across Azure. A hash is prepended to this string for some resources, and resource-specific information is appended."
      }
    },
    "vmSku": {
      "type": "string",
      "defaultValue": "Standard_D2s_v3",
      "metadata": {
        "description": "Size of VMs in the VM Scale Set."
      }
    },
    "windowsOSVersion": {
      "type": "string",
      "defaultValue": "2022-datacenter-azure-edition",
      "allowedValues": [
        "2019-DataCenter-GenSecond",
        "2016-DataCenter-GenSecond",
        "2022-datacenter-azure-edition"
      ],
      "metadata": {
        "description": "The Windows version for the VM. This will pick a fully patched image of this given Windows version. Allowed values: 2008-R2-SP1, 2012-Datacenter, 2012-R2-Datacenter & 2016-Datacenter, 2019-Datacenter."
      }
    },
    "securityType": {
      "type": "string",
      "defaultValue": "TrustedLaunch",
      "allowedValues": [
        "Standard",
        "TrustedLaunch"
      ],
      "metadata": {
        "description": "Security Type of the Virtual Machine."
      }
    },
    "instanceCount": {
      "type": "int",
      "defaultValue": 3,
      "minValue": 1,
      "maxValue": 100,
      "metadata": {
        "description": "Number of VM instances (100 or less)."
      }
    },
    "singlePlacementGroup": {
      "type": "bool",
      "defaultValue": true,
      "metadata": {
        "description": "When true this limits the scale set to a single placement group, of max size 100 virtual machines. NOTE: If singlePlacementGroup is true, it may be modified to false. However, if singlePlacementGroup is false, it may not be modified to true."
      }
    },
    "adminUsername": {
      "type": "string",
      "defaultValue": "vmssadmin",
      "metadata": {
        "description": "Admin username on all VMs."
      }
    },
    "adminPassword": {
      "type": "securestring",
      "metadata": {
        "description": "Admin password on all VMs."
      }
    },
    "_artifactsLocation": {
      "type": "string",
      "defaultValue": "[deployment().properties.templateLink.uri]",
      "metadata": {
        "description": "The base URI where artifacts required by this template are located. For example, if stored on a public GitHub repo, you'd use the following URI: https://raw.githubusercontent.com/Azure/azure-quickstart-templates/master/201-vmss-windows-webapp-dsc-autoscale/."
      }
    },
    "_artifactsLocationSasToken": {
      "type": "securestring",
      "defaultValue": "",
      "metadata": {
        "description": "The sasToken required to access _artifactsLocation.  If your artifacts are stored on a public repo or public storage account you can leave this blank."
      }
    },
    "powershelldscZip": {
      "type": "string",
      "defaultValue": "DSC/InstallIIS.zip",
      "metadata": {
        "description": "Location of the PowerShell DSC zip file relative to the URI specified in the _artifactsLocation, i.e. DSC/IISInstall.ps1.zip"
      }
    },
    "webDeployPackage": {
      "type": "string",
      "defaultValue": "WebDeploy/DefaultASPWebApp.v1.0.zip",
      "metadata": {
        "description": "Location of the  of the WebDeploy package zip file relative to the URI specified in _artifactsLocation, i.e. WebDeploy/DefaultASPWebApp.v1.0.zip"
      }
    },
    "powershelldscUpdateTagVersion": {
      "type": "string",
      "defaultValue": "1.0",
      "metadata": {
        "description": "Version number of the DSC deployment. Changing this value on subsequent deployments will trigger the extension to run."
      }
    },
    "location": {
      "type": "string",
      "defaultValue": "[resourceGroup().location]",
      "metadata": {
        "description": "Location for all resources."
      }
    },
    "platformFaultDomainCount": {
      "type": "int",
      "defaultValue": 1,
      "metadata": {
        "description": "Fault Domain count for each placement group."
      }
    }
  },
  "variables": {
    "vmScaleSetName": "[toLower(substring(format('vmssName{0}', uniqueString(resourceGroup().id)), 0, 9))]",
    "longvmScaleSet": "[toLower(parameters('vmssName'))]",
    "addressPrefix": "10.0.0.0/16",
    "subnetPrefix": "10.0.0.0/24",
    "vNetName": "[format('{0}vnet', variables('vmScaleSetName'))]",
    "publicIPAddressName": "[format('{0}pip', variables('vmScaleSetName'))]",
    "subnetName": "[format('{0}subnet', variables('vmScaleSetName'))]",
    "loadBalancerName": "[format('{0}lb', variables('vmScaleSetName'))]",
    "publicIPAddressID": "[resourceId('Microsoft.Network/publicIPAddresses', variables('publicIPAddressName'))]",
    "lbProbeID": "[resourceId('Microsoft.Network/loadBalancers/probes', variables('loadBalancerName'), 'tcpProbe')]",
    "natPoolName": "[format('{0}natpool', variables('vmScaleSetName'))]",
    "bePoolName": "[format('{0}bepool', variables('vmScaleSetName'))]",
    "lbPoolID": "[resourceId('Microsoft.Network/loadBalancers/backendAddressPools', variables('loadBalancerName'), variables('bePoolName'))]",
    "natStartPort": 50000,
    "natEndPort": 50119,
    "natBackendPort": 3389,
    "nicName": "[format('{0}nic', variables('vmScaleSetName'))]",
    "ipConfigName": "[format('{0}ipconfig', variables('vmScaleSetName'))]",
    "frontEndIPConfigID": "[resourceId('Microsoft.Network/loadBalancers/frontendIPConfigurations', variables('loadBalancerName'), 'loadBalancerFrontEnd')]",
    "osType": {
      "publisher": "MicrosoftWindowsServer",
      "offer": "WindowsServer",
      "sku": "[parameters('windowsOSVersion')]",
      "version": "latest"
    },
    "securityProfileJson": {
      "uefiSettings": {
        "secureBootEnabled": true,
        "vTpmEnabled": true
      },
      "securityType": "[parameters('securityType')]"
    },
    "imageReference": "[variables('osType')]",
    "webDeployPackageFullPath": "[uri(parameters('_artifactsLocation'), format('{0}{1}', parameters('webDeployPackage'), parameters('_artifactsLocationSasToken')))]",
    "powershelldscZipFullPath": "[uri(parameters('_artifactsLocation'), format('{0}{1}', parameters('powershelldscZip'), parameters('_artifactsLocationSasToken')))]"
  },
  "resources": [
    {
      "type": "Microsoft.Network/loadBalancers",
      "apiVersion": "2023-04-01",
      "name": "[variables('loadBalancerName')]",
      "location": "[parameters('location')]",
      "properties": {
        "frontendIPConfigurations": [
          {
            "name": "LoadBalancerFrontEnd",
            "properties": {
              "publicIPAddress": {
                "id": "[variables('publicIPAddressID')]"
              }
            }
          }
        ],
        "backendAddressPools": [
          {
            "name": "[variables('bePoolName')]"
          }
        ],
        "inboundNatPools": [
          {
            "name": "[variables('natPoolName')]",
            "properties": {
              "frontendIPConfiguration": {
                "id": "[variables('frontEndIPConfigID')]"
              },
              "protocol": "Tcp",
              "frontendPortRangeStart": "[variables('natStartPort')]",
              "frontendPortRangeEnd": "[variables('natEndPort')]",
              "backendPort": "[variables('natBackendPort')]"
            }
          }
        ],
        "loadBalancingRules": [
          {
            "name": "LBRule",
            "properties": {
              "frontendIPConfiguration": {
                "id": "[variables('frontEndIPConfigID')]"
              },
              "backendAddressPool": {
                "id": "[variables('lbPoolID')]"
              },
              "protocol": "Tcp",
              "frontendPort": 80,
              "backendPort": 80,
              "enableFloatingIP": false,
              "idleTimeoutInMinutes": 5,
              "probe": {
                "id": "[variables('lbProbeID')]"
              }
            }
          }
        ],
        "probes": [
          {
            "name": "tcpProbe",
            "properties": {
              "protocol": "Tcp",
              "port": 80,
              "intervalInSeconds": 5,
              "numberOfProbes": 2
            }
          }
        ]
      },
      "dependsOn": [
        "[resourceId('Microsoft.Network/publicIPAddresses', variables('publicIPAddressName'))]"
      ]
    },
    {
      "type": "Microsoft.Compute/virtualMachineScaleSets",
      "apiVersion": "2023-09-01",
      "name": "[variables('vmScaleSetName')]",
      "location": "[parameters('location')]",
      "sku": {
        "name": "[parameters('vmSku')]",
        "tier": "Standard",
        "capacity": "[parameters('instanceCount')]"
      },
      "properties": {
        "overprovision": true,
        "upgradePolicy": {
          "mode": "Automatic"
        },
        "singlePlacementGroup": "[parameters('singlePlacementGroup')]",
        "platformFaultDomainCount": "[parameters('platformFaultDomainCount')]",
        "virtualMachineProfile": {
          "storageProfile": {
            "osDisk": {
              "caching": "ReadWrite",
              "createOption": "FromImage"
            },
            "imageReference": "[variables('imageReference')]"
          },
          "osProfile": {
            "computerNamePrefix": "[variables('vmScaleSetName')]",
            "adminUsername": "[parameters('adminUsername')]",
            "adminPassword": "[parameters('adminPassword')]"
          },
          "securityProfile": "[if(equals(parameters('securityType'), 'TrustedLaunch'), variables('securityProfileJson'), null())]",
          "networkProfile": {
            "networkInterfaceConfigurations": [
              {
                "name": "[variables('nicName')]",
                "properties": {
                  "primary": true,
                  "ipConfigurations": [
                    {
                      "name": "[variables('ipConfigName')]",
                      "properties": {
                        "subnet": {
                          "id": "[reference(resourceId('Microsoft.Network/virtualNetworks', variables('vNetName')), '2023-04-01').subnets[0].id]"
                        },
                        "loadBalancerBackendAddressPools": [
                          {
                            "id": "[variables('lbPoolID')]"
                          }
                        ]
                      }
                    }
                  ]
                }
              }
            ]
          },
          "extensionProfile": {
            "extensions": [
              {
                "name": "Microsoft.Powershell.DSC",
                "properties": {
                  "publisher": "Microsoft.Powershell",
                  "type": "DSC",
                  "typeHandlerVersion": "2.9",
                  "autoUpgradeMinorVersion": true,
                  "forceUpdateTag": "[parameters('powershelldscUpdateTagVersion')]",
                  "settings": {
                    "configuration": {
                      "url": "[variables('powershelldscZipFullPath')]",
                      "script": "InstallIIS.ps1",
                      "function": "InstallIIS"
                    },
                    "configurationArguments": {
                      "nodeName": "localhost",
                      "WebDeployPackagePath": "[variables('webDeployPackageFullPath')]"
                    }
                  }
                }
              }
            ]
          }
        }
      },
      "dependsOn": [
        "[resourceId('Microsoft.Network/virtualNetworks', variables('vNetName'))]"
      ]
    },
    {
      "type": "Microsoft.Network/publicIPAddresses",
      "apiVersion": "2023-04-01",
      "name": "[variables('publicIPAddressName')]",
      "location": "[parameters('location')]",
      "properties": {
        "publicIPAllocationMethod": "Static",
        "dnsSettings": {
          "domainNameLabel": "[variables('longvmScaleSet')]"
        }
      }
    },
    {
      "type": "Microsoft.Network/virtualNetworks",
      "apiVersion": "2023-04-01",
      "name": "[variables('vNetName')]",
      "location": "[parameters('location')]",
      "properties": {
        "addressSpace": {
          "addressPrefixes": [
            "[variables('addressPrefix')]"
          ]
        },
        "subnets": [
          {
            "name": "[variables('subnetName')]",
            "properties": {
              "addressPrefix": "[variables('subnetPrefix')]"
            }
          }
        ]
      }
    },
    {
      "type": "Microsoft.Insights/autoscalesettings",
      "apiVersion": "2022-10-01",
      "name": "autoscalehost",
      "location": "[parameters('location')]",
      "properties": {
        "name": "autoscalehost",
        "targetResourceUri": "[resourceId('Microsoft.Compute/virtualMachineScaleSets', variables('vmScaleSetName'))]",
        "enabled": true,
        "profiles": [
          {
            "name": "Profile1",
            "capacity": {
              "minimum": "1",
              "maximum": "10",
              "default": "1"
            },
            "rules": [
              {
                "metricTrigger": {
                  "metricName": "Percentage CPU",
                  "metricResourceUri": "[resourceId('Microsoft.Compute/virtualMachineScaleSets', variables('vmScaleSetName'))]",
                  "timeGrain": "PT1M",
                  "statistic": "Average",
                  "timeWindow": "PT5M",
                  "timeAggregation": "Average",
                  "operator": "GreaterThan",
                  "threshold": 50
                },
                "scaleAction": {
                  "direction": "Increase",
                  "type": "ChangeCount",
                  "value": "1",
                  "cooldown": "PT5M"
                }
              },
              {
                "metricTrigger": {
                  "metricName": "Percentage CPU",
                  "metricResourceUri": "[resourceId('Microsoft.Compute/virtualMachineScaleSets', variables('vmScaleSetName'))]",
                  "timeGrain": "PT1M",
                  "statistic": "Average",
                  "timeWindow": "PT5M",
                  "timeAggregation": "Average",
                  "operator": "LessThan",
                  "threshold": 30
                },
                "scaleAction": {
                  "direction": "Decrease",
                  "type": "ChangeCount",
                  "value": "1",
                  "cooldown": "PT5M"
                }
              }
            ]
          }
        ]
      },
      "dependsOn": [
        "[resourceId('Microsoft.Compute/virtualMachineScaleSets', variables('vmScaleSetName'))]"
      ]
    }
  ],
  "outputs": {
    "applicationUrl": {
      "type": "string",
      "value": "[uri(format('http://{0}', reference(resourceId('Microsoft.Network/publicIPAddresses', variables('publicIPAddressName')), '2023-04-01').dnsSettings.fqdn), '/MyApp')]"
    }
  }
}

Estos recursos se definen en estas plantillas:

Definición de un conjunto de escalado

Para crear una escala con una plantilla, debe definir los recursos adecuados. Las partes principales del tipo de recurso del conjunto de escalado de máquinas virtuales son:

Propiedad Descripción de la propiedad Valor de la plantilla de ejemplo
type Tipo de recurso de Azure que se creará Microsoft.Compute/virtualMachineScaleSets
name Nombre del conjunto de escalado myScaleSet
ubicación Ubicación donde se creará el conjunto de escalado Este de EE. UU.
sku.name Tamaño de VM para cada instancia de conjunto de escalado Standard_A1
sku.capacity Número de instancias de VM que se crearán inicialmente 2
upgradePolicy.mode Modo de actualización de la instancia de VM cuando se producen cambios Automático
imageReference Imagen personalizada o plataforma que se usará para las instancias de VM Microsoft Windows Server 2016 Datacenter
osProfile.computerNamePrefix Prefijo de nombre para cada instancia de VM myvmss
osProfile.adminUsername Nombre de usuario para cada instancia de VM azureuser
osProfile.adminPassword Contraseña para cada instancia de VM P@ssw0rd!

Para personalizar una plantilla de conjunto de escalado, puede cambiar el tamaño de la máquina virtual o la capacidad inicial. Otra opción es usar una plataforma diferente o una imagen personalizada.

Adición de una aplicación de ejemplo

Para probar el conjunto de escalado, instale una aplicación web básica. Cuando se implementa un conjunto de escalado, las extensiones de VM pueden proporcionar tareas de configuración y automatización posteriores a la implementación, como la instalación de una aplicación. Los scripts se pueden descargar desde Azure Storage o GitHub, o se pueden proporcionar a Azure Portal en el tiempo de ejecución de la extensión. Para aplicar una extensión al conjunto de escalado, agregue la sección extensionProfile en el ejemplo anterior del recurso. Normalmente, el perfil de extensión define las propiedades siguientes:

  • Tipo de extensión
  • Editor de la extensión
  • Versión de la extensión
  • Ubicación de los scripts de configuración o instalación
  • Comandos que se ejecutarán en las instancias de VM

La plantilla usa la extensión DSC de PowerShell para instalar una aplicación ASP.NET MVC que se ejecuta en IIS.

Se descarga un script de instalación desde GitHub, tal como se define en url. A continuación, la extensión ejecuta InstallIIS desde el script IISInstall.ps1, tal como se define en function y script. La propia aplicación de ASP.NET se proporciona como un paquete de Web Deploy, que también se descarga desde GitHub, tal como se define en WebDeployPackagePath:

Implementación de la plantilla

Puede implementar la plantilla si selecciona el botón Implementar en Azure. Este botón abre Azure Portal, carga la plantilla completa y pide algunos parámetros, como un nombre para el conjunto de escalado, el recuento de instancias y las credenciales de administrador.

Button to deploy the Resource Manager template to Azure.

También puede implementar una plantilla de Resource Manager mediante Azure PowerShell:

# Create a resource group
New-AzResourceGroup -Name myResourceGroup -Location EastUS

# Deploy template into resource group
New-AzResourceGroupDeployment `
    -ResourceGroupName myResourceGroup `
    -TemplateURI https://raw.githubusercontent.com/Azure/azure-quickstart-templates/master/demos/vmss-windows-webapp-dsc-autoscale/azuredeploy.json

# Update the scale set and apply the extension
Update-AzVmss `
    -ResourceGroupName myResourceGroup `
    -VmScaleSetName myVMSS `
    -VirtualMachineScaleSet $vmssConfig

Responda a los avisos para proporcionar un nombre para el conjunto de escalado y las credenciales de administrador de las instancias de VM. El proceso de creación del conjunto de escalado y la aplicación de la extensión para configurar la aplicación puede tardar entre 10 y 15 minutos.

Validación de la implementación

Para ver el conjunto de escalado en acción, acceda a la aplicación web de ejemplo en un explorador web. Obtenga la dirección IP pública del equilibrador de carga con Get-AzPublicIPAddress de la siguiente manera:

Get-AzPublicIpAddress -ResourceGroupName myResourceGroup | Select IpAddress

Escriba la dirección IP pública del equilibrador de carga en un explorador web con el formato http://publicIpAddress/MyApp. El equilibrador de carga distribuye el tráfico a una de las instancias de VM, como se muestra en el ejemplo siguiente:

Running IIS site

Limpieza de recursos

Cuando ya no lo necesite, puede usar el comando Remove-AzResourceGroup para quitar el grupo de recursos y el conjunto de escalado. El parámetro -Force confirma que desea eliminar los recursos sin pedir confirmación adicional. El parámetro -AsJob devuelve el control a la petición de confirmación sin esperar a que finalice la operación.

Remove-AzResourceGroup -Name "myResourceGroup" -Force -AsJob

Pasos siguientes

En este inicio rápido, ha creado un conjunto de escalado de Windows con una plantilla de Resource Manager y ha usado la extensión DSC de PowerShell para instalar una aplicación ASP.NET básica en las instancias de máquina virtual. Para más información, continúe con el tutorial sobre cómo crear y administrar conjuntos de escalado de máquinas virtuales de Azure.