You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Terraform同模块中循环创建Azure订阅与资源组的实现方案

在同一Terraform模块中为多个动态创建的Azure订阅添加资源组

问题背景

我有一个Terraform模块,需要先创建Azure订阅,再为每个订阅添加对应的资源组及其他资源。但azurerm provider在Terraform初始化阶段就已完成配置,这一阶段早于订阅资源的生成,无法动态创建provider实例,也没法通过循环更新provider配置中的subscription_id参数。这种场景下,如何在同一模块中为多个订阅分别创建对应的资源组?

用户提供的初始代码示例:

locals {
  subscriptions = ["example1", "example2"]
  resource_groups = ["rg1", "rg2"]
}

resource "azurerm_subscription" "example" {
  for_each = local.subscriptions
  subscription_name = each.value.name
}

resource "azurerm_resource_group" "example" {
  for_each = local.resource_groups
  name     = each.value.name
  location = "West Europe"
}

解决方案:嵌套模块+实例化专属Provider

利用Terraform的模块嵌套特性,将单个订阅的资源创建逻辑封装为子模块,通过for_each遍历已创建的订阅,为每个订阅实例化独立的子模块,并在子模块中配置指向该订阅的azurerm provider。

步骤1:创建子模块

新建子模块目录(例如./modules/subscription_resources),子模块负责接收订阅ID,配置专属Provider并创建对应资源组。

子模块main.tf代码:

variable "subscription_id" {
  type        = string
  description = "目标Azure订阅的ID"
}

variable "resource_groups" {
  type = list(object({
    name     = string
    location = string
  }))
  description = "要在该订阅中创建的资源组列表"
}

# 配置指向当前订阅的Provider
provider "azurerm" {
  alias           = "target_sub"
  subscription_id = var.subscription_id
  # 认证信息可继承父模块的环境变量/CLI登录,无需重复配置
}

# 为当前订阅创建多个资源组
resource "azurerm_resource_group" "rg" {
  provider = azurerm.target_sub
  for_each = { for rg in var.resource_groups : rg.name => rg }
  name     = each.value.name
  location = each.value.location
}

步骤2:修改父模块逻辑

在父模块中先创建订阅,再调用子模块为每个订阅分配资源组:

父模块main.tf代码:

locals {
  # 定义订阅与对应资源组的映射关系
  subscription_configs = {
    example1 = {
      sub_name      = "业务订阅1"
      resource_groups = [
        { name = "rg-business-1", location = "West Europe" },
        { name = "rg-dev-1", location = "East Asia" }
      ]
    },
    example2 = {
      sub_name      = "业务订阅2"
      resource_groups = [
        { name = "rg-business-2", location = "West Europe" }
      ]
    }
  }
}

# 批量创建Azure订阅
resource "azurerm_subscription" "main" {
  for_each          = local.subscription_configs
  subscription_name = each.value.sub_name
}

# 为每个订阅实例化子模块,创建对应资源组
module "sub_resource_groups" {
  for_each      = azurerm_subscription.main
  source        = "./modules/subscription_resources"
  subscription_id = each.value.id
  resource_groups = local.subscription_configs[each.key].resource_groups
}

方案原理

  • Terraform的模块实例化发生在资源创建阶段之后,因此子模块可以安全引用父模块中已创建的订阅ID。
  • 每个子模块实例会配置独立的azurerm provider(通过alias区分),指向对应的订阅,实现资源与订阅的一一绑定。
  • 认证逻辑可复用父模块的配置(如环境变量AZURE_CLIENT_ID、AZURE_TENANT_ID等),无需重复设置。

注意事项

  • 父模块的azurerm provider需要具备创建Azure订阅的权限(通常需关联租户或管理组级别的角色)。
  • 若需为单个订阅创建多个资源组,只需在subscription_configs中扩展对应资源组列表即可,子模块会自动遍历创建。

内容的提问来源于stack exchange,提问作者Mark

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 18:45:32