在虚拟机规模集中对扩展预配进行排序Sequence extension provisioning in virtual machine scale sets

Azure 虚拟机扩展提供部署后配置和管理、监视、安全性等功能。Azure virtual machine extensions provide capabilities such as post-deployment configuration and management, monitoring, security, and more. 生产部署通常结合使用为 VM 实例配置的多个扩展来实现所需效果。Production deployments typically use a combination of multiple extensions configured for the VM instances to achieve desired results.

在虚拟机上使用多个扩展时,请务必确保需要相同 OS 资源的扩展并未尝试同时获取这些资源。When using multiple extensions on a virtual machine, it's important to ensure that extensions requiring the same OS resources aren't trying to acquire these resources at the same time. 一些扩展还依赖其他扩展来提供所需配置,如环境设置和机密。Some extensions also depend on other extensions to provide required configurations such as environment settings and secrets. 如果排序不正确,依赖扩展部署可能会失败。Without the correct ordering and sequencing in place, dependent extension deployments can fail.

本文详细介绍了如何在虚拟机规模集中对要为 VM 实例配置的扩展进行排序。This article details how you can sequence extensions to be configured for the VM instances in virtual machine scale sets.

先决条件Prerequisites

本文假定你熟悉以下内容:This article assumes that you're familiar with:

何时使用扩展排序When to use extension sequencing

不强制对规模集执行扩展排序;除非另有指定,否则可以在规模集实例上按任意顺序预配扩展。Sequencing extensions in not mandatory for scale sets, and unless specified, extensions can be provisioned on a scale set instance in any order.

例如,如果规模集模型中指定了两个扩展(扩展 A 和扩展 B),则可能会出现以下两种预配顺序之一:For example, if your scale set model has two extensions - ExtensionA and ExtensionB - specified in the model, then either of the following provisioning sequences may occur:

  • 扩展 A -> 扩展 BExtensionA -> ExtensionB
  • 扩展 B -> 扩展 AExtensionB -> ExtensionA

如果应用程序要求扩展 A 始终先于扩展 B 预配,应使用本文中所述的扩展排序。If your application requires Extension A to always be provisioned before Extension B, then you should use extension sequencing as described in this article. 使用扩展排序后,现在只会出现以下一种顺序:With extension sequencing, only one sequence will now occur:

  • 扩展 A -> 扩展 BExtensionA - > ExtensionB

任何未指定定义的预配顺序的扩展都可以随时预配(包括定义的顺序之前、之后或期间)。Any extensions not specified in a defined provisioning sequence can be provisioned at any time, including before, after, or during a defined sequence. 扩展排序仅指定一个特定扩展在另一个特定扩展之后预配。Extension sequencing only specifies that a specific extension will be provisioned after another specific extension. 它不影响模型中定义的其他任何扩展的预配。It does not impact the provisioning of any other extension defined in the model.

例如,如果规模集模型中指定了三个扩展(扩展 A、扩展 B 和扩展 C),并且扩展 C 设置为在扩展 A 之后预配,则可能会出现以下三种预配顺序之一:For example, if your scale set model has three extensions - Extension A, Extension B and Extension C - specified in the model, and Extension C is set to be provisioned after Extension A, then either of the following provisioning sequences may occur:

  • 扩展 A -> 扩展 C -> 扩展 BExtensionA -> ExtensionC -> ExtensionB
  • 扩展 B -> 扩展 A -> 扩展 CExtensionB -> ExtensionA -> ExtensionC
  • 扩展 A -> 扩展 B -> 扩展 CExtensionA -> ExtensionB -> ExtensionC

如果需要确保在执行定义的扩展顺序时不预配其他任何扩展,建议对规模集模型中的所有扩展进行排序。If you need to ensure that no other extension is provisioned while the defined extension sequence is executing, we recommend sequencing all extensions in your scale set model. 在上面的示例中,可以将扩展 B 设置为在扩展 C 之后预配,这样就只能出现以下一种顺序:In the above example, Extension B can be set to be provisioned after Extension C such that only one sequence can occur:

  • 扩展 A -> 扩展 C -> 扩展 BExtensionA -> ExtensionC -> ExtensionB

如何使用扩展排序How to use extension sequencing

若要对扩展预配进行排序,必须将规模集模型中的扩展定义更新为,包括接受扩展名数组的属性“provisionAfterExtensions”。To sequence extension provisioning, you must update the extension definition in the scale set model to include the property "provisionAfterExtensions", which accepts an array of extension names. 必须在规模集模型中完全定义属性数组值中提到的扩展。The extensions mentioned in the property array value must be fully defined in the scale set model.

模板部署Template Deployment

下面的示例定义了一个模板,其中规模集有三个扩展(扩展 A、扩展 B 和扩展 C),这样扩展就能按以下顺序预配:The following example defines a template where the scale set has three extensions - ExtensionA, ExtensionB, and ExtensionC - such that extensions are provisioned in the order:

  • 扩展 A -> 扩展 B -> 扩展 CExtensionA -> ExtensionB -> ExtensionC
"virtualMachineProfile": {
  "extensionProfile": {
    "extensions": [
      {
        "name": "ExtensionA",
        "properties": {
          "publisher": "ExtensionA.Publisher",
          "settings": {},
          "typeHandlerVersion": "1.0",
          "autoUpgradeMinorVersion": true,
          "type": "ExtensionA"
        }
      },
      {
        "name": "ExtensionB",
        "properties": {
          "provisionAfterExtensions": [
            "ExtensionA"
          ],
          "publisher": "ExtensionB.Publisher",
          "settings": {},
          "typeHandlerVersion": "2.0",
          "autoUpgradeMinorVersion": true,
          "type": "ExtensionB"
        }
      }, 
      {
        "name": "ExtensionC",
        "properties": {
          "provisionAfterExtensions": [
            "ExtensionB"
          ],
          "publisher": "ExtensionC.Publisher",
          "settings": {},
          "typeHandlerVersion": "3.0",
          "autoUpgradeMinorVersion": true,
          "type": "ExtensionC"                   
        }
      }
    ]
  }
}

由于属性“provisionAfterExtensions”接受扩展名数组,因此可以将上面的示例修改为,扩展 C 在扩展 A 和扩展 B 之后预配,但无需对扩展 A 和扩展 B 进行排序。Since the property "provisionAfterExtensions" accepts an array of extension names, the above example can be modified such that ExtensionC is provisioned after ExtensionA and ExtensionB, but no ordering is required between ExtensionA and ExtensionB. 以下模板可用于实现此方案:The following template can be used to achieve this scenario:

"virtualMachineProfile": {
  "extensionProfile": {
    "extensions": [
      {
        "name": "ExtensionA",
        "properties": {
          "publisher": "ExtensionA.Publisher",
          "settings": {},
          "typeHandlerVersion": "1.0",
          "autoUpgradeMinorVersion": true,
          "type": "ExtensionA"
        }
      },
      {
        "name": "ExtensionB",
        "properties": {
          "publisher": "ExtensionB.Publisher",
          "settings": {},
          "typeHandlerVersion": "2.0",
          "autoUpgradeMinorVersion": true,
          "type": "ExtensionB"
        }
      }, 
      {
        "name": "ExtensionC",
        "properties": {
          "provisionAfterExtensions": [
            "ExtensionA","ExtensionB"
          ],
          "publisher": "ExtensionC.Publisher",
          "settings": {},
          "typeHandlerVersion": "3.0",
          "autoUpgradeMinorVersion": true,
          "type": "ExtensionC"                   
        }
      }
    ]
  }
}

REST APIREST API

下面的示例将名为“扩展 C”的新扩展添加到规模集模型中。The following example adds a new extension named ExtensionC to a scale set model. 扩展 C 依赖扩展 A 和扩展 B,这些扩展已在规模集模型中定义。ExtensionC has dependencies on ExtensionA and ExtensionB, which have already been defined in the scale set model.

PUT on `/subscriptions/subscription_id/resourceGroups/myResourceGroup/providers/Microsoft.Compute/virtualMachineScaleSets/myScaleSet/extensions/ExtensionC?api-version=2018-10-01`
{ 
  "name": "ExtensionC",
  "properties": {
    "provisionAfterExtensions": [
      "ExtensionA","ExtensionB"
    ],
    "publisher": "ExtensionC.Publisher",
    "settings": {},
    "typeHandlerVersion": "3.0",
    "autoUpgradeMinorVersion": true,
    "type": "ExtensionC" 
  }                  
}

如果规模集模型中之前已定义扩展 C,并且现在要添加它的依赖项,可以执行 PATCH 来编辑已部署的扩展属性。If ExtensionC was defined earlier in the scale set model and you now want to add its dependencies, you can execute a PATCH to edit the already deployed extension’s properties.

PATCH on `/subscriptions/subscription_id/resourceGroups/myResourceGroup/providers/Microsoft.Compute/virtualMachineScaleSets/myScaleSet/extensions/ExtensionC?api-version=2018-10-01`
{ 
  "properties": {
    "provisionAfterExtensions": [
      "ExtensionA","ExtensionB"
    ]
  }                  
}

对现有规模集实例的更改在下一次升级时应用。Changes to existing scale set instances are applied on the next upgrade.

Azure PowerShellAzure PowerShell

使用 Add-AzVmssExtension cmdlet 将应用程序运行状况扩展添加到规模集模型定义中。Use the Add-AzVmssExtension cmdlet to add the Application Health extension to the scale set model definition. 必须使用 Az PowerShell 1.2.0 或更高版本,才能执行扩展排序。Extension sequencing requires the use of Az PowerShell 1.2.0 or above.

下面的示例将应用程序运行状况扩展添加到 extensionProfile(位于基于 Windows 的规模集的规模集模型中)。The following example adds the Application Health extension to the extensionProfile in a scale set model of a Windows-based scale set. 应用程序运行状况扩展在规模集中已定义的自定义脚本扩展后预配。The Application Health extension will be provisioned after provisioning the Custom Script Extension, already defined in the scale set.

# Define the scale set variables
$vmScaleSetName = "myVMScaleSet"
$vmScaleSetResourceGroup = "myVMScaleSetResourceGroup"

# Define the Application Health extension properties
$publicConfig = @{"protocol" = "http"; "port" = 80; "requestPath" = "/healthEndpoint"};
$extensionName = "myHealthExtension"
$extensionType = "ApplicationHealthWindows"
$publisher = "Microsoft.ManagedServices"

# Get the scale set object
$vmScaleSet = Get-AzVmss `
  -ResourceGroupName $vmScaleSetResourceGroup `
  -VMScaleSetName $vmScaleSetName

# Add the Application Health extension to the scale set model
Add-AzVmssExtension -VirtualMachineScaleSet $vmScaleSet `
  -Name $extensionName `
  -Publisher $publisher `
  -Setting $publicConfig `
  -Type $extensionType `
  -TypeHandlerVersion "1.0" `
  -ProvisionAfterExtension "CustomScriptExtension" `
  -AutoUpgradeMinorVersion $True

# Update the scale set
Update-AzVmss -ResourceGroupName $vmScaleSetResourceGroup `
  -Name $vmScaleSetName `
  -VirtualMachineScaleSet $vmScaleSet

Azure CLI 2.0Azure CLI 2.0

使用 az vmss 扩展集将应用程序运行状况扩展添加到规模集模型定义中。Use az vmss extension set to add the Application Health extension to the scale set model definition. 必须使用 Azure CLI 2.0.55 或更高版本,才能执行扩展排序。Extension sequencing requires the use of Azure CLI 2.0.55 or above.

下面的示例将应用程序运行状况扩展添加到基于 Windows 的规模集的规模集模型中。The following example adds the Application Health extension to the scale set model of a Windows-based scale set. 应用程序运行状况扩展在规模集中已定义的自定义脚本扩展后预配。The Application Health extension will be provisioned after provisioning the Custom Script Extension, already defined in the scale set.

az vmss extension set \
  --name ApplicationHealthWindows \
  --publisher Microsoft.ManagedServices \
  --version 1.0 \
  --resource-group <myVMScaleSetResourceGroup> \
  --vmss-name <myVMScaleSet> \
  --provision-after-extensions CustomScriptExtension \
  --settings ./extension.json

故障排除Troubleshoot

无法添加有依赖项的扩展?Not able to add extension with dependencies?

  1. 请确保 provisionAfterExtensions 中指定的扩展已在规模集模型中定义。Ensure that the extensions specified in provisionAfterExtensions are defined in the scale set model.
  2. 请确保未引入循环依赖。Ensure there are no circular dependencies being introduced. 例如,禁止使用以下顺序:扩展 A -> 扩展 B -> 扩展 C -> 扩展 AFor example, the following sequence isn't allowed: ExtensionA -> ExtensionB -> ExtensionC -> ExtensionA
  3. 请确保所依赖的任何扩展在扩展“属性”下有“设置”属性。Ensure that any extensions that you take dependencies on, have a "settings" property under extension "properties". 例如,如果需要在扩展 A 之后预配扩展 B,扩展 A 必须在扩展 A“属性”下有“设置”字段。For example, if ExtentionB needs to be provisioned after ExtensionA, then ExtensionA must have the "settings" field under ExtensionA "properties". 如果扩展不强制要求任何必需设置,可以指定空的“设置”属性。You can specify an empty "settings" property if the extension does not mandate any required settings.

无法删除扩展?Not able to remove extensions?

请确保要删除的扩展未在其他任何扩展的 provisionAfterExtensions 下列出。Ensure that the extensions being removed are not listed under provisionAfterExtensions for any other extensions.

后续步骤Next steps

了解如何在虚拟机规模集上部署应用程序Learn how to deploy your application on virtual machine scale sets.