使用参数和变量增加灵活性
Bicep 文件的功能非常强大,因为它们具有可重用性。 可以使用 Bicep 编写部署多个环境或资源副本的文件。
玩具公司定期推出新产品,需要使用 Bicep 文件创建每个产品发布所需的 Azure 资源。 需要避免使用固定资源名称。 许多类型的 Azure 资源需要唯一的名称,因此在 Bicep 文件中嵌入名称意味着不能将该文件重新用于多个产品启动。 还必须根据玩具的启动位置在不同位置部署资源,这意味着不能在文件中嵌入资源位置。
在本单元中,你将了解 参数 和变量,这些参数和 变量是两个 Bicep 功能,这些功能可以使 Bicep 文件灵活且可重用。 你还会了解表达式。
注释
本单元中显示的命令用于说明概念。 请暂时不要运行这些命令。 稍后你将练习在此处学到的知识。
参数和变量
参数允许从 Bicep 文件外部引入值。 例如,如果使用 Azure CLI 或 Azure PowerShell 手动部署文件,系统会要求你为每个参数提供值。 你还可创建参数文件,其中列出了要用于部署的所有参数和值。 如果 Bicep 文件是通过自动化流程(如部署管道)部署的,则管道可以提供参数值。
在 Bicep 文件中定义并设置 变量 。 使用变量可以在一个位置存储重要信息,并在整个文件中引用它,而无需复制和粘贴它。
对于将在每个部署之间更改的内容,通常情况下最好使用参数,例如:
- 需要保持唯一的资源名称。
- 将资源部署到的位置。
- 影响资源定价的设置,如其 SKU、定价层和实例计数。
- 访问未在 Bicep 文件中定义的其他系统所需的凭据和信息。
对于每个部署使用相同的值时,变量通常是一个不错的选择,但你想要使值在文件中可重用,或者想要使用表达式创建复杂值时。 此外,还可将变量用于不需要唯一名称的资源。
小窍门
请务必对参数和变量使用良好的命名,因此 Bicep 文件易于阅读和理解。 请确保你使用的是清晰一致的描述性名称。
添加参数
在 Bicep 中,可以定义如下参数:
param appServiceAppName string
我们来看看此定义每个部分的作用:
param
告诉 Bicep 你正在定义参数。appServiceAppName
是参数的名称。 如果手动部署 Bicep 文件,系统可能会要求输入一个值,因此输入的名称必须清楚且易于理解。 该名称也是引用文件中的参数值的方式,就像使用资源符号名称一样。string
是参数的类型。 你可以为 Bicep 参数指定多种不同类型,包括string
(针对文本)、int
(针对数字)以及bool
(针对布尔值 true 或 false 值)。 还可以通过使用array
和object
类型传入更复杂的参数。
小窍门
尝试不要使用太多参数来过度通用化 Bicep 文件。 应使用业务场景所需的最少参数量。 请记住,如果要求发生更改,将来您可以随时更改 Bicep 文件。
提供默认值
你可以选择性地为参数提供默认值。 指定默认值时,参数变为可选。 部署 Bicep 文件的人员可以根据需要指定一个值,但如果不需要,Bicep 将使用默认值。
下面介绍如何添加默认值:
param appServiceAppName string = 'toy-product-launch-1'
注释
在此示例中,Azure 应用服务应用名称具有一个硬编码的默认值。 这不是一个好主意,因为应用服务应用需要唯一的名称。 稍后你将解决此问题。
在 Bicep 文件中使用参数值
声明参数后,可以在 Bicep 文件的其余部分引用它。 我们看看如何在资源定义中使用你的新参数:
resource appServiceApp 'Microsoft.Web/sites@2024-04-01' = {
name: appServiceAppName
location: 'eastus'
properties: {
serverFarmId: appServicePlan.id
httpsOnly: true
}
}
请注意,Bicep 文件现在使用参数值来设置应用资源的资源名称,而不是硬编码的值。
小窍门
Visual Studio Code 的 Bicep 扩展显示了可视指示器,告诉你是否未遵循建议的做法。 例如,如果你定义了一个不使用的参数,则系统会发出警告。 Bicep Linter 会在你工作的时候持续运行这些检查。
添加变量
你可以定义如下所示的变量:
var appServicePlanName = 'toy-product-launch-plan'
变量的定义方式与参数类似,但有几点区别:
- 使用
var
关键字告诉 Bicep 你要声明一个变量。 - 必须为变量提供值。
- 变量不需要类型。 Bicep 可以基于你设置的值确定类型。
表达式
编写 Bicep 文件时,通常不希望硬编码值或要求在参数中指定它们。 相反,你想要在文件运行时发现值。 例如,你可能想要将 Bicep 文件中的所有资源部署到单个 Azure 区域:在其中创建了资源组的区域。 或者,你可能需要根据公司使用的特定命名策略自动为资源创建一个唯一的名称。
Bicep 中的表达式是一个强大的功能,可帮助你处理各种有趣的场景。 我们来看看可以在 Bicep 文件中使用表达式的几个位置。
源位置
当你编写和部署模板时,通常不需要单独指定每个资源的位置。 相反,你可能会有一个简单的业务规则,显示“默认情况下,将所有资源部署到创建资源组的同一位置”。
在 Bicep 中,可以创建一个名为 location
的参数,并使用表达式来设置其值:
param location string = resourceGroup().location
查看该参数的默认值。 它使用一个名为resourceGroup()
,使您可以访问有关 Bicep 文件部署到的资源组的信息。 在此示例中,该文件使用 location
属性。 通常使用这种方法将资源部署到与资源组相同的 Azure 区域。
如果有人正在部署此 Bicep 文件,他们可能会选择替代此处的默认值并使用其他位置。
注释
Azure 中的某些资源只能部署到特定位置。 你可能需要单独的参数来设置这些资源的位置。
现在可以在 Bicep 文件中使用资源位置参数,如下所示:
resource appServiceApp 'Microsoft.Web/sites@2024-04-01' = {
name: appServiceAppName
location: location
properties: {
serverFarmId: appServicePlan.id
httpsOnly: true
}
}
资源名称
许多 Azure 资源都需要唯一的名称。 在你的场景中,你有两个需要唯一名称的资源:存储帐户和应用服务应用。 要求将这些值设为参数可能会使 Bicep 文件的用户面临困难,因为他们需要找到一个没有被其他人使用过的名称。
Bicep 还有一个名为 uniqueString()
的函数,当你创建资源名称时,它会派上用场。 在使用此函数时,需要提供一个种子值,该值在不同的部署中应该是不同的,但在相同资源的所有部署中都是一致的。
如果选择了良好的种子值,则每次部署同一组资源时,都可以获取相同的名称,但每次使用同一 Bicep 文件部署不同的资源集时,都会获得不同的名称。 我们看看如何使用 uniqueString()
函数:
param storageAccountName string = uniqueString(resourceGroup().id)
此参数的默认值将再次使用 resourceGroup()
函数,就像你设置资源位置时所做的那样。 不过,这次你获取的是资源组的 ID。 资源组 ID 如下所示:
/subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/resourceGroups/MyResourceGroup
资源组 ID 包含 Azure 订阅 ID (aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e
) 和资源组名称 (MyResourceGroup
)。 资源组 ID 通常是资源名称种子值的合适候选项,原因如下:
- 每次当你部署相同资源时,它们都将进入同一资源组。
uniqueString()
函数每次都会返回相同的值。 - 如果在 Azure 订阅中部署到两个不同的资源组中,该值
resourceGroup().id
将有所不同,因为资源组名称会有所不同。 对于每组资源,uniqueString()
函数将给出不同的值。 - 如果你将部署到两个不同的 Azure 订阅,那么即使你使用相同的资源组名称,
resourceGroup().id
值也会不同,因为 Azure 订阅 ID 会不同。 对于每组资源,uniqueString()
函数将再次给出不同的值。
小窍门
通常最好使用 Bicep 文件表达式来创建资源名称。 许多 Azure 资源类型都有关于允许的字符及其名称长度的规则。 将资源名称创建逻辑嵌入到 Bicep 文件意味着使用该文件的人无需自己记住并遵循这些规则。
组合字符串
如果你只是使用 uniqueString()
函数设置资源名称,可能会获得唯一的名称,但这些名称没有意义。 好的资源名称也应该是描述性的,这样才能清楚地知道资源的用途。 通常需要将有意义的单词或字符串与唯一值结合起来,创建一个名称。 这样一来,你就可以获得有意义且名称唯一的资源。
Bicep 有一个名为“字符串内插”的功能,可让你组合字符串。 我们来看看它的运作方式:
param storageAccountName string = 'toylaunch${uniqueString(resourceGroup().id)}'
storageAccountName
参数的默认值现在有两个部分:
toylaunch
是一个硬编码字符串,可帮助查看 Azure 中已部署资源的任何人了解存储帐户的用途。${uniqueString(resourceGroup().id)}
是指示 Bicep 评估uniqueString(resourceGroup().id)
函数的输出,然后将其连接到字符串的方法。
小窍门
有时,uniqueString()
函数将创建以数字开头的字符串。 某些 Azure 资源(如存储帐户)不允许其名称以数字开头。 这意味着,最好使用字符串内插来创建资源名称,如前面的示例中所示。
为资源选择 SKU
你的团队的其他成员对你目前构建的 Bicep 代码具有深刻印象。 你们已经共同决定使用 Bicep 文件来部署资源,从而支持所有新玩具的发布。
你的一个同事建议为每个产品发布创建非生产环境,以帮助营销团队在将站点提供给客户之前对其进行测试。 但是,你需要确保不会在非生产环境上花费太多的资金,因此你们共同决定一些策略:
- 在生产环境中,存储帐户将部署在
Standard_GRS
(异地冗余存储)SKU 上,以实现高复原能力。 应用服务计划将部署在P2v3
SKU 上,以获得高性能。 - 在非生产环境中,存储帐户将部署在
Standard_LRS
(本地冗余存储)SKU 上。 应用服务计划将部署在免费F1
SKU 上。
满足这些业务需求的一种方法是使用参数来指定每个 SKU。 但是,将每个 SKU 指定为参数可能会变得难以管理,尤其是在拥有较大的 Bicep 文件时。 另一个选项是使用参数、变量和表达式的组合将业务规则嵌入文件中。
首先,你可以指定一个参数,指示部署是用于生产环境还是非生产环境:
@allowed([
'nonprod'
'prod'
])
param environmentType string
请注意,此代码使用一些新语法来指定参数 的允许值environmentType
列表。 除非 Bicep 提供其中一个值,否则 Bicep 不会让任何人部署 Bicep 文件。
接下来,你可以创建变量,根据环境确定用于存储帐户和应用服务计划的 SKU:
var storageAccountSkuName = (environmentType == 'prod') ? 'Standard_GRS' : 'Standard_LRS'
var appServicePlanSkuName = (environmentType == 'prod') ? 'P2V3' : 'F1'
这里还要注意一些新的语法。 让我们来详细讲解:
(environmentType == 'prod')
计算结果为布尔值(true 或 false),具体取决于用于environmentType
参数的允许值。?
称为三元运算符,它计算 语句。if/then
如果表达式为 true,则使用?
运算符后面的值。 如果表达式的计算结果为 false,则使用冒号 (:
) 后面的值。
我们可以将这些规则转换为:
- 对于
storageAccountSkuName
变量,如果environmentType
参数设置为prod
,则使用Standard_GRS
SKU。 否则,使用Standard_LRS
SKU。 - 对于
appServicePlanSkuName
变量,如果environmentType
参数设置为prod
,则使用P2V3
SKU 和PremiumV3
层。 否则,使用F1
SKU。
小窍门
当你创建类似于这样的多部分表达式时,最好使用变量,而不是将表达式直接嵌入资源属性中。 这使 Bicep 文件更易于阅读和理解,因为这样可以避免将资源定义与逻辑混淆。
在 Bicep 文件中使用参数、变量和表达式时,可以重复使用文件并快速部署一组新的资源。 例如,每次营销部门要求你为下一次玩具发布部署新的网站时,为所部署的每个环境提供一些新参数值就可以了!