快速入门:使用 ARM 模板创建 Linux 虚拟机规模集Quickstart: Create a Linux virtual machine scale set with an ARM template

利用虚拟机规模集,可以部署和管理一组自动缩放的虚拟机。A virtual machine scale set allows you to deploy and manage a set of auto-scaling virtual machines. 可以手动缩放规模集中的 VM 数,也可以定义规则,以便根据资源使用情况(如 CPU 使用率、内存需求或网络流量)进行自动缩放。You can scale the number of VMs in the scale set manually, or define rules to autoscale based on resource usage like CPU, memory demand, or network traffic. 然后,Azure 负载均衡器会将流量分配到规模集中的 VM 实例。An Azure load balancer then distributes traffic to the VM instances in the scale set. 本快速入门将使用 Azure 资源管理器模板(ARM 模板)创建虚拟机规模集并部署示例应用程序。In this quickstart, you create a virtual machine scale set and deploy a sample application with an Azure Resource Manager template (ARM template).

ARM 模板是定义项目基础结构和配置的 JavaScript 对象表示法 (JSON) 文件。An ARM template is a JavaScript Object Notation (JSON) file that defines the infrastructure and configuration for your project. 该模板使用声明性语法,使你可以声明要部署的内容,而不需要编写一系列编程命令来进行创建。The template uses declarative syntax, which lets you state what you intend to deploy without having to write the sequence of programming commands to create it.

ARM 模板允许部署相关资源的组。ARM templates let you deploy groups of related resources. 在单个模板中,可以创建虚拟机规模集、安装应用程序,以及配置自动缩放规则。In a single template, you can create the virtual machine scale set, install applications, and configure autoscale rules. 在借助变量和参数的情况下,可以重复使用此模板来更新现有的规模集,或者创建更多的规模集。With the use of variables and parameters, this template can be reused to update existing, or create additional, scale sets. 可通过 Azure 门户、Azure CLI、Azure PowerShell 或持续集成/持续交付 (CI/CD) 管道部署模板。You can deploy templates through the Azure portal, Azure CLI, or Azure PowerShell, or from continuous integration / continuous delivery (CI/CD) pipelines.

如果你的环境满足先决条件,并且你熟悉如何使用 ARM 模板,请选择“部署到 Azure”按钮。If your environment meets the prerequisites and you're familiar with using ARM templates, select the Deploy to Azure button. Azure 门户中会打开模板。The template will open in the Azure portal.

部署到 AzureDeploy to Azure

先决条件Prerequisites

如果没有 Azure 订阅,可在开始前创建一个试用帐户If you don't have an Azure subscription, create a Trial before you begin.

查看模板Review the template

本快速入门中使用的模板来自 Azure 快速启动模板The template used in this quickstart is from Azure Quickstart Templates.

{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "location": {
      "type": "string",
      "metadata": {
        "description": "Location for all resources"
      },
      "defaultValue": "[resourceGroup().location]"
    },
    "vmSku": {
      "type": "string",
      "defaultValue": "Standard_D1_v2",
      "metadata": {
        "description": "Size of VMs in the VM Scale Set."
      }
    },
    "vmssName": {
      "type": "string",
      "metadata": {
        "description": "String used as a base for naming resources (9 characters or less). A hash is prepended to this string for some resources, and resource-specific information is appended."
      }
    },
    "instanceCount": {
      "type": "int",
      "metadata": {
        "description": "Number of VM instances (100 or less)."
      },
      "defaultValue": 1,
      "minValue": 1,
      "maxValue": 100
    },
    "adminUsername": {
      "type": "string",
      "metadata": {
        "description": "Admin username on all VMs."
      }
    },
    "authenticationType": {
      "type": "string",
      "defaultValue": "sshPublicKey",
      "allowedValues": [
        "sshPublicKey",
        "password"
      ],
      "metadata": {
        "description": "Type of authentication to use on the Virtual Machine. SSH key is recommended."
      }
    },
    "adminPasswordOrKey": {
      "type": "securestring",
      "metadata": {
        "description": "SSH Key or password for the Virtual Machine. SSH key is recommended."
      }
    },
    "_artifactsLocation": {
         "type": "string",
         "defaultValue": "https://raw.githubusercontent.com/Azure/azure-quickstart-templates/master/201-vmss-bottle-autoscale/",
         "metadata": {
            "description": "The base URI where artifacts required by this template are located"
         }
      },
      "_artifactsLocationSasToken": {
         "type": "securestring",
         "defaultValue": "",
         "metadata": {
            "description": "The sasToken required to access _artifactsLocation.  When the template is deployed using the accompanying scripts, a sasToken will be automatically generated"
         }
      }
  },
  "variables": {
    "addressPrefix": "10.0.0.0/16",
    "subnetPrefix": "10.0.0.0/24",
    "virtualNetworkName": "[concat(parameters('vmssName'), 'vnet')]",
    "publicIPAddressName": "[concat(parameters('vmssName'), 'pip')]",
    "subnetName": "[concat(parameters('vmssName'), 'subnet')]",
    "loadBalancerName": "[concat(parameters('vmssName'), 'lb')]",
    "publicIPAddressID": "[resourceId('Microsoft.Network/publicIPAddresses',variables('publicIPAddressName'))]",
    "lbID": "[resourceId('Microsoft.Network/loadBalancers',variables('loadBalancerName'))]",
    "natPoolName": "[concat(parameters('vmssName'), 'natpool')]",
    "bePoolName": "[concat(parameters('vmssName'), 'bepool')]",
    "natStartPort": 50000,
    "natEndPort": 50120,
    "natBackendPort": 22,
    "nicName": "[concat(parameters('vmssName'), 'nic')]",
    "ipConfigName": "[concat(parameters('vmssName'), 'ipconfig')]",
    "frontEndIPConfigID": "[concat(variables('lbID'),'/frontendIPConfigurations/loadBalancerFrontEnd')]",
    "osType": {
      "publisher": "Canonical",
      "offer": "UbuntuServer",
      "sku": "16.04-LTS",
      "version": "latest"
    },
    "imageReference": "[variables('osType')]",
    "linuxConfiguration": {
      "disablePasswordAuthentication": true,
      "ssh": {
        "publicKeys": [
          {
            "path": "[concat('/home/', parameters('adminUsername'), '/.ssh/authorized_keys')]",
            "keyData": "[parameters('adminPasswordOrKey')]"
          }
        ]
      }
    }
  },
  "resources": [
    {
      "type": "Microsoft.Network/virtualNetworks",
      "name": "[variables('virtualNetworkName')]",
      "location": "[parameters('location')]",
      "apiVersion": "2020-05-01",
      "properties": {
        "addressSpace": {
          "addressPrefixes": [
            "[variables('addressPrefix')]"
          ]
        },
        "subnets": [
          {
            "name": "[variables('subnetName')]",
            "properties": {
              "addressPrefix": "[variables('subnetPrefix')]"
            }
          }
        ]
      }
    },
    {
      "type": "Microsoft.Network/publicIPAddresses",
      "name": "[variables('publicIPAddressName')]",
      "location": "[parameters('location')]",
      "apiVersion": "2020-05-01",
      "properties": {
        "publicIPAllocationMethod": "Dynamic",
        "dnsSettings": {
          "domainNameLabel": "[parameters('vmssName')]"
        }
      }
    },
    {
      "type": "Microsoft.Network/loadBalancers",
      "name": "[variables('loadBalancerName')]",
      "location": "[parameters('location')]",
      "apiVersion": "2020-05-01",
      "dependsOn": [
        "[resourceId('Microsoft.Network/publicIPAddresses/', variables('publicIPAddressName'))]"
      ],
      "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')]"
            }
          },
          {
            "name": "natpool2",
            "properties": {
              "frontendIPConfiguration": {
                "id": "[variables('frontEndIPConfigID')]"
              },
              "protocol": "Tcp",
              "frontendPortRangeStart": 9000,
              "frontendPortRangeEnd": 9120,
              "backendPort": 9000
            }
          }
        ]
      }
    },
    {
      "type": "Microsoft.Compute/virtualMachineScaleSets",
      "name": "[parameters('vmssName')]",
      "location": "[parameters('location')]",
      "apiVersion": "2019-12-01",
      "dependsOn": [
        "[resourceId('Microsoft.Network/loadBalancers/', variables('loadBalancerName'))]",
        "[resourceId('Microsoft.Network/virtualNetworks/', variables('virtualNetworkName'))]"
      ],
      "sku": {
        "name": "[parameters('vmSku')]",
        "tier": "Standard",
        "capacity": "[parameters('instanceCount')]"
      },
      "properties": {
        "overprovision": "false",
        "upgradePolicy": {
          "mode": "Manual"
        },
        "virtualMachineProfile": {
          "storageProfile": {
            "osDisk": {
              "createOption": "FromImage",
              "caching": "ReadWrite"
            },
            "imageReference": "[variables('imageReference')]"
          },
          "osProfile": {
            "computerNamePrefix": "[parameters('vmssName')]",
            "adminUsername": "[parameters('adminUsername')]",
            "adminPassword": "[parameters('adminPasswordOrKey')]",
            "linuxConfiguration": "[if(equals(parameters('authenticationType'), 'password'), json('null'), variables('linuxConfiguration'))]"
          },
          "networkProfile": {
            "networkInterfaceConfigurations": [
              {
                "name": "[variables('nicName')]",
                "properties": {
                  "primary": true,
                  "ipConfigurations": [
                    {
                      "name": "[variables('ipConfigName')]",
                      "properties": {
                        "subnet": {
                          "id": "[concat('/subscriptions/', subscription().subscriptionId,'/resourceGroups/', resourceGroup().name, '/providers/Microsoft.Network/virtualNetworks/', variables('virtualNetworkName'), '/subnets/', variables('subnetName'))]"
                        },
                        "loadBalancerBackendAddressPools": [
                          {
                            "id": "[concat('/subscriptions/', subscription().subscriptionId,'/resourceGroups/', resourceGroup().name, '/providers/Microsoft.Network/loadBalancers/', variables('loadBalancerName'), '/backendAddressPools/', variables('bePoolName'))]"
                          }
                        ],
                        "loadBalancerInboundNatPools": [
                          {
                            "id": "[concat('/subscriptions/', subscription().subscriptionId,'/resourceGroups/', resourceGroup().name, '/providers/Microsoft.Network/loadBalancers/', variables('loadBalancerName'), '/inboundNatPools/', variables('natPoolName'))]"
                          },
                          {
                            "id": "[concat('/subscriptions/', subscription().subscriptionId,'/resourceGroups/', resourceGroup().name, '/providers/Microsoft.Network/loadBalancers/', variables('loadBalancerName'), '/inboundNatPools/natpool2')]"
                          }
                        ]
                      }
                    }
                  ]
                }
              }
            ]
          },
          "extensionProfile": {
            "extensions": [
              {
                "name": "lapextension",
                "properties": {
                  "publisher": "Microsoft.Azure.Extensions",
                  "type": "CustomScript",
                  "typeHandlerVersion": "2.0",
                  "autoUpgradeMinorVersion": true,
                  "settings": {
                    "fileUris": [
                      "[uri(parameters('_artifactsLocation'), concat('installserver.sh', parameters('_artifactsLocationSasToken')))]",
                      "[uri(parameters('_artifactsLocation'), concat('workserver.py', parameters('_artifactsLocationSasToken')))]"
                    ],
                    "commandToExecute": "bash installserver.sh"
                  }
                }
              }
            ]
          }
        }
      }
    },
    {
      "type": "Microsoft.Insights/autoscaleSettings",
      "apiVersion": "2015-04-01",
      "name": "autoscalehost",
      "location": "[parameters('location')]",
      "dependsOn": [
        "[resourceId('Microsoft.Compute/virtualMachineScaleSets/', parameters('vmSSName'))]"
      ],
      "properties": {
        "name": "autoscalehost",
        "targetResourceUri": "[concat('/subscriptions/',subscription().subscriptionId, '/resourceGroups/',  resourceGroup().name, '/providers/Microsoft.Compute/virtualMachineScaleSets/', parameters('vmSSName'))]",
        "enabled": true,
        "profiles": [
          {
            "name": "Profile1",
            "capacity": {
              "minimum": "1",
              "maximum": "10",
              "default": "1"
            },
            "rules": [
              {
                "metricTrigger": {
                  "metricName": "Percentage CPU",
                  "metricNamespace": "",
                  "metricResourceUri": "[concat('/subscriptions/',subscription().subscriptionId, '/resourceGroups/',  resourceGroup().name, '/providers/Microsoft.Compute/virtualMachineScaleSets/', parameters('vmSSName'))]",
                  "timeGrain": "PT1M",
                  "statistic": "Average",
                  "timeWindow": "PT5M",
                  "timeAggregation": "Average",
                  "operator": "GreaterThan",
                  "threshold": 60
                },
                "scaleAction": {
                  "direction": "Increase",
                  "type": "ChangeCount",
                  "value": "1",
                  "cooldown": "PT1M"
                }
              },
              {
                "metricTrigger": {
                  "metricName": "Percentage CPU",
                  "metricNamespace": "",
                  "metricResourceUri": "[concat('/subscriptions/',subscription().subscriptionId, '/resourceGroups/',  resourceGroup().name, '/providers/Microsoft.Compute/virtualMachineScaleSets/', parameters('vmSSName'))]",
                  "timeGrain": "PT1M",
                  "statistic": "Average",
                  "timeWindow": "PT5M",
                  "timeAggregation": "Average",
                  "operator": "LessThan",
                  "threshold": 30
                },
                "scaleAction": {
                  "direction": "Decrease",
                  "type": "ChangeCount",
                  "value": "1",
                  "cooldown": "PT1M"
                }
              }
            ]
          }
        ]
      }
    }
  ]
}

该模板中定义了以下资源:These resources are defined in the template:

定义规模集Define a scale set

若要使用模板创建规模集,请定义相应的资源。To create a scale with a template, you define the appropriate resources. 虚拟机规模集资源类型的核心部件包括:The core parts of the virtual machine scale set resource type are:

属性Property 属性说明Description of property 示例模板值Example template value
typetype 要创建的 Azure 资源类型Azure resource type to create Microsoft.Compute/virtualMachineScaleSetsMicrosoft.Compute/virtualMachineScaleSets
namename 规模集名称The scale set name myScaleSetmyScaleSet
locationlocation 要创建规模集的位置The location to create the scale set 中国北部 2China North 2
sku.namesku.name 每个规模集实例的 VM 大小The VM size for each scale set instance Standard_A1Standard_A1
sku.capacitysku.capacity 一开始需要创建的 VM 实例数The number of VM instances to initially create 22
upgradePolicy.modeupgradePolicy.mode 更改发生时的 VM 实例升级模式VM instance upgrade mode when changes occur 自动Automatic
imageReferenceimageReference 用于 VM 实例的平台或自定义映像The platform or custom image to use for the VM instances Canonical Ubuntu Server 16.04-LTSCanonical Ubuntu Server 16.04-LTS
osProfile.computerNamePrefixosProfile.computerNamePrefix 每个 VM 实例的名称前缀The name prefix for each VM instance myvmssmyvmss
osProfile.adminUsernameosProfile.adminUsername 每个 VM 实例的用户名The username for each VM instance azureuserazureuser
osProfile.adminPasswordosProfile.adminPassword 每个 VM 实例的密码The password for each VM instance P@ssw0rd!P@ssw0rd!

若要自定义规模集模板,可以更改 VM 大小或初始容量。To customize a scale set template, you can change the VM size or initial capacity. 另一选项是使用其他平台或自定义映像。Another option is to use a different platform or a custom image.

添加示例应用程序Add a sample application

若要测试规模集,请安装一个基本的 Web 应用程序。To test your scale set, install a basic web application. 部署规模集时,可以通过 VM 扩展来完成部署后配置和自动化任务,例如安装某个应用。When you deploy a scale set, VM extensions can provide post-deployment configuration and automation tasks, such as installing an app. 可以从 Azure 存储或 GitHub 下载脚本,或者在扩展运行时将脚本提供给 Azure 门户。Scripts can be downloaded from Azure storage or GitHub, or provided to the Azure portal at extension run-time. 若要对规模集应用某个扩展,请将 extensionProfile 节添加到前面的资源示例中。To apply an extension to your scale set, you add the extensionProfile section to the preceding resource example. 扩展配置文件通常定义以下属性:The extension profile typically defines the following properties:

  • 扩展类型Extension type
  • 扩展发布者Extension publisher
  • 扩展版本Extension version
  • 配置或安装脚本的位置Location of configuration or install scripts
  • 可在 VM 实例上执行的命令Commands to execute on the VM instances

模板使用自定义脚本扩展来安装 Bottle(Python Web 框架)和简单的 HTTP 服务器。The template uses the Custom Script Extension to install Bottle, a Python web framework, and a simple HTTP server.

两个脚本在 fileUris - (installserver.shworkserver.py)中定义。Two scripts are defined in fileUris - installserver.sh, and workserver.py. 从 GitHub 下载这些文件以后,commandToExecute 就可以运行 bash installserver.sh 来安装和配置应用。These files are downloaded from GitHub, then commandToExecute runs bash installserver.sh to install and configure the app.

部署模板Deploy the template

可以通过选择下面的“部署到 Azure”按钮来部署模板。You can deploy the template by selecting the following Deploy to Azure button. 此按钮可打开 Azure 门户、加载完整的模板,以及提示输入一些参数,例如规模集名称、实例计数和管理员凭据。This button opens the Azure portal, loads the complete template, and prompts for a few parameters such as a scale set name, instance count, and admin credentials.

部署到 AzureDeploy to Azure

还可以使用 Azure CLI 部署资源管理器模板:You can also deploy a Resource Manager template by using Azure CLI:

# Create a resource group
az group create --name myResourceGroup --location ChinaNorth2

# Deploy template into resource group
az group deployment create \
    --resource-group myResourceGroup \
    --template-uri https://raw.githubusercontent.com/Azure/azure-quickstart-templates/master/201-vmss-bottle-autoscale/azuredeploy.json

响应提示,为 VM 实例提供规模集名称、实例计数和管理员凭据。Answer the prompts to provide a scale set name, instance count, and admin credentials for the VM instances. 创建规模集和支持资源需要数分钟。It takes a few minutes for the scale set and supporting resources to be created.

验证部署Validate the deployment

若要查看正在运行的规模集,请在 Web 浏览器中访问示例 Web 应用程序。To see your scale set in action, access the sample web application in a web browser. 使用 az network public-ip list 命令获取负载均衡器的公共 IP 地址,如下所示:Obtain the public IP address of the load balancer with az network public-ip list as follows:

az network public-ip list \
    --resource-group myResourceGroup \
    --query [*].ipAddress -o tsv

以“http://publicIpAddress:9000/do_work” 格式将负载均衡器的公共 IP 地址输入到 Web 浏览器中。Enter the public IP address of the load balancer in to a web browser in the format http://publicIpAddress:9000/do_work. 负载均衡器将流量分发到某个 VM 实例,如以下示例所示:The load balancer distributes traffic to one of your VM instances, as shown in the following example:

NGINX 中的默认网页

清理资源Clean up resources

如果不再需要资源组、规模集和所有相关的资源,可以使用 az group delete 命令将其删除,如下所示。When no longer needed, you can use az group delete to remove the resource group, scale set, and all related resources as follows. --no-wait 参数会使光标返回提示符处,不会等待操作完成。The --no-wait parameter returns control to the prompt without waiting for the operation to complete. --yes 参数将确认是否希望删除资源,不会显示询问是否删除的额外提示。The --yes parameter confirms that you wish to delete the resources without an additional prompt to do so.

az group delete --name myResourceGroup --yes --no-wait

后续步骤Next steps

在本快速入门中,你已使用 ARM 模板创建了 Linux 规模集,并已使用自定义脚本扩展在 VM 实例上安装了基本的 Python Web 服务器。In this quickstart, you created a Linux scale set with an ARM template and used the Custom Script Extension to install a basic Python web server on the VM instances. 若要了解详细信息,请继续学习有关如何创建和管理 Azure 虚拟机规模集的教程。To learn more, continue to the tutorial for how to create and manage Azure virtual machine scale sets.