什麼是部署指令碼?

已完成

在本單元中,您將了解 deploymentScripts 資源可如何延伸 Azure Resource Manager (ARM) 範本。

ARM 範本很實用。 可用來宣告雲端基礎結構的理想狀態,並透過 API 和服務來設法達成目的。 不過,您偶而需要執行超出 Azure Resource Manager 本分以外的動作。

什麼是部署指令碼?

deploymentScripts 資源是範本部署過程中於 Docker 容器中執行的 PowerShell 或 Bash 指令碼。 預設容器映像提供 Azure CLI 或 Azure PowerShell。 這些指令碼在處理 ARM 範本期間執行,因此,您可以在部署程序中新增自訂行為。

部署指令碼使用受控識別向 Azure 驗證。 受控識別是服務主體,其認證和生命週期由 Azure 平台管理。 此身分識別決定 Azure PowerShell 或 Azure CLI 命令在環境上的動作。 您指派身分識別來控制 deploymentScripts 資源所能影響的範圍。

deploymentScripts 資源產生輸出供部署中的其他資源使用。 然後,您可以從外部系統查閱資訊,或根據環境目前的狀態來提供資料,以影響部署的其餘部分。

部署指令碼的運作方式

deploymentScripts 資源接受使用者提供的指令碼 (從範本或 URI),可能還有一些支援的指令碼,然後在 Azure 容器執行個體中執行指令碼。 您提供的受控識別會指派給該容器執行個體。 指令碼及其輸出儲存在 Azure 儲存體帳戶的檔案共用

範本部署執行時會檢查目標資源群組中是否有現存的 deploymentScripts 資源。 如果是,則會比較屬性。 如果完全相符,則沒有什麼情況發生。 如果資源不存在或已變更,Azure Resource Manager 會建立新的容器執行個體,並在該容器執行個體內執行部署指令碼。 任何已定義的輸出將傳回給 Azure Resource Manager,供稍後在部署中使用。

部署指令碼結構

若要將自訂行為新增至 ARM 範本,請從 deploymentScripts 資源開始。 您至少需要提供常用的詳細資料,例如:

  • deploymentScripts 資源的 name
  • typeapiVersion 值。
  • 將建立支援資源的位置 (location 值)。
  • 空的 properties 物件。 等一下就會看到。

需要兩個 deploymentScripts 特定值:

  • kind:執行的指令碼類型 (AzurePowerShellAzureCLI)。

    {
      "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:容器執行個體將使用的受控識別。 您可以事先建立受控識別,並像下列範例一樣加以指定,也可以在範本中建立它,並在該處加以參考,(這是您將在下一個練習中執行的動作)。

    {
      "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': {}
        }
      }
    }
    

設定這些元素之後,您可以移至 deploymentScripts 資源的 properties 區段。 主要部分是 scriptContent,指定要執行的實際指令碼:

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

請注意,scriptContent 使用多行字串。 在 Bicep 中,您可以在字串前後括上連續三個引號 ('''),就能指定多行字串。

部署指令碼通常將輸出傳回給部署。 例如,如果您使用指令碼來查閱 API 提供的某些資訊,您可能將資訊當作輸出傳回給部署。 然後,部署中的其他資源會在自己的定義中使用該資訊。

以 PowerShell 指令碼為例,您建立名為 $DeploymentScriptOutputs 的變數 (必須是雜湊表) 以傳回輸出。 範例指令碼初始化雜湊表,然後建立名為 text 的輸出,從 $output 區域變數取得值:

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

提示

您也可以在 Bash 中撰寫部署指令碼。 若要從 Bash 指令碼建立輸出,您必須在 AZ_SCRIPTS_OUTPUT_PATH 環境變數指定的位置中建立 JSON 檔案。

properties 區段中,您也可以定義各種選項供 deploymentScripts 取用。 在本課程模組中,我們保持簡單,添加的內容足夠執行指令碼即可。 您至少需要提供要使用的 Azure PowerShell 或 Azure CLI 版本、要執行的指令碼,以及保留間隔。

保留間隔是指結果要保留多久以便您保留資源。 執行指令碼之後預設會移除結果。

"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'
}

完整範本看起來像這樣:

{
  "$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

包含指令檔檔案

在範本中內嵌指令碼可能很麻煩、難以閱讀和了解,而且難以變更。 Bicep 會使用 loadTextContent() 函式在部署中內嵌外部文字檔。 當 Bicep 將您的範本轉譯為 JSON 時,它會將外部檔案內嵌至它發出的範本。

假設您在與 Bicep 範本相同的資料夾中有名為 myscript.ps1 的 PowerShell 檔案。 您可以告訴 Bicep 將檔案內嵌如下:

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

您可以在 ARM 範本參考文件中找到 deploymentScripts 資源的所有屬性。