使用 Bicep 参数处理环境之间的差异

已完成

你已对 Bicep 参数有所了解。 这些参数有助于指定可在 Bicep 文件部署之间更改的值。

参数通常用于支持环境之间的差异。 例如,在非生产环境中,你通常希望部署 Azure 资源的低成本 SKU。 在生产环境中,则想要部署性能更好的 SKU。 并且你可能希望在每个环境中对资源使用不同的名称。

部署 Bicep 文件时,需要为每个参数提供值。 对于如何为管道中的每个参数指定值以及如何为每个环境指定单独的值,有多种选项。 本单元将介绍在部署管道中指定 Bicep 参数的方法。

参数文件

参数文件是 JSON 格式的文件,其中列出了要用于每个环境的参数值。 提交部署时,将参数文件提交到 Azure 资源管理器。

下面是一个示例参数文件:

{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "reviewApiUrl": {
      "value": "https://sandbox.contoso.com/reviews"
    }
  }
}

可以将参数文件与 Bicep 文件一起提交到 Git 存储库。 然后,可以在执行部署的管道模板中引用参数文件。

建议为参数文件建立一致的环境命名策略。 例如,你可以将参数文件命名为 parameters.ENVIRONMENT_NAME.json,例如 parameters.Production.json。 然后,可以使用管道模板参数自动选择正确的参数文件。

parameters: 
- name: environmentType
  type: string
- name: serviceConnectionName
  type: string
- name: resourceGroupName
  type: string

- stage: Deploy
  jobs:
  - deployment: DeployWebsite
    displayName: Deploy Website
    environment: Website
    strategy:
      runOnce:
        deploy:
          steps:
            - checkout: self
            - task: AzureCLI@2
              name: DeployBicepFile
              displayName: Deploy Bicep file
              inputs:
                azureSubscription: ${{parameters.serviceConnectionName}}
                scriptType: 'bash'
                scriptLocation: 'inlineScript'
                inlineScript: |
                  az deployment group create \
                    --resource-group ${{parameters.resourceGroupName}} \
                    --template-file deploy/main.bicep \
                    --parameters deploy/azuredeploy.parameters.${{parameters.environmentType}}.json

使用参数文件时,管道 YAML 文件不需要包含需要单独传递到部署步骤的参数列表。 当你拥有大量参数时,这很有用。

参数文件将参数值一起保存在单个 JSON 文件中。 参数文件也是 Git 存储库的一部分,因此可以与所有其他代码相同的方式对其进行版本控制。

重要

参数文件不应用于安全值。 无法保护参数文件中机密的值,切勿将机密提交到 Git 存储库。

管道变量

通过 Azure Pipelines 可存储管道变量,这对于可能因环境而异的值非常有用。 对于只希望定义一次然后在整个管道中重用的值,它们也很有用。 Azure Pipelines 支持多种定义变量的方法。

YAML 文件中定义的变量

可以在 YAML 文件中定义变量并设置其值。 当需要多次重用同一值时,这很有用。 但与 Bicep 参数文件一样,YAML 文件不适用于机密。

Web 界面中定义的变量

可通过使用 Azure DevOps Web 界面来定义变量。 你可以随时更改变量值,管道将在下次运行时读取更新的值。

通过 Web 界面定义的变量可以标记为机密,这会指示 Azure Pipelines 尝试在管道日志中隐藏变量的值。 这意味着,你可以存储 Bicep 文件随后作为参数与 @secure() 装饰器一起接受的值。

警告

默认情况下,Azure Pipelines 将对管道日志中的机密变量值进行模糊处理,但你需要遵循良好的做法。 管道步骤可以访问所有变量值,包括机密。 如果管道包含以不安全方式处理安全变量的步骤,则有可能在管道日志中显示机密变量。

变量组

还可以定义变量组,即变量集。 与变量一样,你可以使用 Azure DevOps Web 界面定义这些组。 你还可以使用变量组来安全地存储机密。 甚至可以在同一 Azure DevOps 项目的多个管道中重复使用变量组。

与其他变量不同,你需要使用 variables 部分中的 group 关键字将变量组显式导入管道,如下所示:

variables:
- group: MyVariableGroup

使用管道模板时,可以命名变量组,以便使用模板参数轻松加载它们。 例如,假设管道部署到两个环境,需要为每个环境定义一组变量。 在命名变量组时可以将环境名称包含在内,如下所示:

环境名称 变量组名称
测试 ToyWebsiteTest
生产 ToyWebsiteProduction

在每个变量组中,可以为每个环境添加名称相同但值不同的变量。

管道模板文件使用 {{ parameters.PARAMETER_NAME }} 宏来选择要导入的正确变量组:

parameters: 
- name: environmentType
  type: string
  default: 'Test'

variables: 
- group: ToyWebsite${{ parameters.environmentType }}

Key Vault 变量组

可以将变量组链接到 Azure Key Vault。 密钥保管库中的机密作为变量组中的变量提供。 然后,可以在管道中像使用普通变量一样使用这些机密。

Key Vault 使得机密管理更加安全。 它还允许安全团队管理这些值,并将对管道的访问与其使用的机密分开。

将变量组链接到密钥保管库需要执行更多步骤。 这些步骤包括创建一个有权从密钥保管库读取机密的服务连接。 在摘要单元中,我们提供了指向有关如何配置 Key Vault 变量组的更多详细信息的链接。

在管道中使用变量

无论如何定义变量,都可以使用 $(VariableName) 语法在管道中访问其值。 例如,运行 Bicep 部署时,可以使用变量来指定参数的值:

- stage: Deploy
  jobs:
  - deployment: DeployWebsite
    displayName: Deploy Website
    environment: Website
    strategy:
      runOnce:
        deploy:
          steps:
            - checkout: self
            - task: AzureCLI@2
              name: DeployBicepFile
              displayName: Deploy Bicep file
              inputs:
                azureSubscription: MyServiceConnection
                scriptType: 'bash'
                scriptLocation: 'inlineScript'
                inlineScript: |
                  az deployment group create \
                    --resource-group $(ResourceGroupName) \
                    --template-file deploy/main.bicep \
                    --parameters environmentType=$(EnvironmentType)

最佳方法是什么?

你已经了解了几种处理 Bicep 文件部署所需参数的方法。 了解何时可以使用哪种方法会很有帮助。

避免不必要的参数

参数有助于使 Bicep 文件可重用,但很容易定义过多参数。 部署 Bicep 文件时,需要为每个参数提供一个值。 在针对多个环境的复杂部署中,很难管理大量的单个参数值。

考虑尽可能将参数设为可选项,并使用适用于大多数环境的默认值。 这样便可以避免管道传递参数值。

此外,请记住,当资源需要连接到其他资源时,通常会在 Bicep 中使用参数。 例如,如果网站需要连接到存储帐户,则需要提供存储帐户名称和访问密钥。 密钥是安全值。 但是,在部署此资源组合时,请考虑以下其他方法:

  • 使用网站的托管标识访问存储帐户。 创建托管标识时,Azure 会自动生成并管理其凭据。 此方法简化了连接设置。 这也意味着你根本不需要处理机密,所以这是最安全的选择。
  • 在同一 Bicep 模板中同时部署存储帐户和网站。 使用 Bicep 模块整合网站和存储资源。 然后便可以在 Bicep 代码中自动查找存储帐户名称和密钥的值,而不是传入参数。
  • 将存储帐户的详细信息作为机密添加到密钥保管库。 然后网站代码可直接从保管库加载访问密钥。 此方法完全无需管理管道中的密钥。

对小型参数集使用变量组

如果 Bicep 文件只有少量参数,请考虑使用变量组。 可以同时将机密和非机密值存储在变量组中。

对大型参数集使用参数文件

如果 Bicep 文件有大量参数,请考虑使用参数文件将每个环境的非安全值放置在一起。 然后,无论何时需要更改值,都可以更新参数文件并提交更改。

这种方法使管道步骤更简单,因为不需要为每个参数显式设置值。

安全地存储机密

使用适当的过程来存储和处理机密。 如果只有少量机密需要管理,Azure Pipelines 变量和变量组通常可以很好地工作。 但是你可能有更复杂的要求,例如大量机密、许多不同的环境或访问控制限制。 对于这些情况,请考虑将每个环境的机密存储在单独的密钥保管库中。 使用变量组将保管库链接到管道。

对于安全参数,请记得将每个参数显式传递到部署步骤中。

组合方法

结合多种方法来处理参数很常见。 例如,可以将大部分参数值存储在参数文件中,然后使用变量组设置安全值。 下面的示例演示了这一组合:

variables:
- group: MyVariableGroup # This group imports a parameter named MySecureParameter.

stages:

- stage: Deploy
  jobs:
  - deployment: DeployWebsite
    displayName: Deploy Website
    environment: Website
    strategy:
      runOnce:
        deploy:
          steps:
            - checkout: self
            - task: AzureCLI@2
              name: DeployBicepFile
              displayName: Deploy Bicep file
              inputs:
                azureSubscription: MyServiceConnection
                scriptType: 'bash'
                scriptLocation: 'inlineScript'
                inlineScript: |
                  az deployment group create \
                    --resource-group ${{parameters.resourceGroupName}} \
                    --template-file deploy/main.bicep \
                    --parameters deploy/azuredeploy.parameters.${{parameters.environmentName}}.json \
                                 mySecureParameter=$(MySecureParameter)

对于如何指定服务连接名称,有一些特殊规则。 这些规则会影响你在部署到多个环境的管道中使用名称的方式。 例如,你不能使用变量组中定义的变量来指定服务连接名称。 你可以使用管道模板参数来指定要使用的服务连接的名称。