什么是部署脚本?
本单元将介绍 deploymentScripts
资源如何扩展 Azure 资源管理器 (ARM) 模板。
ARM 模板是很棒的内容。 可使用此模板来声明云基础结构的所需状态,让 API 和服务了解如何实现该状态。 但是,有时需要执行 Azure 资源管理器提供的操作之外的操作。
什么是部署脚本?
deploymentScripts
资源是 PowerShell 或 Bash 脚本,作为模板部署的一部分在 Docker 容器中运行。 默认容器映像可使用 Azure CLI 或 Azure PowerShell。 这些脚本在 ARM 模板处理过程中运行,因此可向部署过程添加自定义行为。
部署脚本使用托管标识向 Azure 进行身份验证。 托管标识是服务主体,其凭据和生命周期由 Azure 平台管理。 Azure PowerShell 或 Azure CLI 命令将使用此标识在环境中操作。 由于你分配了标识,因此可以控制 deploymentScripts
资源的影响范围。
deploymentScripts
资源生成部署中其他资源可以使用的输出。 然后,可以从外部系统查找信息或根据环境的当前状态提供数据,以影响部署的其余部分。
部署脚本的工作原理
deploymentScripts
资源采用用户提供的脚本(来自模板或通过 URI)以及可能的一些支持脚本,然后在 Azure 容器实例中运行这些脚本。 为该容器实例分配你提供的托管标识。 脚本及其输出存储在 Azure 存储帐户的文件共享中。
当模板部署运行时,它会检查目标资源组中是否存在现有 deploymentScripts
资源。 如果存在,则会比较属性。 如果一切匹配,则不发生任何新情况。 如果资源不存在或已更改,Azure 资源管理器将创建一个新容器实例,并在该容器实例内运行部署脚本。 任何定义的输出都将传回 Azure 资源管理器,供稍后在部署中使用。
部署脚本结构
若要向 ARM 模板添加自定义行为,请从资源 deploymentScripts
开始。 至少需要提供常见详细信息,例如:
deploymentScripts
资源的name
。type
和apiVersion
值。- 将在其中创建支持资源的位置(
location
值)。 - 空的
properties
对象。 你很快就会了解这一点。
需要两个特定于 deploymentScripts
的值:
kind
:要运行的脚本类型(AzurePowerShell
或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
:容器实例将使用的托管标识。 可以提前创建托管标识并指定它(如以下示例所示),也可以在模板中创建它,然后对其进行引用(你将在下个练习中执行此操作)。{ "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'
}
若要了解 deploymentScripts
资源的所有属性,请参阅 ARM 模板参考文档。