Usare gli script di distribuzione per controllare le proprietà delle risorse

Questo articolo descrive come usare Bicep e uno script di distribuzione per sospendere una distribuzione fino a quando una proprietà della risorsa non restituisce un valore specifico. È possibile usare questa tecnica per assicurarsi che una distribuzione abbia esito positivo se la risorsa distribuita segnala Azure Resource Manager che sia pronta, ma le risorse sottostanti non lo sono. In questo caso, la risorsa distribuita non è ancora pronta per interagire con il resto della distribuzione, il che significa che è necessaria una pausa.

Questo articolo usa uno scenario rete WAN virtuale di Azure per illustrare la tecnica. I file seguenti includono un controllo delle risorse e un'implementazione di pausa:

È possibile adattare i file per la distribuzione. Per semplificare l'operazione, il modulo azResourceStateCheck.bicep è parametrizzato. La dependsOn proprietà viene usata in orchestration.bicep per assicurarsi che la distribuzione del modulo vwanvhcs.bicep dipende dalla distribuzione del modulo azResourceStateCheck.bicep.

Architecture

Diagramma che mostra l'architettura di Bicep e dello script di distribuzione.

Scaricare un file di Visio di questa architettura.

Esaminare e scaricare gli esempi di codice in GitHub per questa architettura.

  1. Inviare il file orchestration.bicep per la distribuzione a Resource Manager nell'ambito della sottoscrizione.

    Annotazioni

    È possibile ottenere questo file Bicep e gli altri file usati per questo esempio dalla directory infra/samples/deployment-scripts-property-check. Sul lato destro del diagramma dell'architettura viene visualizzata un'organizzazione parziale dei file nel repository.

  2. Il file orchestration.bicep crea un gruppo di risorse nell'ambito della sottoscrizione.

  3. Il file orchestration.bicep distribuisce le rete WAN virtuale e le reti virtuali spoke.

    • orchestration.bicep distribuisce il modulo vwan.bicep, che distribuisce il rete WAN virtuale nell'ambito del gruppo di risorse.

    • orchestration.bicep distribuisce il modulo vnet.bicep che distribuisce le reti virtuali nell'ambito del gruppo di risorse.

    Le reti virtuali rete WAN virtuale e spoke vengono distribuite in parallelo perché Bicep le considera indipendenti l'una dall'altra. Le dipendenze determinano l'ordine di distribuzione in Bicep. Una risorsa viene distribuita prima di qualsiasi risorsa che ne dipende. Per altre informazioni sulle dipendenze delle risorse in Bicep, incluse le dipendenze esplicite e implicite, vedere Dipendenze delle risorse in Bicep.

  4. Il file orchestration.bicep distribuisce il modulo vwanhub.bicep, che distribuisce l'hub rete WAN virtuale nell'ambito del gruppo di risorse. L'hub dipende in modo implicito dalla rete WAN virtuale, il che significa che la distribuzione dell'hub viene eseguita solo dopo il completamento della distribuzione rete WAN virtuale.

  5. Il file orchestration.bicep distribuisce il modulo azResourceStateCheck.bicep, che crea un'identità gestita assegnata dall'utente e assegna il ruolo di lettore del controllo degli accessi in base al ruolo (RBAC) Azure al gruppo di risorse.

  6. Il modulo azResourceStateCheck.bicep distribuisce la risorsa script di distribuzione.

  7. La risorsa script di distribuzione usa l'identità gestita assegnata dall'utente per l'autenticazione Resource Manager. La risorsa esegue quindi lo script di distribuzione di PowerShell Invoke-AzResourceStateCheck.ps1. Per altre informazioni sugli script di distribuzione, vedere Usare gli script di distribuzione in Bicep.

    Lo script esegue il polling della proprietà rete WAN virtuale hub routingState per determinare se il valore è Provisioned:

    1. Se il valore della proprietà non è Provisioned, lo script viene sospeso per una durata specificata da un parametro impostato nel file orchestration.bicep e passato come parametro al modulo azResourceStateCheck.bicep. Lo script controlla quindi di nuovo il valore della routingState proprietà.

      Lo script ripete il ciclo di pausa e controllo. Un parametro nel file orchestration.bicep determina il numero massimo di iterazioni. Se il valore della proprietà non è Provisioned dopo il numero massimo di iterazioni, lo script genera un'eccezione e si chiude, causando l'arresto e l'esito negativo del resto della distribuzione Bicep.

    2. Se il valore della proprietà è Provisioned, lo script di distribuzione viene chiuso con un codice (0)di operazione riuscita.

  8. Se lo script di distribuzione ha esito positivo, il file orchestration.bicep distribuisce il modulo vwanvhcs.bicep, che crea le connessioni tra le reti virtuali spoke e l'hub rete WAN virtuale.

    La definizione del modulo vwanvhcs.bicep in orchestration.bicep ha una dependsOn clausola che fa sì che vwanvhcs.bicep dipende in modo esplicito dal completamento corretto del modulo azResourceStateCheck.bicep. Pertanto, le connessioni vengono create solo se la routingState proprietà è Provisioned.

    Il modulo vwanvhcs.bicep distribuisce le connessioni hub rete WAN virtuale in sequenza, anziché in parallelo, perché la distribuzione parallela non è supportata per un singolo hub rete WAN virtuale. Per impostare le dimensioni del batch su 1, il modulo utilizza il decorator Bicep batchSize, @batchSize(1). Questo decorator garantisce che le connessioni vengano distribuite una alla volta.

Dettagli dello scenario

Le parti principali di questa architettura sono il modulo azResourceStateCheck.bicep, che distribuisce la risorsa script di distribuzione e lo script di distribuzione associato Invoke-AzResourceStateCheck.ps1, ovvero un file di PowerShell. Il modulo usa lo script di distribuzione per controllare il valore di una proprietà della risorsa. In questo esempio la risorsa è un hub della rete WAN virtuale.

È possibile usare dependsOn per fare in modo che un modulo dipenda in modo esplicito da un altro perché questo ambiente viene distribuito da un singolo file che usa moduli Bicep. In questo esempio il dependsOn modulo vwanvhcs.bicep dipende dal modulo azResourceStateCheck.bicep.

L'estratto seguente di orchestration.bicep mostra come si utilizza 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
  }
}

Il controllo delle risorse è obbligatorio perché gli hub di rete WAN virtuale distribuiti non sono pronti per l'uso finché la proprietà routingState ha il valore di Provisioned. rete WAN virtuale hub segnalano la corretta distribuzione in Resource Manager in modo che il motore di distribuzione continui la distribuzione. Un nuovo hub rete WAN virtuale diventa operativo dopo il provisioning del router hub rete WAN virtuale nell'hub creato. Questo processo richiede circa 15 minuti. Questo comportamento può essere visualizzato nello screenshot seguente di un nuovo hub rete WAN virtuale. Lo screenshot mostra uno stato dell'hub di Succeeded ma uno stato di routing di Provisioning.

Screenshot di un hub di rete WAN virtuale appena distribuito. Lo stato dell'hub è Completato e lo stato del routing è In fase di provisioning.

Se si tenta di distribuire il modulo vwanvhcs.bicep prima che il valore sia routingState, la Provisioned creazione della connessione non riesce e la distribuzione complessiva non riesce. Finché non viene effettuato il provisioning del router, anche i tentativi di ridistribuzione hanno esito negativo.

Lo screenshot seguente mostra un esempio del log dello script di distribuzione durante i controlli del routingState hub rete WAN virtuale. Il log mostra controlli ripetuti della proprietà che restituiscono un valore diverso da Provisioned.

Screenshot che mostra lo script di distribuzione che esegue il polling della proprietà routingState dell'hub rete WAN virtuale.

Lo screenshot seguente mostra che il valore cambia in Provisioned.

Screenshot che mostra il completamento dello script di distribuzione quando la proprietà routingState dell'hub rete WAN virtuale viene modificata in Provisioned.

Se il valore non cambia in Provisioned dopo il numero massimo di iterazioni, lo script genera un'eccezione, che segnala l'errore della risorsa script a Resource Manager. Il motore di distribuzione Resource Manager ha esito negativo e arresta la distribuzione perché l'eccezione suggerisce che si è verificato un problema con la risorsa Azure che richiede la risoluzione dei problemi. Per altre informazioni, vedere lo script di Invoke-AzResourceStateCheck.ps1 seguente.

[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."
}

Contributors

Microsoft gestisce questo articolo. I seguenti collaboratori hanno scritto questo articolo.

Autore principale:

Altro collaboratore:

Per visualizzare i profili LinkedIn non pubblici, accedere a LinkedIn.

Passaggi successivi