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

Terraform vSphere提供程序迭代网卡嵌套映射配置方法

如何遍历嵌套映射为Terraform数据资源块分配字符串类型值

场景说明

基于Terraform vSphere 2.0提供程序通过OVA模板批量部署多台虚拟机时,不同环境的虚拟机网络接口配置存在差异,OVA模板仅预置所有环境通用的全局网络接口,需要通过vsphere_network数据源查询各虚拟机网卡对应的分布式虚拟端口组(DVPG)ID。
目标实现逻辑:通过单个vsphere_network数据块迭代获取所有DVPG ID,再通过单个虚拟机资源块结合dynamic网络接口块完成所有虚拟机部署。

现有基础配置

变量定义

variable "vmconfig" {
  description = "Map of VM name => Configs "
  type = map(object({
    name       =   string
    cpus       =   number
    memory     =   number
    folder     =   string
    remote_ovf =   string
    netint     =  map(string)
  }))
  default = {}
}

.tfvars配置示例

vmconfig = {    
  "vm1" = {    
    name       = "vm1"    
    cpus       = 4    
    memory     = 16384    
    folder     = "foo/bary"    
    remote_ovf = "foo.bar.ova"    
    netint     = {    
      nic1 = "segment1",    
      nic2 = "segment2",    
      nic3 = "segment3",
      nic4 = "segment4"    
    }    
  },
  "vm2" = {...}
}

本地值转换配置

locals {
  vm_values = { for name, config in var.vmconfig : name => {
    vm_name        = config.name
    num_cpus       = config.cpus
    memory         = config.memory
    folder         = config.folder
    remote_ovf_url = config.remote_ovf
    netint         = config.netint
    }
  }
}

初始错误实现

最初尝试直接遍历VM配置给数据源传值,同时虚拟机资源未做VM维度遍历:

data "vsphere_network" "nicint" {
  for_each         = local.vm_values
  name             = each.value.netint
  datacenter_id    = data.vsphere_datacenter.dc.id
}

resource "vsphere_virtual_machine" "vm" {
  # 省略其他VM配置
  dynamic "network_interface" {
    for_each = data.vsphere_network.nicint
    content {
      network_id = network_interface.value.id
    }
  }
}

该写法核心问题:each.value.netint是map(string)类型,直接传给要求字符串入参的name字段会触发类型不匹配报错,且虚拟机资源未按VM维度遍历,所有网卡会被错误挂载到单台VM上。

已尝试方案及问题

  • 方案1:直接映射netint为for_each值
    data "vsphere_network" "nicint" {
      for_each         = {for k,v in local.vm_values : k => v.netint}
      name             = each.value
      datacenter_id    = data.vsphere_datacenter.dc.id
    }
    
    触发报错:属性name值不合法,需要字符串类型,实际传入each.value为包含4个元素的字符串map,类型不匹配。
  • 方案2:merge拼接带VM前缀的网卡映射
    locals {
      netint_map = merge([
        for vmtype, values in var.vmconfig:
        {
          for netint in values.netint:
            "${vmtype}-${netint}" => {vmtype = vmtype, netint = netint}
        }
      ]...)
    }
    
    data "vsphere_network" "nicint" {
      for_each         = local.netint_map
      name             = each.value
      datacenter_id    = data.vsphere_datacenter.dc.id
    }
    
    该写法可临时运行,但资源键值设计不合理,后续调整网卡配置时Terraform无法正确识别存量资源关联关系,会触发资源销毁重建,无法完成原地更新。

正确实现方案

核心逻辑分三步:扁平化嵌套网卡配置、去重重复的网络段减少冗余查询、虚拟机资源按VM维度遍历后动态生成对应网卡配置。

第一步:补全本地值逻辑

locals {
  vm_values = { for name, config in var.vmconfig : name => {
    vm_name        = config.name
    num_cpus       = config.cpus
    memory         = config.memory
    folder         = config.folder
    remote_ovf_url = config.remote_ovf
    netint         = config.netint
    }
  }

  # 提取所有不重复的DVPG段名,避免重复查询同一个端口组
  unique_dvpg_segments = toset(flatten([
    for vm_name, vm_conf in local.vm_values : values(vm_conf.netint)
  ]))
}

第二步:配置vsphere_network数据源

同个DVPG仅生成一个数据源实例,减少API调用,键为稳定的段名,不会触发无意义重建:

data "vsphere_network" "nicint" {
  for_each      = local.unique_dvpg_segments
  name          = each.value
  datacenter_id = data.vsphere_datacenter.dc.id
}

第三步:修正虚拟机资源配置

虚拟机资源本身用for_each遍历所有VM配置,内部dynamic块仅遍历当前VM对应的网卡,直接通过段名索引已查询的DVPG ID:

resource "vsphere_virtual_machine" "vm" {
  for_each = local.vm_values

  name             = each.value.vm_name
  num_cpus         = each.value.num_cpus
  memory           = each.value.memory
  folder           = each.value.folder
  # 其余OVA部署配置(remote_ovf_url、磁盘配置等)按原有逻辑补全
  # ...

  dynamic "network_interface" {
    for_each = each.value.netint
    content {
      network_id = data.vsphere_network.nicint[network_interface.value].id
    }
  }
}

该方案优势:

  • 类型完全匹配:name参数始终接收字符串类型的段名,无类型报错
  • 资源状态稳定:所有资源的for_each键与配置强绑定,调整单台VM的单个网卡时仅变更对应资源,不会触发全量销毁重建
  • 执行效率高:同个DVPG仅查询一次,减少不必要的vSphere API调用
  • 配置对齐:网卡顺序与tfvars中定义的nic1、nic2顺序完全一致,不会出现网卡错位问题

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 06:03:21