使用现有资源

已完成

Bicep 文件通常需要引用已在其他位置创建的资源。 这些资源可能是由某个同事使用 Azure 门户手动创建的。 或者,它们可能是在另一个 Bicep 文件中创建的。 需要引用这些资源的原因有很多,例如:

  • 你正在将一个 SQL 数据库添加到某人已创建的 Azure SQL 逻辑服务器实例中。
  • 你正在为在另一个 Bicep 模块中定义的资源配置诊断设置。
  • 你必须安全地访问已手动部署到你的订阅中的存储帐户的密钥。

Bicep 为你提供 existing 关键字供你在这些情况下使用。

注意

本单元中显示的命令用于说明概念。 请暂时不要运行这些命令。 稍后你将练习在此处学到的知识。

引用现有资源

在 Bicep 文件中,可以定义已存在的资源。 声明看起来与常规资源定义相似,有一些关键的区别。 在现有资源定义的以下示例中,该定义引用名为 toydesigndocs 的存储帐户。 存储帐户位于你的 Bicep 模板要将资源部署到的同一资源组中。

resource storageAccount 'Microsoft.Storage/storageAccounts@2023-05-01' existing = {
  name: 'toydesigndocs'
}

让我们仔细看看是什么构成了这个定义:

  • 与常规资源一样,包含 resource 关键字、符号名称、资源类型和 API 版本。

    备注

    请记住,符号名称只能在此 Bicep 文件中使用。 如果使用一个 Bicep 文件创建此资源,并在其他 Bicep 文件中使用 existing 资源来引用它,则象征性名称不必匹配。

  • existing 关键字向 Bicep 指示此资源定义是对已创建资源的引用,并且 Bicep 不应尝试部署它。

  • name 属性是以前部署的存储帐户的 Azure 资源名称。

  • 无需指定 locationskuproperties,因为模板不部署资源。 它仅引用现有资源。 将它视为占位符资源。

引用子资源

还可以引用现有的子资源。 使用与你部署子资源时相同类型的语法。 下面的示例演示如何引用现有子网,该子网是虚拟网络的一个子资源。 本例使用嵌套的子资源,如下所示:

resource vnet 'Microsoft.Network/virtualNetworks@2024-05-01' existing = {
  name: 'toy-design-vnet'

  resource managementSubnet 'subnets' existing = {
    name: 'management'
  }
}

请注意,父资源和子资源都应用了 existing 关键字。

然后,可以使用用于其他嵌套子资源的相同 :: 运算符来引用子网:

output managementSubnetResourceId string = vnet::managementSubnet.id

请参阅资源组外部的资源

通常,你需要引用其他资源组中的资源。 例如,如果在集中式资源组中有一个虚拟网络,则可能要在其自己的资源组中将虚拟机部署到该虚拟网络中。 可以使用 scope 关键字引用其他资源组中的现有资源。 以下示例演示如何引用 networking-rg 资源组中名为 toy-design-vnet 的虚拟网络:

resource vnet 'Microsoft.Network/virtualNetworks@2024-05-01' existing = {
  scope: resourceGroup('networking-rg')
  name: 'toy-design-vnet'
}

请注意,scope 使用 resourceGroup() 关键字来引用包含虚拟网络的资源组。

甚至可以引用其他 Azure 订阅中的资源,只要该订阅位于 Microsoft Entra 租户中。 如果你的网络团队在不同的订阅中预配了虚拟网络,则模板可以引用它,如下例所示:

resource vnet 'Microsoft.Network/virtualNetworks@2024-05-01' existing = {
  scope: resourceGroup('A123b4567c-1234-1a2b-2b1a-1234abc12345', 'networking-rg')
  name: 'toy-design-vnet'
}

请注意,scope 使用 resourceGroup() 关键字来引用 Azure 订阅 ID (A123b4567c-1234-1a2b-2b1a-1234abc12345) 和包含虚拟网络的资源组名称。

了解如何引用现有资源后,让我们看看如何在模板中使用此功能。

将子资源和扩展资源添加到现有资源

可以通过使用 existing 关键字和 parent 关键字的组合将子资源添加到已创建的父资源。 以下示例模板在服务器中创建已存在的 Azure SQL 数据库:

resource server 'Microsoft.Sql/servers@2024-05-01-preview' existing = {
  name: serverName
}

resource database 'Microsoft.Sql/servers/databases@2024-05-01-preview' = {
  parent: server
  name: databaseName
  location: location
  sku: {
    name: 'Standard'
    tier: 'Standard'
  }
}

如果需要将扩展资源部署到现有资源,可以使用 scope 关键字。 下面的模板使用 existing 关键字和 scope 关键字将资源锁添加到已存在的存储帐户:

resource storageAccount 'Microsoft.Storage/storageAccounts@2023-05-01' existing = {
  name: 'toydesigndocs'
}

resource lockResource 'Microsoft.Authorization/locks@2020-05-01' = {
  scope: storageAccount
  name: 'DontDelete'
  properties: {
    level: 'CanNotDelete'
    notes: 'Prevents deletion of the toy design documents storage account.'
  }
}

引用现有资源的属性

资源通常需要引用其他资源的属性。 例如,如果部署应用程序,则可能需要知道另一资源的键或连接信息。 通过使用 existing 关键字,可以访问所引用的资源的属性。

提示

最佳做法是以这种方式查找来自其他资源的键,而不是通过输出传递这些键。 你将始终获得最新的数据。 而且,重要的是,输出并不用于处理安全数据(如键)。

访问资源相关信息的方式取决于所获取信息的类型。 如果它是一个不安全的属性,那么通常只使用资源的 properties。 下面的示例模板部署一个 Azure Functions 应用程序,并将访问详细信息(检测密钥)用于已创建的 Application Insights 实例:

resource applicationInsights 'Microsoft.Insights/components@2020-02-02' existing = {
  name: applicationInsightsName
}

resource functionApp 'Microsoft.Web/sites@2024-04-01' = {
  name: functionAppName
  location: location
  kind: 'functionapp'
  properties: {
    siteConfig: {
      appSettings: [
        // ...
        {
          name: 'APPINSIGHTS_INSTRUMENTATIONKEY'
          value: applicationInsights.properties.InstrumentationKey
        }
      ]
    }
  }
}

在此示例中,由于检测密钥不被视为敏感数据,因此可以在资源的 properties 中找到它。 当需要访问安全数据(如用于访问资源的凭据)时,请使用 listKeys() 函数,如以下代码所示:

resource storageAccount 'Microsoft.Storage/storageAccounts@2023-05-01' existing = {
  name: storageAccountName
}

resource functionApp 'Microsoft.Web/sites@2024-04-01' = {
  name: functionAppName
  location: location
  kind: 'functionapp'
  properties: {
    siteConfig: {
      appSettings: [
        // ...
        {
          name: 'StorageAccountKey'
          value: storageAccount.listKeys().keys[0].value
        }
      ]
    }
  }
}

请注意,listKeys 函数会返回数组 keys。 Bicep 代码从 value 数组的第一项检索 keys 属性。 每个资源类型都具有 listKeys() 函数提供的不同信息。 适用于 Visual Studio Code 的 Bicep 扩展提供提示,以帮助你了解每个资源的 listKeys() 函数返回的数据。 以下屏幕截图显示了存储帐户的 listKeys() 函数的输出:

适用于 Visual Studio Code 的 Bicep 扩展的屏幕截图。IntelliSense 显示由存储帐户的 listKeys 函数返回的多个信息。

一些资源也支持其他函数。 Visual Studio Code 的 IntelliSense 列出了每个资源可用的函数。 在下面的屏幕截图中,你可以看到,除了 listKeys() 之外,存储帐户还提供了名为 listAccountSas()listServiceSas() 的函数:

适用于 Visual Studio Code 的 Bicep 扩展的屏幕截图。IntelliSense 显示存储帐户可用的几个函数。

重要

listKeys() 函数提供对有关资源的敏感数据的访问。 这意味着,运行部署的用户或服务主体需要具有对资源的适当级别的权限。 这通常是参与者内置角色,或分配适当权限的自定义角色。