共用方式為


在 Bicep 中使用部署指令碼

藉由使用 deploymentScripts 資源,您可以在 Bicep 部署中執行指令碼,並檢閱執行結果。 您可以使用這些指令碼來執行自訂步驟,例如:

  • 將使用者新增到目錄。
  • 執行資料平面作業,例如複製 Blob 或植入資料庫。
  • 查詢及驗證授權金鑰。
  • 建立自我簽署憑證。
  • 在 Microsoft Entra ID 中建立物件。
  • 從自訂系統查詢 IP 位址區塊。

部署指令碼的優點包括:

  • 易於編寫程式碼、使用和偵錯。 您可以在慣用的開發環境中開發部署指令碼。 這些指令碼可以內嵌在 Bicep 檔案或外部指令檔中。
  • 您可以指定指令碼語言和平台。 目前支援在 Linux 環境上的 Azure PowerShell 和 Azure CLI 部署指令碼。
  • 您可以允許將命令列引數傳遞至指令碼。
  • 您可以指定指令碼輸出,並將其傳回至部署。

部署指令碼資源僅適用於可使用 Azure 容器執行個體的區域。 如需詳細資訊,請參閱 Azure 容器執行個體在 Azure 區域中的資源可用性

警告

部署指令碼服務需要兩個額外的資源才能執行和疑難排解指令碼:儲存體帳戶和容器執行個體。 一般而言,服務會在部署指令碼完成之後清除這些資源。 在移除這些資源之前,您需要承擔這些資源的費用。

如需價格資訊,請參閱容器執行個體定價Azure 儲存體定價。 若要深入了解,請參閱清除部署指令碼資源

訓練資源

如果您比較想要透過逐步指導來了解部署指令碼,請參閱使用部署指令碼擴充 Bicep 和 ARM 範本

設定最低權限

針對部署指令碼 API 版本 2020-10-01 或更新版本,部署指令碼執行牽涉到兩個主體:

  • 部署主體:此主體是用來部署 Bicep 檔案。 部署主體會建立部署指令碼資源執行所需的基礎資源,也就是儲存體帳戶和 Azure 容器執行個體。 若要設定最低權限,請使用下列屬性將自訂角色指派給部署主體:

    {
      "roleName": "deployment-script-minimum-privilege-for-deployment-principal",
      "description": "Configure least privilege for the deployment principal in deployment script",
      "type": "customRole",
      "IsCustom": true,
      "permissions": [
        {
          "actions": [
            "Microsoft.Storage/storageAccounts/*",
            "Microsoft.ContainerInstance/containerGroups/*",
            "Microsoft.Resources/deployments/*",
            "Microsoft.Resources/deploymentScripts/*"
          ],
        }
      ],
      "assignableScopes": [
        "[subscription().id]"
      ]
    }
    

    如果未註冊 Azure 儲存體和 Azure 容器執行個體資源提供者,請務必新增 Microsoft.Storage/register/actionMicrosoft.ContainerInstance/register/action

  • 部署指令碼主體:只有在部署指令碼需要向 Azure 進行驗證並呼叫 Azure CLI 或 PowerShell 時,才需要此主體。 有兩種方式可以指定部署指令碼主體:

    • identity 屬性中指定使用者指派的受控識別。 (請參閱部署指令碼資源語法。)指定使用者指派的受控識別時,指令碼服務會在叫用部署指令碼之前先呼叫 Connect-AzAccount -Identity。 受控識別必須擁有必要的存取權,才能完成指令碼中的作業。 目前,identity 屬性僅支援使用者指派的受控識別。 若要使用不同的身分識別登入,請使用此清單中的第二個方法。
    • 將服務主體認證傳遞為安全的環境變數,然後在部署指令碼中呼叫 Connect-AzAccountaz login

    如果使用受控識別,則部署主體需要將內建的「受控識別操作員」角色指派給受控識別資源。

目前,不會針對設定部署指令碼權限而量身打造任何內建角色。

建立部署指令碼

下列範例示範有部署指令碼資源的簡單 Bicep 檔案。 指令碼會接受一個字串參數,並建立另一個字串。

param name string = 'John Dole'
param location string = resourceGroup().location

resource deploymentScript 'Microsoft.Resources/deploymentScripts@2023-08-01' = {
  name: 'inlineCLI'
  location: location
  kind: 'AzureCLI'
  properties: {
    azCliVersion: '2.52.0'
    arguments: name
    scriptContent: 'echo "The argument is ${name}."; jq -n -c --arg st "Hello ${name}" \'{"text": $st}\' > $AZ_SCRIPTS_OUTPUT_PATH'
    retentionInterval: 'PT1H'
  }
}

output text string = deploymentScript.properties.outputs.text

如需建立部署指令碼資源的詳細資訊,請參閱建立部署指令碼。 若要建立部署指令碼資源的指令碼,建議您建立專用的指令碼開發環境,例如 Azure 容器執行個體或 Docker 映像。 在您開發並徹底測試指令碼之後,可以從部署指令碼資源整合或叫用指令碼檔案。 如需詳細資訊,請參閱設定指令碼開發環境

將指令碼儲存在 inlineScript.bicep 檔案中,然後使用下列指令碼來部署資源:

$resourceGroupName = Read-Host -Prompt "Enter the name of the resource group to be created"
$location = Read-Host -Prompt "Enter the location (i.e. centralus)"

New-AzResourceGroup -Name $resourceGroupName -Location $location

New-AzResourceGroupDeployment -ResourceGroupName $resourceGroupName -TemplateFile "inlineScript.bicep"

Write-Host "Press [ENTER] to continue ..."

使用受控識別

下列範例示範如何使用受控識別,從部署腳本內部與 Azure 互動。

@description('The location of the resources.')
param location string = resourceGroup().location

@description('The storage account to list blobs from.')
param storageAccountData {
  name: string
  container: string
}

@description('The role id of Storage Blob Data Reader.')
var storageBlobDataReaderRoleId = '2a2b9908-6ea1-4ae2-8e65-a410df84e7d1'

@description('The storage account to read blobs from.')
resource storageAccount 'Microsoft.Storage/storageAccounts@2023-04-01' existing = {
  name: storageAccountData.name
}

@description('The Storage Blob Data Reader Role definition from [Built In Roles](https://learn.microsoft.com/en-us/azure/role-based-access-control/built-in-roles).')
resource storageBlobDataReaderRoleDef 'Microsoft.Authorization/roleDefinitions@2022-05-01-preview' existing = {
  scope: subscription()
  name: storageBlobDataReaderRoleId
}

@description('The user identity for the deployment script.')
resource scriptIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-07-31-preview' = {
  name: 'script-identity'
  location: location
}

@description('Assign permission for the deployment scripts user identity access to the read blobs from the storage account.')
resource dataReaderRoleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
  scope: storageAccount
  name: guid(storageBlobDataReaderRoleDef.id, scriptIdentity.id, storageAccount.id)
  properties: {
    principalType: 'ServicePrincipal'
    principalId: scriptIdentity.properties.principalId
    roleDefinitionId: storageBlobDataReaderRoleDef.id
  }
}

@description('The deployment script.')
resource script 'Microsoft.Resources/deploymentScripts@2023-08-01' = {
  name: 'script'
  location: location
  kind: 'AzureCLI'
  identity: {
    type: 'UserAssigned'
    userAssignedIdentities: {
      '${scriptIdentity.id}': {}
    }
  }
  properties: {
    azCliVersion: '2.59.0'
    retentionInterval: 'PT1H'
    arguments: '${storageAccount.properties.primaryEndpoints.blob} ${storageAccountData.container}'
    scriptContent: '''
      #!/bin/bash
      set -e
      az storage blob list --auth-mode login --blob-endpoint $1 --container-name $2
    '''
  }
}

監視部署指令碼並進行疑難排解

部署一個部署指令碼資源時,需要儲存體帳戶來儲存使用者指令碼、執行結果,以及 stdout 檔案。 您可以指定自己的儲存體帳戶。 如需詳細資訊,請參閱使用現有的儲存體帳戶

除了指定自己的儲存體帳戶,也可以將 cleanupPreference 設定為 OnExpiration。 接著,設定 retentionInterval 持續時間,以允許在移除儲存體帳戶之前有足夠的時間檢閱輸出。 如需詳細資訊,請參閱清除部署指令碼資源

cleanupPreference 屬性新增至上述 Bicep 檔案,並將值設定為 OnExpiration。 預設值是 Always。 此外,將 rentalInterval 設定為 PT1H (一小時) 或更短時間。

param name string = 'John Dole'
param location string = resourceGroup().location

resource deploymentScript 'Microsoft.Resources/deploymentScripts@2023-08-01' = {
  name: 'inlineCLI'
  location: location
  kind: 'AzureCLI'
  properties: {
    azCliVersion: '2.52.0'
    arguments: name
    scriptContent: 'echo "The argument is ${name}."; jq -n -c --arg st "Hello ${name}" \'{"text": $st}\' > $AZ_SCRIPTS_OUTPUT_PATH'
    cleanupPreference: 'OnExpiration'
    retentionInterval: 'PT1H'
  }
}

output text string = deploymentScript.properties.outputs.text

成功部署 Bicep 檔案之後,請使用 Azure 入口網站、Azure CLI、Azure PowerShell 或 REST API 來檢查結果。

Azure 入口網站

在部署指令碼資源部署完成後,資源會列在 Azure 入口網站中的資源群組下。 [概觀] 頁面除了部署指令碼資源之外,還會列出兩個支援的資源。 在保留間隔到期後,系統會刪除支援的資源。

請注意,這兩個支援資源的名稱都有 azscripts 尾碼,因為這些資源是自動建立的。 識別支援資源的另一種方式是使用標籤

部署腳本資源群組的螢幕快照。

從清單中選取部署指令碼資源。 部署指令碼資源的 [概觀] 頁面會顯示資源的重要資訊,例如 [佈建狀態] 和兩個支援資源 ([儲存體帳戶] 和 [容器執行個體])。 [記錄] 區域會顯示指令碼中的列印文字。

部署腳本資源相關信息的螢幕快照。

選取 [輸出] 以顯示指令碼的輸出。

部署腳本輸出的螢幕快照。

回到資源群組,選取儲存體帳戶,選取 [檔案共用],然後選取共用名稱附加了 azscripts的檔案共用。 清單中會出現兩個資料夾:azscriptinputazscriptoutput。 輸出資料夾包含 executionresult.json 檔案和指令碼輸出檔案。 executionresult.json 檔案包含指令碼執行錯誤訊息。 只有在您成功執行指令碼時,才會建立輸出檔案。

部署腳本輸出資料夾內容的螢幕快照。

輸入資料夾包含系統指令檔和使用者部署指令檔。 您可以使用已修改的檔案來取代使用者部署指令檔,然後從 Azure 容器執行個體重新執行部署指令碼。

Azure CLI

您可以使用 Azure CLI,在訂用帳戶或資源群組範圍管理部署指令碼:

list 命令的輸出類似此範例:

{
  "arguments": "John Dole",
  "azCliVersion": "2.52.0",
  "cleanupPreference": "OnExpiration",
  "containerSettings": {
    "containerGroupName": null
  },
  "environmentVariables": null,
  "forceUpdateTag": null,
  "id": "/subscriptions/01234567-89AB-CDEF-0123-456789ABCDEF/resourceGroups/dsDemo/providers/Microsoft.Resources/deploymentScripts/inlineCLI",
  "identity": null,
  "kind": "AzureCLI",
  "location": "centralus",
  "name": "inlineCLI",
  "outputs": {
    "text": "Hello John Dole"
  },
  "primaryScriptUri": null,
  "provisioningState": "Succeeded",
  "resourceGroup": "dsDemo",
  "retentionInterval": "1:00:00",
  "scriptContent": "echo \"The argument is John Dole.\"; jq -n -c --arg st \"Hello John Dole\" '{\"text\": $st}' > $AZ_SCRIPTS_OUTPUT_PATH",
  "status": {
    "containerInstanceId": "/subscriptions/01234567-89AB-CDEF-0123-456789ABCDEF/resourceGroups/dsDemo/providers/Microsoft.ContainerInstance/containerGroups/jgczqtxom5oreazscripts",
    "endTime": "2023-12-11T20:20:12.149468+00:00",
    "error": null,
    "expirationTime": "2023-12-11T21:20:12.149468+00:00",
    "startTime": "2023-12-11T20:18:26.674492+00:00",
    "storageAccountId": "/subscriptions/01234567-89AB-CDEF-0123-456789ABCDEF/resourceGroups/dsDemo/providers/Microsoft.Storage/storageAccounts/jgczqtxom5oreazscripts"
  },
  "storageAccountSettings": null,
  "supportingScriptUris": null,
  "systemData": {
    "createdAt": "2023-12-11T19:45:32.239063+00:00",
    "createdBy": "johndole@contoso.com",
    "createdByType": "User",
    "lastModifiedAt": "2023-12-11T20:18:26.183565+00:00",
    "lastModifiedBy": "johndole@contoso.com",
    "lastModifiedByType": "User"
  },
  "tags": null,
  "timeout": "1 day, 0:00:00",
  "type": "Microsoft.Resources/deploymentScripts"
}

Azure PowerShell

您可以使用 Azure PowerShell,在訂用帳戶或資源群組範圍管理部署指令碼:

Get-AzDeploymentScript 輸出類似此範例:

Name                : inlinePS
Id                  : /subscriptions/01234567-89AB-CDEF-0123-456789ABCDEF/resourceGroups/dsDemo/providers/Microsoft.Resources/deploymentScripts/inlinePS
ResourceGroupName   : dsDemo
Location            : centralus
SubscriptionId      : 01234567-89AB-CDEF-0123-456789ABCDEF
ProvisioningState   : Succeeded
Identity            :
ScriptKind          : AzurePowerShell
AzPowerShellVersion : 10.0
StartTime           : 12/11/2023 9:45:50 PM
EndTime             : 12/11/2023 9:46:59 PM
ExpirationDate      : 12/11/2023 10:46:59 PM
CleanupPreference   : OnExpiration
StorageAccountId    : /subscriptions/01234567-89AB-CDEF-0123-456789ABCDEF/resourceGroups/dsDemo/providers/Microsoft.Storage/storageAccounts/ee5o4rmoo6ilmazscripts
ContainerInstanceId : /subscriptions/01234567-89AB-CDEF-0123-456789ABCDEF/resourceGroups/dsDemo/providers/Microsoft.ContainerInstance/containerGroups/ee5o4rmoo6ilmazscripts
Outputs             :
                      Key                 Value
                      ==================  ==================
                      text                Hello John Dole.

RetentionInterval   : PT1H
Timeout             : P1D

REST API

您可以使用 REST API,在資源群組層級和訂用帳戶層級取得部署指令碼資源的相關資訊:

/subscriptions/<SubscriptionID>/resourcegroups/<ResourceGroupName>/providers/microsoft.resources/deploymentScripts/<DeploymentScriptResourceName>?api-version=2020-10-01
/subscriptions/<SubscriptionID>/providers/microsoft.resources/deploymentScripts?api-version=2020-10-01

下列範例會使用 ARMClient。 ARMClient 不是受支援的 Microsoft 工具。

armclient login
armclient get /subscriptions/01234567-89AB-CDEF-0123-456789ABCDEF/resourcegroups/myrg/providers/microsoft.resources/deploymentScripts/myDeployementScript?api-version=2020-10-01

輸出類似此範例:

{
  "kind": "AzureCLI",
  "identity": null,
  "location": "centralus",
  "systemData": {
    "createdAt": "2023-12-11T19:45:32.239063+00:00",
    "createdBy": "johndole@contoso.com",
    "createdByType": "User",
    "lastModifiedAt": "2023-12-11T20:18:26.183565+00:00",
    "lastModifiedBy": "johndole@contoso.com",
    "lastModifiedByType": "User"
  },
  "properties": {
    "provisioningState": "Succeeded",
    "azCliVersion": "2.52.0",
    "scriptContent": "echo \"The argument is John Dole.\"; jq -n -c --arg st \"Hello John Dole\" '{\"text\": $st}' > $AZ_SCRIPTS_OUTPUT_PATH",
    "arguments": "John Dole",
    "retentionInterval": "1:00:00",
    "timeout": "1 day, 0:00:00",
    "containerSettings": {
      "containerGroupName": null
    },
    "status": {
      "containerInstanceId": "/subscriptions/01234567-89AB-CDEF-0123-456789ABCDEF/resourceGroups/dsDemo/providers/Microsoft.ContainerInstance/containerGroups/jgczqtxom5oreazscripts",
      "endTime": "2023-12-11T20:20:12.149468+00:00",
      "error": null,
      "expirationTime": "2023-12-11T21:20:12.149468+00:00",
      "startTime": "2023-12-11T20:18:26.674492+00:00",
      "storageAccountId": "/subscriptions/01234567-89AB-CDEF-0123-456789ABCDEF/resourceGroups/dsDemo/providers/Microsoft.Storage/storageAccounts/jgczqtxom5oreazscripts"
    },
    "outputs": {
      "text": "Hello John Dole"
    },
    "cleanupPreference": "OnSuccess"
  },
  "id": "/subscriptions/01234567-89AB-CDEF-0123-456789ABCDEF/resourceGroups/dsDemo/providers/Microsoft.Resources/deploymentScripts/inlineCLI",
  "type": "Microsoft.Resources/deploymentScripts",
  "name": "inlineCLI",
}

下列 REST API 會傳回記錄:

/subscriptions/<SubscriptionID>/resourcegroups/<ResourceGroupName>/providers/microsoft.resources/deploymentScripts/<DeploymentScriptResourceName>/logs?api-version=2020-10-01

只有在刪除部署指令碼資源之前才可運作。


部署指令碼錯誤碼

下表列出部署指令碼的錯誤碼:

錯誤碼 描述
DeploymentScriptInvalidOperation Bicep 檔案中的部署指令碼資源定義包括不正確的屬性名稱。
DeploymentScriptResourceConflict 如果部署指令碼資源處於非終止狀態,且執行未超過一小時,則無法刪除該資源。 或者,您也無法同時重新執行具有相同的資源識別碼 (相同的訂用帳戶、資源群組名稱和資源名稱),但具有不同指令碼主體內容的相同部署指令碼。
DeploymentScriptOperationFailed 部署指令碼作業內部執行失敗。 請連絡 Microsoft 支援服務。
DeploymentScriptStorageAccountAccessKeyNotSpecified 未指定現有儲存體帳戶的存取金鑰。
DeploymentScriptContainerGroupContainsInvalidContainers 部署指令碼服務所建立的容器群組已從外部修改,並新增了不正確的容器。
DeploymentScriptContainerGroupInNonterminalState 有兩個或多個部署指令碼資源在相同的資源群組中使用相同的 Azure 容器執行個體名稱,且其中一個資源尚未完成執行。
DeploymentScriptExistingStorageNotInSameSubscriptionAsDeploymentScript 部署中提供的現有記憶體在部署腳本的訂用帳戶中找不到。
DeploymentScriptStorageAccountInvalidKind BlobBlobStorageBlobStorage 類型的現有儲存體帳戶不支援檔案共用,因此無法使用。
DeploymentScriptStorageAccountInvalidKindAndSku 現有的儲存體帳戶不支援檔案共用。 如需支援的儲存體帳戶類型清單,請參閱使用現有的儲存體帳戶
DeploymentScriptStorageAccountNotFound 儲存體帳戶不存在,或是已遭外部流程或工具刪除。
DeploymentScriptStorageAccountWithServiceEndpointEnabled 指定的儲存體帳戶具有服務端點。 不支援具有服務端點的儲存體帳戶。
DeploymentScriptStorageAccountInvalidAccessKey 為現有儲存體帳戶指定的存取金鑰不正確。
DeploymentScriptStorageAccountInvalidAccessKeyFormat 儲存體帳戶金鑰的格式不正確。 請參閱管理儲存體帳戶存取金鑰
DeploymentScriptExceededMaxAllowedTime 部署指令碼的執行時間超過部署指令碼資源定義中指定的逾時值。
DeploymentScriptInvalidOutputs 部署指令碼輸出不是有效的 JSON 物件。
DeploymentScriptContainerInstancesServiceLoginFailure 使用者指派的受控識別在一分鐘的間隔內嘗試了 10 次後仍無法成功登入。
DeploymentScriptContainerGroupNotFound 外部工具或流程已刪除部署指令碼服務所建立的容器群組。
DeploymentScriptDownloadFailure 下載支援的指令碼失敗。 請參閱使用支援的指令碼
DeploymentScriptError 使用者指令碼擲回錯誤。
DeploymentScriptBootstrapScriptExecutionFailed 啟動程序指令碼擲回錯誤。 啟動程序指令碼是可協調部署指令碼執行的系統指令碼。
DeploymentScriptExecutionFailed 執行部署指令碼期間發生未知的錯誤。
DeploymentScriptContainerInstancesServiceUnavailable 在建立容器執行個體期間,Azure 容器執行個體服務擲回「服務無法使用」錯誤。
DeploymentScriptContainerGroupInNonterminalState 在建立容器執行個體期間,另一個部署指令碼在相同的範圍中使用相同的容器執行個體名稱 (相同的訂用帳戶、資源組名和資源名稱)。
DeploymentScriptContainerGroupNameInvalid 指定的容器執行個體名稱不符合 Azure 容器執行個體需求。 請參閱針對 Azure 容器執行個體的常見問題進行疑難排解

存取私人虛擬網路

您可以使用一些額外的設定,在私人網路中執行部署指令碼。 如需詳細資訊,請參閱存取私人虛擬網路

下一步

在本文中,您已了解如何使用部署指令碼。 若要深入了解,請參閱: