在 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 ..."

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

部署一個部署指令碼資源時,需要儲存體帳戶來儲存使用者指令碼、執行結果,以及 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 容器執行個體的常見問題進行疑難排解

存取私人虛擬網路

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

下一步

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