在 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/action
和Microsoft.ContainerInstance/register/action
。部署指令碼主體:只有在部署指令碼需要向 Azure 進行驗證並呼叫 Azure CLI 或 PowerShell 時,才需要此主體。 有兩種方式可以指定部署指令碼主體:
- 在
identity
屬性中指定使用者指派的受控識別。 (請參閱部署指令碼資源語法。)指定使用者指派的受控識別時,指令碼服務會在叫用部署指令碼之前先呼叫Connect-AzAccount -Identity
。 受控識別必須擁有必要的存取權,才能完成指令碼中的作業。 目前,identity
屬性僅支援使用者指派的受控識別。 若要使用不同的身分識別登入,請使用此清單中的第二個方法。 - 將服務主體認證傳遞為安全的環境變數,然後在部署指令碼中呼叫 Connect-AzAccount 或 az 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的檔案共用。 清單中會出現兩個資料夾:azscriptinput 和 azscriptoutput。 輸出資料夾包含 executionresult.json 檔案和指令碼輸出檔案。 executionresult.json 檔案包含指令碼執行錯誤訊息。 只有在您成功執行指令碼時,才會建立輸出檔案。
輸入資料夾包含系統指令檔和使用者部署指令檔。 您可以使用已修改的檔案來取代使用者部署指令檔,然後從 Azure 容器執行個體重新執行部署指令碼。
Azure CLI
您可以使用 Azure CLI,在訂用帳戶或資源群組範圍管理部署指令碼:
- az deployment-scripts delete:刪除部署指令碼。
- az deployment-scripts list:列出所有部署指令碼。
- az deployment-scripts show:擷取部署指令碼。
- az deployment-scripts show-log:顯示部署指令碼記錄。
list 命令的輸出類似此範例:
{
"arguments": "John Dole",
"azCliVersion": "2.52.0",
"cleanupPreference": "OnExpiration",
"containerSettings": {
"containerGroupName": null
},
"environmentVariables": null,
"forceUpdateTag": null,
"id": "/subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/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/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/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/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/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:取得或列出部署指令碼。
- Get-AzDeploymentScriptLog:取得部署指令碼執行的記錄。
- Remove-AzDeploymentScript:移除部署指令碼及其相關聯的資源。
- Save-AzDeploymentScriptLog:將部署指令碼執行記錄儲存至磁碟。
Get-AzDeploymentScript
輸出類似此範例:
Name : inlinePS
Id : /subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/resourceGroups/dsDemo/providers/Microsoft.Resources/deploymentScripts/inlinePS
ResourceGroupName : dsDemo
Location : centralus
SubscriptionId : aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e
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/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/resourceGroups/dsDemo/providers/Microsoft.Storage/storageAccounts/ee5o4rmoo6ilmazscripts
ContainerInstanceId : /subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/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/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/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/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/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/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/resourceGroups/dsDemo/providers/Microsoft.Storage/storageAccounts/jgczqtxom5oreazscripts"
},
"outputs": {
"text": "Hello John Dole"
},
"cleanupPreference": "OnSuccess"
},
"id": "/subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/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 |
BlobBlobStorage 或 BlobStorage 類型的現有儲存體帳戶不支援檔案共用,因此無法使用。 |
DeploymentScriptStorageAccountInvalidKindAndSku |
現有的儲存體帳戶不支援檔案共用。 如需支援的儲存體帳戶類型清單,請參閱使用現有的儲存體帳戶。 |
DeploymentScriptStorageAccountNotFound |
儲存體帳戶不存在,或是已遭外部流程或工具刪除。 |
DeploymentScriptStorageAccountWithServiceEndpointEnabled |
指定的儲存體帳戶具有服務端點。 不支援具有服務端點的儲存體帳戶。 |
DeploymentScriptStorageAccountInvalidAccessKey |
為現有儲存體帳戶指定的存取金鑰不正確。 |
DeploymentScriptStorageAccountInvalidAccessKeyFormat |
儲存體帳戶金鑰的格式不正確。 請參閱管理儲存體帳戶存取金鑰。 |
DeploymentScriptExceededMaxAllowedTime |
部署指令碼的執行時間超過部署指令碼資源定義中指定的逾時值。 |
DeploymentScriptInvalidOutputs |
部署指令碼輸出不是有效的 JSON 物件。 |
DeploymentScriptContainerInstancesServiceLoginFailure |
使用者指派的受控識別在一分鐘的間隔內嘗試了 10 次後仍無法成功登入。 |
DeploymentScriptContainerGroupNotFound |
外部工具或流程已刪除部署指令碼服務所建立的容器群組。 |
DeploymentScriptDownloadFailure |
下載支援的指令碼失敗。 請參閱使用支援的指令碼。 |
DeploymentScriptError |
使用者指令碼擲回錯誤。 |
DeploymentScriptBootstrapScriptExecutionFailed |
啟動程序指令碼擲回錯誤。 啟動程序指令碼是可協調部署指令碼執行的系統指令碼。 |
DeploymentScriptExecutionFailed |
執行部署指令碼期間發生未知的錯誤。 |
DeploymentScriptContainerInstancesServiceUnavailable |
在建立容器執行個體期間,Azure 容器執行個體服務擲回「服務無法使用」錯誤。 |
DeploymentScriptContainerGroupInNonterminalState |
在建立容器執行個體期間,另一個部署指令碼在相同的範圍中使用相同的容器執行個體名稱 (相同的訂用帳戶、資源組名和資源名稱)。 |
DeploymentScriptContainerGroupNameInvalid |
指定的容器執行個體名稱不符合 Azure 容器執行個體需求。 請參閱針對 Azure 容器執行個體的常見問題進行疑難排解。 |
存取私人虛擬網路
您可以使用一些額外的設定,在私人網路中執行部署指令碼。 如需詳細資訊,請參閱使用服務端點存取私人虛擬網路,或透過私人端點私下執行 Bicep 部署指令碼。
下一步
在本文中,您已了解如何使用部署指令碼。 若要深入了解,請參閱: