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

如何通过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
}

关键说明

  1. 唯一键生成:用区域-子网-VM名称作为实例唯一标识,避免资源命名冲突。
  2. 动态子网绑定:通过子网模块的组合键匹配对应区域的子网ID,确保VM部署到目标子网。
  3. 嵌套遍历:用flatten+嵌套for表达式将三维结构(区域/子网/VM)转为一维实例列表,适配for_each要求。

执行terraform plan即可验证:将生成2个区域×3个子网×2台VM=12台VM,分别部署在对应子网中。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 03:15:49