如何通过Terraform模块在多区域多子网中创建多台VM?
多区域多子网批量部署VM的Terraform实现方案
核心问题分析
当前你的VM模块仅固定关联Subnet1,且未实现区域-子网-VM的多维度遍历,导致所有VM都部署到同一个子网。要实现每个区域的每个子网部署2台VM,需要通过嵌套遍历生成所有实例组合,并动态绑定对应子网ID。
步骤1:调整变量结构(适配多区域场景)
首先更新variables.tf定义多区域的变量类型,确保支持区域、子网、VM模板的层级关联:
variable "regions" { type = map(object({ location = string network_rg_name = string vm_rg_name = string vnet = object({ name = string address_space = list(string) }) subnets = map(object({ name = string address_prefixes = list(string) enforce_private_link_endpoint_network_policies = bool })) vm_templates = map(object({ name = string size = string admin_username = string zone = string vtpm_enabled = bool nic = object({ name = string ip_name = string private_ip_address = string }) })) })) } variable "vm_pwd" { type = string sensitive = true } variable "tfvars" { type = object({ vm_shared = object({ # 补充你的VM共享配置,比如镜像ID等 }) }) }
步骤2:更新terraform.tfvars(填充多区域配置)
将子网和VM模板绑定到每个区域,避免重复代码:
regions = { "eastus" = { location = "eastus" network_rg_name = "rg-network-eastus" vm_rg_name = "rg-vm-eastus" vnet = { name = "vnet-eastus" address_space = ["10.0.0.0/16"] } subnets = { "Subnet1" = { name = "subnet1-eastus" address_prefixes = ["10.0.1.0/24"] enforce_private_link_endpoint_network_policies = false }, "Subnet2" = { name = "subnet2-eastus" address_prefixes = ["10.0.2.0/24"] enforce_private_link_endpoint_network_policies = false }, "Subnet3" = { name = "subnet3-eastus" address_prefixes = ["10.0.3.0/24"] enforce_private_link_endpoint_network_policies = false } }, vm_templates = { "vm1" = { name = "vm1" size = "Standard_D2s_v3" admin_username = "adminuser" zone = "1" vtpm_enabled = true nic = { name = "nic-vm1" ip_name = "ip-vm1" private_ip_address = "" } }, "vm2" = { name = "vm2" size = "Standard_D2s_v3" admin_username = "adminuser" zone = "1" vtpm_enabled = true nic = { name = "nic-vm2" ip_name = "ip-vm2" private_ip_address = "" } } } }, "westus" = { location = "westus" network_rg_name = "rg-network-westus" vm_rg_name = "rg-vm-westus" vnet = { name = "vnet-westus" address_space = ["10.1.0.0/16"] } subnets = { "Subnet1" = { name = "subnet1-westus" address_prefixes = ["10.1.1.0/24"] enforce_private_link_endpoint_network_policies = false }, "Subnet2" = { name = "subnet2-westus" address_prefixes = ["10.1.2.0/24"] enforce_private_link_endpoint_network_policies = false }, "Subnet3" = { name = "subnet3-westus" address_prefixes = ["10.1.3.0/24"] enforce_private_link_endpoint_network_policies = false } }, vm_templates = { "vm1" = { name = "vm1" size = "Standard_D2s_v3" admin_username = "adminuser" zone = "1" vtpm_enabled = true nic = { name = "nic-vm1" ip_name = "ip-vm1" private_ip_address = "" } }, "vm2" = { name = "vm2" size = "Standard_D2s_v3" admin_username = "adminuser" zone = "1" vtpm_enabled = true nic = { name = "nic-vm2" ip_name = "ip-vm2" private_ip_address = "" } } } } } vm_pwd = "your-strong-password" tfvars = { vm_shared = { # 示例:image_id = "/subscriptions/xxx/resourceGroups/xxx/providers/Microsoft.Compute/images/xxx" } }
步骤3:修改main.tf(实现多维度遍历)
3.1 批量创建跨区域子网
module "subnet" { source = "./../modules/subnet" for_each = flatten([ for region_key, region_val in var.regions : [ for subnet_key, subnet_val in region_val.subnets : { key = "${region_key}-${subnet_key}" region_key = region_key region_val = region_val subnet_key = subnet_key subnet_val = subnet_val } ] ]) depends_on = [module.vnet] # 关联你的VNet模块(需按区域遍历) network_rg_name = each.value.region_val.network_rg_name location = each.value.region_val.location route_table_id = module.route_table[each.value.region_key].route_table_id # 关联对应区域的路由表 subnet = each.value.subnet_val vnet = each.value.region_val.vnet }
3.2 生成所有VM实例组合并部署
# 生成区域-子网-VM的全量实例组合 locals { vm_instances = flatten([ for region_key, region_val in var.regions : [ for subnet_key, subnet_val in region_val.subnets : [ for vm_key, vm_val in region_val.vm_templates : { key = "${region_key}-${subnet_key}-${vm_key}" region_key = region_key region_val = region_val subnet_key = subnet_key vm_key = vm_key vm_val = vm_val } ] ] ]) } # 批量部署VM module "vm" { source = "./../modules/vm" for_each = { for inst in local.vm_instances : inst.key => inst } vm_rg_name = each.value.region_val.vm_rg_name location = each.value.region_val.location # 动态绑定对应子网的ID vm_subnet_id = module.subnet["${each.value.region_key}-${each.value.subnet_key}"].subnet_id # 重命名VM/NIC避免跨子网冲突 vm = merge(each.value.vm_val, { name = "${each.value.vm_val.name}-${each.value.region_key}-${each.value.subnet_key}" nic = merge(each.value.vm_val.nic, { name = "${each.value.vm_val.nic.name}-${each.value.region_key}-${each.value.subnet_key}" ip_name = "${each.value.vm_val.nic.ip_name}-${each.value.region_key}-${each.value.subnet_key}" }) }) vm_shared = var.tfvars.vm_shared vm_pwd = var.vm_pwd }
关键说明
- 唯一键生成:用
区域-子网-VM名称作为实例唯一标识,避免资源命名冲突。 - 动态子网绑定:通过子网模块的组合键匹配对应区域的子网ID,确保VM部署到目标子网。
- 嵌套遍历:用
flatten+嵌套for表达式将三维结构(区域/子网/VM)转为一维实例列表,适配for_each要求。
执行terraform plan即可验证:将生成2个区域×3个子网×2台VM=12台VM,分别部署在对应子网中。
内容的提问来源于stack exchange,提问作者Tyra
相关产品推荐
相关产品推荐

