向模块添加参数和输出

已完成

创建的每个模块都应具有明确的用途。 将模块视为具有一个“协定”。 它接受一组参数,创建一组资源,并可向父模板提供一些输出。 使用模块的任何人都无需考虑其工作原理,只需模块实现其预期操作即可。

规划模块时,请考虑:

  • 你需要了解什么信息才能实现模块的目的。
  • 所有使用模块的人都希望能提供什么内容。
  • 所有使用模块的人都希望获得哪些产出。

模块参数

考虑模块可接受的参数,以及每个参数是可选还是必需。

为模板创建参数时,建议在可能的位置添加默认参数。 在模块中,添加默认参数并不总是那么重要,因为模块将由可使用自己的默认参数的父模板使用。 如果两个文件中都有类似参数(两个参数都有默认值),则模板的用户可能很难确定将应用哪个默认值并强制实施一致性。 通常最好保留父模板上的默认值,并从模块中删除它。

此外,还应考虑如何管理控制资源的 SKU 的参数和其他重要配置设置。 创建独立 Bicep 模板时,通常会将业务规则嵌入模板中。 例如:部署生产环境时,存储帐户应使用 GRS 层。 不过,众多模块有时会有不同的关注点。

如果要构建需要可重用且灵活的模块,请记住,每个父模板的业务规则可能有所不同,因此,不太建议将业务规则嵌入泛型模块。 请考虑在父模板中定义业务规则,然后通过参数显式传递模块配置。

但是,如果创建模块来使自己的组织能轻松部署符合特定需求的资源,建议添加业务规则以简化父模板。

无论模块中包含什么参数,请确保使用 @description 属性添加有意义的说明:

@description('The name of the storage account to deploy.')
param storageAccountName string

使用条件

使用代码(如 Bicep)部署基础结构的目的之一是避免重复工作,甚至是为了避免创建多个模板来实现相同或相似的目的。 Bicep 的功能为你提供了一个功能强大的工具箱,可用于创建适用于各种情况的可重复使用的模块。 可结合使用模块、表达式、默认参数值和条件等功能来生成可重用的代码,从而提供所需的灵活性。

假设要创建一个部署 Azure Cosmos DB 帐户的模块。 将其部署到生产环境时,需要配置帐户以将其日志发送到 Log Analytics 工作区。 若要将日志配置为发送到 Log Analytics,请定义“diagnosticSettings”资源。

可通过将条件添加到资源定义来满足你的要求,并通过添加默认值使工作区 ID 参数成为可选的:

param logAnalyticsWorkspaceId string = ''

resource cosmosDBAccount 'Microsoft.DocumentDB/databaseAccounts@2022-08-15' = {
  // ...
}

resource cosmosDBAccountDiagnostics 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' =  if (logAnalyticsWorkspaceId != '') {
  scope: cosmosDBAccount
  name: 'route-logs-to-log-analytics'
  properties: {
    workspaceId: logAnalyticsWorkspaceId
    logs: [
      {
        category: 'DataPlaneRequests'
        enabled: true
      }
    ]
  }
}

在 Bicep 模板中包含此模块时,可通过设置工作区 ID 轻松对其进行配置,从而将 Azure Cosmos DB 帐户日志发送到 Log Analytics。 或者,如果要部署的环境不需要日志,则需要省略该参数。 它是否具有默认值。 为满足你要求,该模块将封装执行正确操作所需的逻辑。

提示

if 语句的计算结果为 truefalse 时,记得测试模板对这两个场景是否均有效。

模块输出

模块可以定义输出。 建议为父模板可能需要使用的信息创建输出。 例如,如果模块定义了存储帐户,请考虑为存储帐户的名称创建一个输出,以便父模板可以访问它。

警告

请勿针对机密值使用输出。 输出将记录到部署历史记录中,所以它们不适用于安全值。 可考虑改为以下选项之一:

  • 使用输出提供资源的名称。 然后,父模板可创建具有该名称的 existing 资源,并可动态查找安全值。
  • 将该值写入 Azure Key Vault 机密。 让父模板在需要时从保管库中读取该机密。

父模板可使用变量中的模块输出,可使用其他资源定义的属性,也可将变量和属性作为输出本身公开。 通过在整个 Bicep 文件中公开和使用输出,创建可重用的 Bicep 模块集,这些模块可与团队共享并在多个部署中重复使用。 也建议使用 @description 属性为输出添加有意义的说明:

@description('The fully qualified Azure resource ID of the blob container within the storage account.')
output blobContainerResourceId string = storageAccount::blobService::container.id

提示

你还可使用专用服务来存储、管理和访问 Bicep 模板创建的设置。 Key Vault 旨在存储安全值。 Azure 应用配置旨在存储其他(不安全的)值。

将模块链接在一起

常用方法是创建一个由多个模块共同组成的父 Bicep 文件。 例如,假设你要构建一个新的 Bicep 模板来部署使用专用虚拟网络的虚拟机。 你可创建一个模块来定义虚拟网络。 然后,可以将虚拟网络的子网资源 ID 作为该模块的输出,并将其用作虚拟机模块的输入:

@description('Username for the virtual machine.')
param adminUsername string

@description('Password for the virtual machine.')
@minLength(12)
@secure()
param adminPassword string

module virtualNetwork 'modules/vnet.bicep' = {
  name: 'virtual-network'
}

module virtualMachine 'modules/vm.bicep' = {
  name: 'virtual-machine'
  params: {
    adminUsername: adminUsername
    adminPassword: adminPassword
    subnetResourceId: virtualNetwork.outputs.subnetResourceId
  }
}

在此示例中,符号名称用于模块之间的引用。 此引用有助于 Bicep 自动了解模块之间的关系。

由于 Bicep 知道存在依赖关系,因此会按顺序部署模块:

  1. Bicep 会部署 virtualNetwork 模块中的所有内容。
  2. 如果该部署成功,Bicep 将访问 subnetResourceId 输出值并将其作为参数传递给 virtualMachine 模块。
  3. Bicep 会部署 virtualMachine 模块中的所有内容。

注意

当你依赖某个模块时,Bicep 将等待整个模块部署完成。 在规划模块时,务必记住这一点。 如果你创建了一个定义需要花长时间部署的资源的模块,则依赖于该模块的任何其他资源将等待整个模块的部署完成。