使用 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。 然后,可以使用工作流模板输入根据输入值自动选择正确的参数文件。
on:
workflow_call:
inputs:
environmentType:
required: true
type: string
# ...
jobs:
deploy:
runs-on: ubuntu-latest
steps:
# ...
- uses: azure/arm-deploy@v1
with:
failOnStdErr: false
resourceGroupName: ${{ inputs.resourceGroupName }}
template: ./deploy/main.bicep
parameters: ./deploy/azuredeploy.parameters.${{ inputs.environmentType }}.json
使用参数文件时,工作流 YAML 文件不需要包含需要单独传递到部署步骤的参数列表。 当你拥有大量参数时,这尤其有用。
参数文件将参数值一起保存在单个 JSON 文件中。 参数文件也是 Git 存储库的一部分,因此可以与所有其他代码相同的方式对其进行版本控制。
重要
参数文件不应用于安全值。 无法保护参数文件中机密的值,切勿将机密提交到 Git 存储库。
工作流变量
通过 GitHub Actions 可存储工作流变量,这对于可能因环境而异的值非常有用。 对于只希望定义一次然后在整个工作流中重用的值,它们也很有用。
YAML 文件中定义的变量
可以在 YAML 文件中定义变量并设置其值。 当需要多次重用同一值时,这很有用。 你可以为整个工作流定义变量,也可以为一个作业或单个步骤定义变量:
env:
MyVariable1: value1
jobs:
deploy:
runs-on: ubuntu-latest
env:
MyVariable2: value2
steps:
- run: echo Hello world!
env:
MyVariable3: value3
Web 界面中定义的机密
与 Bicep 参数文件一样,YAML 文件不适用于机密。 相反,可以使用 GitHub Web 界面定义机密。 你可以随时更改变量值,工作流将在下次运行时读取更新的值。 GitHub Actions 尝试在工作流日志中隐藏机密值。 这意味着,你可以存储 Bicep 文件随后作为参数与 @secure()
装饰器一起接受的值。
警告
默认情况下,GitHub Actions 将对工作流日志中的机密变量值进行模糊处理,但你需要遵循良好的做法。 工作流步骤可以访问机密的值。 如果工作流包含以不安全方式处理机密的步骤,则有可能在工作流日志中显示机密值。 应始终仔细审查对工作流定义文件所做的任何更改,确认不会错误地处理机密。
创建机密时,GitHub 允许选择是将其限定为整个 Git 存储库还是特定环境。 环境范围内的机密遵循你对环境配置的保护规则,因此,如果你配置了所需的审阅者规则,则工作流无法访问机密值,直到指定的 GitHub 用户批准你的管道部署到该环境。
环境范围的机密可能有用,但它们无法轻松地与 Azure 资源管理器的预检验证或 what-if 操作搭配使用。 这些操作需要与 Azure 通信,这意味着它们需要工作负载标识。 通常需要在预检验证或 What-if 操作完成后提供部署批准,以便你对要部署的更改具有很高的置信度。 因此,如果使用环境范围的机密,则人工评审过程在工作流中发生得太早。
因此,在本模块的练习中,不使用环境范围的机密。 而是使用包含环境名称的可预测名称创建存储库范围的机密。 这使工作流能够识别要用于每个环境的正确机密。 在自己的工作流中,可以选择使用存储库范围的机密、环境范围的机密,甚至两者的混合。
注意
还可以将机密范围扩大为 GitHub 组织。 虽然这不在本模块的范围内,但我们在摘要中链接到更多信息。
在工作流中使用变量
在工作流中访问变量值的方式取决于变量的类型。
类型 | 语法 |
---|---|
在同一文件中定义的变量 | ${{ env.VARIABLE_NAME }} |
被调用的工作流的输入 | ${{ inputs.INPUT_NAME }} |
机密 | ${{ secrets.SECRET_NAME }} |
例如,运行 Bicep 部署时,可以使用机密来指定要使用的 Azure 工作负载标识,使用调用的工作流输入来指定资源组名称,并使用变量指定参数的值:
jobs:
deploy:
runs-on: ubuntu-latest
env:
MyParameter: value-of-parameter
steps:
- uses: actions/checkout@v3
- uses: azure/login@v1
with:
client-id: ${{ secrets.AZURE_CLIENT_ID }}
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
- uses: azure/arm-deploy@v1
with:
failOnStdErr: false
resourceGroupName: ${{ inputs.resourceGroupName }}
template: ./deploy/main.bicep
parameters: myParameter=${{ env.MyParameter }}
最佳方法是什么?
你已经了解了几种处理 Bicep 文件部署所需参数的方法。 了解何时可以使用哪种方法会很有帮助。
避免不必要的参数
参数有助于使 Bicep 文件可重用,但很容易定义过多参数。 部署 Bicep 文件时,需要为每个参数提供一个值。 在针对多个环境的复杂部署中,很难管理大量的单个参数值。
考虑尽可能将参数设为可选项,并使用适用于大多数环境的默认值。 这样便可以避免工作流传递参数值。
此外,请记住,当资源需要连接到其他资源时,通常会在 Bicep 中使用参数。 例如,如果网站需要连接到存储帐户,则需要提供存储帐户名称和访问密钥。 密钥是安全值。 但是,在部署此资源组合时,请考虑以下其他方法:
- 使用网站的托管标识访问存储帐户。 创建托管标识时,Azure 会自动生成并管理其凭据。 此方法简化了连接设置。 这也意味着你根本不需要处理机密,所以这是最安全的选择。
- 在同一 Bicep 模板中同时部署存储帐户和网站。 使用 Bicep 模块整合网站和存储资源。 然后便可以在 Bicep 代码中自动查找存储帐户名称和密钥的值,而不是传入参数。
- 将存储帐户的详细信息作为机密添加到密钥保管库。 然后网站代码可直接从保管库加载访问密钥。 此方法完全无需管理工作流中的密钥。
对小型参数集使用工作流变量
如果 Bicep 文件只有一些参数,请考虑在 YAML 文件中定义变量。
对大型参数集使用参数文件
如果 Bicep 文件有大量参数,请考虑使用参数文件将每个环境的非安全值放置在一起。 然后,无论何时需要更改值,都可以更新参数文件并提交更改。
这种方法使工作流步骤更简单,因为不需要为每个参数显式设置值。
安全地存储机密
使用适当的过程来存储和处理机密。 使用 GitHub 机密将机密存储在 GitHub 存储库中,或使用 Key Vault 在 Azure 中存储机密。
对于安全参数,请记得将每个参数显式传递到部署步骤中。
GitHub 可以自动扫描存储库中意外提交的机密,以便可以收到通知。 然后,你可以移除和轮换这些机密。 我们在总结中提供了指向此功能详细信息的链接。
组合方法
结合多种方法来处理参数很常见。 例如,可以将大部分参数值存储在参数文件中,然后使用机密设置安全值。 下面的示例演示了这一组合:
on:
workflow_dispatch:
inputs:
environmentType:
required: true
type: string
resourceGroupName:
required: true
type: string
secrets:
AZURE_CLIENT_ID:
required: true
AZURE_TENANT_ID:
required: true
AZURE_SUBSCRIPTION_ID:
required: true
MySecureParameter:
required: true
permissions:
id-token: write
contents: read
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: azure/login@v1
with:
client-id: ${{ secrets.AZURE_CLIENT_ID }}
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
- uses: azure/arm-deploy@v1
with:
failOnStdErr: false
resourceGroupName: ${{ inputs.resourceGroupName }}
template: ./deploy/main.bicep
parameters: >
./deploy/azuredeploy.parameters.${{ inputs.environmentType }}.json
mySecureParameter=${{ secrets.MySecureParameter }}
提示
在此示例末尾,使用 >
字符将 parameters
值作为 YAML 多行字符串提供。 这使得 YAML 文件更易于读取。 它相当于将整个值包含在一行中。