快速入门:使用 ARM 模板创建 Windows 虚拟机规模集
适用于:✔️ Windows VM ✔️ 统一规模集
注意
下文介绍了统一虚拟机规模集。 建议对新的工作负载使用灵活虚拟机规模集。 如需详细了解此业务流程模式,请参阅灵活虚拟机规模集概述。
利用虚拟机规模集,可以部署和管理一组自动缩放的虚拟机。 可以手动缩放规模集中的 VM 数,也可以定义规则,以便根据资源使用情况(如 CPU 使用率、内存需求或网络流量)进行自动缩放。 然后,Azure 负载均衡器会将流量分配到规模集中的 VM 实例。 本快速入门将使用 Azure 资源管理器模板(ARM 模板)创建虚拟机规模集并部署示例应用程序。
Azure 资源管理器模板是定义项目基础结构和配置的 JavaScript 对象表示法 (JSON) 文件。 模板使用声明性语法。 你可以在不编写用于创建部署的编程命令序列的情况下,描述预期部署。
ARM 模板允许部署相关资源的组。 在单个模板中,可以创建虚拟机规模集、安装应用程序,以及配置自动缩放规则。 在借助变量和参数的情况下,可以重复使用此模板来更新现有的规模集,或者创建更多的规模集。 可通过 Azure 门户、Azure CLI、Azure PowerShell 或持续集成/持续交付 (CI/CD) 管道部署模板。
如果你的环境满足先决条件,并且你熟悉如何使用 ARM 模板,请选择“部署到 Azure”按钮。 Azure 门户中会打开模板。
先决条件
如果没有 Azure 订阅,可在开始前创建一个试用帐户。
查看模板
本快速入门中使用的模板来自 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')]"
}
}
}
这些模板中定义了这些资源:
- Microsoft.Network/virtualNetworks
- Microsoft.Network/publicIPAddresses
- Microsoft.Network/loadBalancers
- Microsoft.Compute/virtualMachineScaleSets
- Microsoft.Insights/autoscaleSettings
定义规模集
若要使用模板创建规模集,请定义相应的资源。 虚拟机规模集资源类型的核心部件包括:
属性 | 属性说明 | 示例模板值 |
---|---|---|
type | 要创建的 Azure 资源类型 | Microsoft.Compute/virtualMachineScaleSets |
name | 规模集名称 | myScaleSet |
location | 要创建规模集的位置 | 中国北部 2 |
sku.name | 每个规模集实例的 VM 大小 | Standard_A1 |
sku.capacity | 一开始需要创建的 VM 实例数 | 2 |
upgradePolicy.mode | 更改发生时的 VM 实例升级模式 | 自动 |
imageReference | 用于 VM 实例的平台或自定义映像 | Microsoft Windows Server 2016 Datacenter |
osProfile.computerNamePrefix | 每个 VM 实例的名称前缀 | myvmss |
osProfile.adminUsername | 每个 VM 实例的用户名 | azureuser |
osProfile.adminPassword | 每个 VM 实例的密码 | P@ssw0rd! |
若要自定义规模集模板,可以更改 VM 大小或初始容量。 另一选项是使用其他平台或自定义映像。
添加示例应用程序
若要测试规模集,请安装一个基本的 Web 应用程序。 部署规模集时,可以通过 VM 扩展来完成部署后配置和自动化任务,例如安装某个应用。 可以从 Azure 存储或 GitHub 下载脚本,或者在扩展运行时将脚本提供给 Azure 门户。 若要对规模集应用某个扩展,请将 extensionProfile 节添加到前面的资源示例中。 扩展配置文件通常定义以下属性:
- 扩展类型
- 扩展发布者
- 扩展版本
- 配置或安装脚本的位置
- 可在 VM 实例上执行的命令
此模板使用 PowerShell DSC 扩展来安装在 IIS 中运行的 ASP.NET MVC 应用。
安装脚本从 url 中定义的 GitHub 下载。 扩展然后运行 IISInstall.ps1 脚本中的 InstallIIS(在 function 和 Script 中定义)。 ASP.NET 应用本身作为 Web 部署包提供,该包也从 WebDeployPackagePath 中定义的 GitHub 下载:
部署模板
可以通过选择“部署到 Azure”按钮来部署模板。 此按钮可打开 Azure 门户、加载完整的模板,以及提示输入一些参数,例如规模集名称、实例计数和管理员凭据。
还可以使用 Azure PowerShell 部署资源管理器模板:
# Create a resource group
New-AzResourceGroup -Name myResourceGroup -Location chinanorth2
# 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
响应提示,为 VM 实例提供规模集名称和管理员凭据。 创建规模集并通过其来应用可配置应用的扩展可能需要 10-15 分钟。
验证部署
若要查看正在运行的规模集,请在 Web 浏览器中访问示例 Web 应用程序。 使用 Get-AzPublicIpAddress 获取负载均衡器的公共 IP 地址,如下所示:
Get-AzPublicIpAddress -ResourceGroupName myResourceGroup | Select IpAddress
以 http://publicIpAddress/MyApp 格式将负载均衡器的公共 IP 地址输入到 Web 浏览器中。 负载均衡器将流量分发到某个 VM 实例,如以下示例所示:
清理资源
如果不再需要资源组、规模集,可以使用 Remove-AzResourceGroup 命令将其删除。 -Force
参数将确认是否希望删除资源,而不会有额外提示。 -AsJob
参数会使光标返回提示符处,无需等待操作完成。
Remove-AzResourceGroup -Name "myResourceGroup" -Force -AsJob
后续步骤
在本快速入门中,你已使用 ARM 模板创建了 Windows 规模集,并已使用 PowerShell DSC 扩展在 VM 实例上安装了基本的 ASP.NET 应用。 若要了解详细信息,请继续学习有关如何创建和管理 Azure 虚拟机规模集的教程。