你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn

使用部署脚本检查资源属性

本文介绍如何使用Bicep和部署脚本暂停部署,直到资源属性返回特定值。 可以使用此技术来确保部署过程的成功,即使部署的资源向 Azure 资源管理器报告其已准备就绪,但底层资源尚未就绪。 在这种情况下,已部署的资源尚未准备好与部署的其余部分进行交互,这意味着需要暂停。

本文使用Azure 虚拟 WAN方案演示技术。 以下文件包含资源检查和暂停功能的实现:

你可以根据部署调整文件。 为了帮助你,azResourceStateCheck.bicep 模块已参数化。 该 dependsOn 属性用于 orchestration.bicep,以确保 vwanvhcs.bicep 模块部署依赖于 azResourceStateCheck.bicep 模块部署。

Architecture

图示,展示Bicep和部署脚本架构。

下载此体系结构的 Visio 文件

查看并下载 GitHub 中此体系结构的代码示例

  1. 提交 orchestration.bicep 文件以部署到订阅范围内的资源管理器。

    Note

    可以从 infra/samples/deployment-scripts-property-check directory 获取此Bicep文件和用于此示例的其他文件。 存储库中文件的部分组织显示在体系结构关系图的右侧。

  2. orchestration.bicep 文件在订阅范围内创建资源组。

  3. orchestration.bicep 文件部署虚拟广域网和分支虚拟网络。

    • orchestration.bicep 部署 vwan.bicep 模块,该模块在资源组范围内部署虚拟 WAN。

    • orchestration.bicep 部署在资源组范围内部署虚拟网络的 vnet.bicep 模块。

    虚拟广域网和其连接的虚拟网络是并行部署的,因为在Bicep中,它们被视作相互独立的。 依赖项确定 Bicep 中的部署顺序。 资源部署在依赖于该资源的任何资源之前。 有关 Bicep 中的资源依赖项的详细信息,包括显式和隐式依赖项,请参阅 Bicep 中的资源依赖项

  4. orchestration.bicep 文件部署 vwanhub.bicep 模块,该模块在资源组范围内部署虚拟 WAN中心。 中心隐式依赖于虚拟 WAN,这意味着中心部署仅在虚拟 WAN部署完成后进行。

  5. orchestration.bicep 文件部署 azResourceStateCheck.bicep 模块,该模块创建用户分配的托管标识,并将Azure基于角色的访问控制(RBAC)读取者角色分配给资源组。

  6. azResourceStateCheck.bicep 模块部署 部署脚本资源

  7. 部署脚本资源使用用户分配的托管标识进行资源管理器身份验证。 然后,资源运行 PowerShell 部署脚本,Invoke-AzResourceStateCheck.ps1。 有关部署脚本的详细信息,请参阅 Bicep 中使用部署脚本

    该脚本轮询 虚拟 WAN 中心 routingState 属性,以确定该值是否为 Provisioned

    1. 如果未指定属性值 Provisioned,脚本会在 orchestration.bicep 文件中参数集指定的持续时间内暂停,并传递给 azResourceStateCheck.bicep 模块。 然后,该脚本会再次检查 routingState 属性值。

      该脚本重复暂停和检查周期。 orchestration.bicep 文件中的参数确定最大迭代数。 如果属性值在达到最大迭代次数后不是Provisioned,脚本将生成异常并退出,这会导致 Bicep 部署的其余部分停止和失败。

    2. 如果属性值为 Provisioned,则部署脚本会退出并显示成功代码 (0)

  8. 如果部署脚本成功,orchestration.bicep 文件将部署 vwanvhcs.bicep 模块,该模块创建辐射虚拟网络与虚拟 WAN 中心之间的连接。

    orchestration.bicep 中 vwanvhcs.bicep 模块的定义具有一个 dependsOn 子句,该子句导致 vwanvhcs.bicep 显式依赖于 azResourceStateCheck.bicep 模块的成功完成。 因此,只有当routingState属性为Provisioned时,才会创建连接。

    vwanvhcs.bicep 模块按顺序部署虚拟 WAN中心连接,而不是并行部署,因为单个虚拟 WAN中心不支持并行部署。 若要将批大小设置为 1,模块使用 Bicep batchSize 修饰器,@batchSize(1)。 此装饰器确保连接被逐一建立。

方案详细信息

此体系结构的关键部分是 azResourceStateCheck.bicep 模块,该模块部署部署脚本资源,以及关联的部署脚本 Invoke-AzResourceStateCheck.ps1(PowerShell 文件)。 该模块使用部署脚本检查资源属性的值。 在此示例中,资源是虚拟 WAN 中心。

可以使用 dependsOn使一个模块显式依赖于另一个模块,因为此环境是从使用Bicep模块的单个文件中部署的。 在此示例中, dependsOn 使 vwanvhcs.bicep 模块依赖于 azResourceStateCheck.bicep 模块。

编排.bicep 中的以下代码摘录展示了 dependsOn 的使用:

@description('The API version of the Azure Resource you need to use to check the state of a property.')
param parAzResourceApiVersion string = '2022-01-01'

@description('The property of the resource that you need to check. This is a property inside the `properties` bag of the resource that's captured from a GET call to the Resource ID.')
param parAzResourcePropertyToCheck string = 'routingState'

@description('The value of the property of the resource that you need to check.')
param parAzResourceDesiredState string = 'Provisioned'

@description('The duration that the deployment script waits between check or polling requests to check the property and its state, if it is not in its desired state. The duration defaults to `30` seconds.')
param parWaitInSecondsBetweenIterations int = 30

module modVWANHub 'modules/vwanHub.bicep' = {
  scope: rsg
  name: 'deployVWANHub'
  params: {
    region: region
    regionNamePrefix: regionNamePrefix
    defaultTags: defaultTags
    vwanHubCIDR: vwanHubCIDR
    vwanName: modVWAN.outputs.vwanName
  }
}

module modVWANHubRouterCheckerDeploymentScript 'modules/azResourceStateCheck.bicep' = {
  scope: rsg
  name: 'deployVWANHubRouterChecker'
  params: {
    parLocation: region
    parAzResourceId: modVWANHub.outputs.outVwanVHubId
    parAzResourceApiVersion: parAzResourceApiVersion
    parAzResourcePropertyToCheck: parAzResourcePropertyToCheck
    parAzResourceDesiredState: parAzResourceDesiredState
    parMaxIterations: parMaxIterations
    parWaitInSecondsBetweenIterations: parWaitInSecondsBetweenIterations
  }
}

module modVWanVhubVnetConnections 'modules/vwanVhcs.bicep' = {
  dependsOn: [
    modVWANHubRouterCheckerDeploymentScript
  ]
  scope: rsg
  name: 'deployConnectVnetsToVWANVHub'
  params: {
    vnets: vnets
    regionNamePrefix: regionNamePrefix
  }
}

资源检查是必需的,因为部署的“虚拟 WAN”中心在 routingState 属性的值达到 Provisioned 之前都无法使用。 虚拟 WAN 中心将部署成功状态报告给资源管理器,以便部署引擎能够继续执行部署。 将虚拟 WAN中心路由器预配到创建的中心后,新的虚拟 WAN中心将变为可操作。 此过程大约需要 15 分钟。 可以在新虚拟 WAN中心的以下屏幕截图中看到此行为。 屏幕截图显示中心状态为Succeeded,而路由状态为Provisioning

新部署的虚拟广域网中心的截图。中心状态为“成功”,路由状态为“正在配置”。

如果在routingState值为Provisioned之前尝试部署 vwanvhcs.bicep 模块,连接的创建将失败,从而导致整体部署失败。 在预配路由器之前,重新部署尝试也会失败。

以下屏幕截图显示了虚拟 WAN中心routingState检查期间部署脚本日志的示例。 日志显示对属性的多次检查,返回不同于 Provisioned 的值。

截图显示部署脚本轮询 虚拟 WAN 中心的 routingState 属性。

以下屏幕截图显示值更改为 Provisioned

截图,显示当 虚拟 WAN 中心的 routingState 属性更改为 Provisioned 时部署脚本的完成。

如果值在达到最大迭代次数后仍未更改为Provisioned,脚本将生成一个异常,该异常向资源管理器表明脚本资源失败。 资源管理器部署引擎失败并停止部署,因为异常表明Azure资源存在需要故障排除的问题。 有关详细信息,请参阅以下 Invoke-AzResourceStateCheck.ps1 脚本。

[CmdletBinding()]
param (
  [string]
  $azResourceResourceId,

  [string]
  $apiVersion = "2022-05-01",

  [string]
  $azResourcePropertyToCheck = "provisioningState",

  [string]
  $azResourceDesiredState = "Provisioned",

  [int]
  $waitInSecondsBetweenIterations = 30,

  [int]
  $maxIterations = 30
)

$totalTimeoutCalculation = $waitInSecondsBetweenIterations * $maxIterations

$azResourcePropertyExistenceCheck = Invoke-AzRestMethod -Method GET -Path "$($azResourceResourceId)?api-version=$($apiVersion)"

if ($azResourcePropertyExistenceCheck.StatusCode -ne "200") {
  $DeploymentScriptOutputs["azResourcePropertyState"] = "Not Found"
  throw "Unable to get Azure Resource - $($azResourceResourceId). Likely it doesn't exist. Status code: $($azResourcePropertyExistenceCheck.StatusCode) Error: $($azResourcePropertyExistenceCheck.Content)"
}

$azResourcePropertyStateResult = "Unknown"
$iterationCount = 0

do {
  $azResourcePropertyStateGet = Invoke-AzRestMethod -Method GET -Path "$($azResourceResourceId)?api-version=$($apiVersion)"
  $azResourcePropertyStateJsonConverted = $azResourcePropertyStateGet.Content | ConvertFrom-Json -Depth 10
  $azResourcePropertyStateResult = $azResourcePropertyStateJsonConverted.properties.$($azResourcePropertyToCheck)

  if ($azResourcePropertyStateResult -ne $azResourceDesiredState) {
    Write-Host "Azure Resource Property ($($azResourcePropertyToCheck)) is not in $($azResourceDesiredState) state. Waiting $($waitInSecondsBetweenIterations) seconds before checking again. Iteration count: $($iterationCount)"
    Start-Sleep -Seconds $waitInSecondsBetweenIterations
    $iterationCount++
  }
} while (
  $azResourcePropertyStateResult -ne $azResourceDesiredState -and $iterationCount -ne $maxIterations
)

if ($azResourcePropertyStateResult -eq $azResourceDesiredState) {
  Write-Host "Azure Resource Property ($($azResourcePropertyToCheck)) is now in $($azResourceDesiredState) state."
  $DeploymentScriptOutputs["azResourcePropertyState"] = "$($azResourceDesiredState)"
}

if ($iterationCount -eq $maxIterations -and $azResourcePropertyStateResult -ne $azResourceDesiredState) {
  $DeploymentScriptOutputs["azResourcePropertyState"] = "Azure Resource Property ($($azResourcePropertyToCheck)) is still not in desired state of $($azResourceDesiredState). Timeout reached of $($totalTimeoutCalculation) seconds."
  throw "Azure Resource Property ($($azResourcePropertyToCheck)) is still not in $($azResourceDesiredState) state after $($totalTimeoutCalculation) seconds."
}

贡献者

Microsoft维护本文。 以下贡献者撰写了本文。

主要作者:

其他参与者:

若要查看非公开的领英个人资料,请登录领英。

后续步骤