Che cosa sono gli script di distribuzione?

Completato

In questa unità si apprenderà come estendere i modelli di Azure Resource Manager con la risorsa deploymentScripts.

I modelli di ARM sono risorse straordinarie. È possibile usarli per dichiarare lo stato desiderato dell'infrastruttura cloud e indicare alle API e ai servizi come ottenerlo. In alcuni casi, tuttavia, è necessario eseguire azioni non previste da Azure Resource Manager.

Che cosa sono gli script di distribuzione?

Le risorse deploymentScripts sono script di PowerShell o Bash che vengono eseguiti in un contenitore Docker come parte della distribuzione del modello. Le immagini del contenitore predefinite hanno l'interfaccia della riga di comando di Azure o Azure PowerShell disponibile. Questi script vengono eseguiti durante l'elaborazione del modello di ARM, quindi è possibile aggiungere un comportamento personalizzato al processo di distribuzione.

Gli script di distribuzione usano un'identità gestita per l'autenticazione in Azure. Un'identità gestita è un'entità servizio le cui credenziali e il cui ciclo di vita sono gestiti dalla piattaforma Azure. Questa identità verrà usata da Azure PowerShell o dall'interfaccia della riga di comando di Azure per agire sull'ambiente. Poiché è l'utente che assegna l'identità, controlla anche l'ambito degli elementi su cui può influire una risorsa deploymentScripts.

La risorsa deploymentScripts produce un output che può essere usato da altre risorse nella distribuzione. È quindi possibile cercare informazioni in un sistema esterno o fornire dati in base allo stato corrente dell'ambiente per influire sul resto della distribuzione.

Come funzionano gli script di distribuzione

Una risorsa deploymentScripts accetta uno script fornito dall'utente (dal modello o tramite URI) ed eventualmente alcuni script di supporto, quindi li esegue in un'istanza di contenitore di Azure. A tale istanza di contenitore viene assegnata l'identità gestita specificata. Gli script e il relativo output vengono archiviati in una condivisione file per un account di archiviazione di Azure.

Quando viene eseguita, la distribuzione del modello controlla se è presente una risorsa deploymentScripts esistente nel gruppo di risorse di destinazione. In caso affermativo, confronta le proprietà. Se tutto corrisponde, non succede nulla di nuovo. Se la risorsa non esiste o è stata cambiata, Azure Resource Manager crea una nuova istanza di contenitore ed esegue gli script di distribuzione al suo interno. Qualsiasi output definito verrà restituito ad Azure Resource Manager per l'uso successivo nella distribuzione.

Struttura degli script di distribuzione

Per aggiungere un comportamento personalizzato a un modello di ARM, si inizia con la risorsa deploymentScripts. Come minimo, è necessario fornire dettagli comuni come:

  • Un oggetto name per la risorsa deploymentScripts.
  • I valori di type e apiVersion.
  • La posizione (valore di location) in cui verranno create le risorse di supporto.
  • Oggetto properties vuoto. Questa impostazione verrà illustrata tra poco.

Sono necessari due valori specifici di deploymentScripts:

  • kind: il tipo di script da eseguire (AzurePowerShell o AzureCLI).

    {
      "type": "Microsoft.Resources/deploymentScripts",
      "apiVersion": "2020-10-01",
      "name": "myFirstDeploymentScript",
      "location": "[resourceGroup().location]",
      "kind": "AzurePowerShell",
      "identity": {
        "type": "UserAssigned",
        "userAssignedIdentities": {
          "/subscriptions/01234567-89AB-CDEF-0123-456789ABCDEF/resourcegroups/deploymenttest/providers/Microsoft.ManagedIdentity/userAssignedIdentities/myscriptingid": {}
        }
      }
    }
    
    resource myFirstDeploymentScript 'Microsoft.Resources/deploymentScripts@2020-10-01' = {
      name: 'myFirstDeploymentScript'
      location: resourceGroup().location
      kind: 'AzurePowerShell'
      identity: {
        type: 'UserAssigned'
        userAssignedIdentities: {
          '/subscriptions/01234567-89AB-CDEF-0123-456789ABCDEF/resourcegroups/deploymenttest/providers/Microsoft.ManagedIdentity/userAssignedIdentities/myscriptingid': {}
        }
      }
    }
    
  • identity: l'identità gestita che verrà usata dall'istanza di contenitore. È possibile creare l'identità gestita in anticipo e specificarla come nell'esempio seguente oppure è possibile crearla nel modello e farvi riferimento (ovvero ciò che verrà eseguito nell'esercizio successivo).

    {
      "type": "Microsoft.Resources/deploymentScripts",
      "apiVersion": "2020-10-01",
      "name": "myFirstDeploymentScript",
      "location": "[resourceGroup().location]",
      "kind": "AzurePowerShell",
      "identity": {
        "type": "UserAssigned",
        "userAssignedIdentities": {
          "/subscriptions/01234567-89AB-CDEF-0123-456789ABCDEF/resourcegroups/deploymenttest/providers/Microsoft.ManagedIdentity/userAssignedIdentities/myscriptingid": {}
        }
      }
    }
    
    resource myFirstDeploymentScript 'Microsoft.Resources/deploymentScripts@2020-10-01' = {
      name: 'myFirstDeploymentScript'
      location: resourceGroup().location
      kind: 'AzurePowerShell'
      identity: {
        type: 'UserAssigned'
        userAssignedIdentities: {
          '/subscriptions/01234567-89AB-CDEF-0123-456789ABCDEF/resourcegroups/deploymenttest/providers/Microsoft.ManagedIdentity/userAssignedIdentities/myscriptingid': {}
        }
      }
    }
    

Dopo aver impostato tali elementi, è possibile passare alla sezione properties della risorsa deploymentScripts. La parte principale di questa sezione è l'oggetto scriptContent, che specifica lo script effettivo da eseguire:

"properties": {
  "scriptContent": "
      $output = 'Hello Learner!'
      Write-Output $output
      $DeploymentScriptOutputs = @{}
      $DeploymentScriptOutputs['text'] = $output
  ",
}
properties: {
  scriptContent: '''
    $output = 'Hello Learner!'
    Write-Output $output
    $DeploymentScriptOutputs = @{}
    $DeploymentScriptOutputs['text'] = $output
  '''
}

Si noti che scriptContent usa una stringa su più righe. In Bicep è possibile specificare una stringa su più righe usando tre virgolette (''') prima e dopo.

È comune che uno script di distribuzione passi gli output alla distribuzione. Ad esempio, se si usa uno script per cercare alcune informazioni in un'API, è possibile passare tali informazioni alla distribuzione come output. Altre risorse della distribuzione potrebbero quindi usare le informazioni nelle proprie definizioni.

Per uno script di PowerShell, gli output si passano creando una variabile denominata $DeploymentScriptOutputs, che deve essere una tabella hash. Lo script di esempio inizializza la tabella hash e quindi crea un output denominato text, che ne accetta il valore dalla variabile locale $output:

$output = 'Hello Learner!'
Write-Output $output
$DeploymentScriptOutputs = @{}
$DeploymentScriptOutputs['text'] = $output
$output = 'Hello Learner!'
Write-Output $output
$DeploymentScriptOutputs = @{}
$DeploymentScriptOutputs['text'] = $output

Suggerimento

È anche possibile scrivere script di distribuzione in Bash. Per creare output da uno script Bash, è necessario creare un file JSON in una posizione specificata dalla variabile di ambiente AZ_SCRIPTS_OUTPUT_PATH.

All'interno della sezione properties si definiscono anche le varie opzioni che possono essere accettate da deploymentScripts. In questo modulo, per semplicità, verranno aggiunte solo quelle sufficienti per consentire l'esecuzione dello script. Come minimo, è necessario specificare la versione di Azure PowerShell o dell'interfaccia della riga di comando di Azure da usare, uno script da eseguire e un intervallo di conservazione.

L'intervallo di conservazione è il periodo in cui dovranno conservati i risultati se si vogliono mantenere le risorse. Per impostazione predefinita, i risultati vengono rimossi dopo l'esecuzione dello script.

"properties": {
  "azPowerShellVersion": "3.0",
  "scriptContent": "
      $output = 'Hello Learner!'
      Write-Output $output
      $DeploymentScriptOutputs = @{}
      $DeploymentScriptOutputs['text'] = $output
  ",
  "retentionInterval": "P1D"
}
properties: {
  azPowerShellVersion: '3.0'
  scriptContent: '''
    $output = 'Hello Learner!'
    Write-Output $output
    $DeploymentScriptOutputs = @{}
    $DeploymentScriptOutputs['text'] = $output
  '''
  retentionInterval: 'P1D'
}

Il modello completo sarà simile al seguente:

{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.1",
  "apiProfile": "",
  "parameters": {},
  "variables": {},
  "functions": [],
  "resources": [
    {
      "type": "Microsoft.Resources/deploymentScripts",
      "apiVersion": "2020-10-01",
      "name": "myFirstDeploymentScript",
      "location": "[resourceGroup().location]",
      "kind": "AzurePowerShell",
      "identity": {
        "type": "UserAssigned",
        "userAssignedIdentities": {
          "/subscriptions/01234567-89AB-CDEF-0123-456789ABCDEF/resourcegroups/deploymenttest/providers/Microsoft.ManagedIdentity/userAssignedIdentities/myscriptingid": {}
        }
      },
      "properties": {
        "azPowerShellVersion": "3.0",
        "scriptContent": "
            $output = 'Hello Learner!'
            Write-Output $output
            $DeploymentScriptOutputs = @{}
            $DeploymentScriptOutputs['text'] = $output
        ",
        "retentionInterval": "P1D"
      }
    }
  ],
  "outputs": {
    "scriptResult": {
      "type": "string",
      "value": "[reference('myFirstDeploymentScript').outputs.text]"
    }
  }
}
resource myFirstDeploymentScript 'Microsoft.Resources/deploymentScripts@2020-10-01' = {
  name: 'myFirstDeploymentScript'
  location: resourceGroup().location
  kind: 'AzurePowerShell'
  identity: {
    type: 'UserAssigned'
    userAssignedIdentities: {
      '/subscriptions/01234567-89AB-CDEF-0123-456789ABCDEF/resourcegroups/deploymenttest/providers/Microsoft.ManagedIdentity/userAssignedIdentities/myscriptingid': {}
    }
  }
  properties: {
    azPowerShellVersion: '3.0'
    scriptContent: '''
      $output = 'Hello Learner!'
      Write-Output $output
      $DeploymentScriptOutputs = @{}
      $DeploymentScriptOutputs['text'] = $output
    '''
    retentionInterval: 'P1D'
  }
}

output scriptResult string = myFirstDeploymentScript.properties.outputs.text

Includi file di script

L'incorporamento di script inline nei modelli può essere complesso, difficile da leggere e comprendere e difficile da modificare. Bicep usa la funzione loadTextContent() per incorporare un file di testo esterno nella distribuzione. Quando Bicep esegue il transpile del modello in JSON, incorpora il file esterno nel modello generato.

Si supponga di avere un file di PowerShell denominato myscript.ps1 nella stessa cartella del modello Bicep. È possibile indicare a Bicep di incorporare il file come segue:

properties: {
  azPowerShellVersion: '3.0'
  scriptContent: loadTextContent('myscript.ps1')
  retentionInterval: 'P1D'
}

È possibile trovare tutte le proprietà per la risorsa deploymentScripts nella documentazione di riferimento del modello di ARM.