Terraform 地形-从地图创建更多虚拟机

Terraform 地形-从地图创建更多虚拟机,terraform,vmware,Terraform,Vmware,我有一个带有映射的变量文件: variable "machines" { default = { // type = map(string) "VM1" = { "name" = "VM_1" "ip" = "192.168.10.10" "procs" = 8 "ram" = 8192

我有一个带有映射的变量文件:

 variable "machines" {
 default = {
 //  type = map(string)
 "VM1" = {
    "name" = "VM_1"
    "ip" = "192.168.10.10"
    "procs" = 8
    "ram" = 8192
    "network" = "VM_Network_A33"
    "gateway" = "192.168.10.254"
    "template" = "Templates/Template1"
    "guest_id" = "centosGuest"
 }

 "VM2" = {
      "name" = "VM_2"
      "ip" = "192.168.11.10"
      "procs" = 4
      "ram" = 4096
      "network" = "VM_Network_A34"
      "gateway" = "192.168.11.254"
      "template" = "Templates/Template2"
      "guest_id" = "centosGuest"
    }
  }
}
和一个资源文件

data "vsphere_virtual_machine" "template" {
  name          = var.vsphere_vm_template
  datacenter_id = data.vsphere_datacenter.dc.id
} 
data "vsphere_network" "network" {
  name          = var.network
  datacenter_id = data.vsphere_datacenter.dc.id
}
resource "vsphere_virtual_machine" "machine" {
  for_each          = var.machines
  name              = "${var.site}${var.env}${each.value.name}"
  resource_pool_id  = data.vsphere_compute_cluster.cluster.resource_pool_id
  datastore_id      = data.vsphere_datastore.datastore.id
  folder            = var.vm_folder

  num_cpus          = each.value.procs
  memory            = each.value.ram
  guest_id          = each.value.guest_id

  disk {
    label            = "${var.site}${var.env}${each.value.name}.vmdk"
    size             = data.vsphere_virtual_machine.template.disks[0].size
    thin_provisioned = data.vsphere_virtual_machine.template.disks[0].thin_provisioned
  }
  scsi_type = data.vsphere_virtual_machine.template.scsi_type
  network_interface {
    network_id   = data.vsphere_network.network.id
    adapter_type = data.vsphere_virtual_machine.template.network_interface_types[0]
  }

  clone {
    template_uuid = data.vsphere_virtual_machine.template.id

    customize {
      linux_options {
        host_name = "${var.site}${var.env}${each.value.name}"
        domain    = "${var.site}.${var.domain}"
      }

      network_interface {
        ipv4_address = each.value.ip
        ipv4_netmask = var.network_netmask
      }

      ipv4_gateway    = var.gateway
      dns_server_list = var.network_dns
      dns_suffix_list = [var.domain]
    }
  }

}
我需要在
machines
变量中创建尽可能多的虚拟机,但要使用单个资源文件。在这一点上,它不起作用,因为每台机器使用的模板和网络是不同的

我有一个解决方案,但这意味着有一个资源文件(为模板和网络定义
data
,并在
data
下有资源。这会多次复制资源(我至少要构建20台机器)

我正在寻找的解决方案是有一个单一的资源文件,我可以在其中通过模板列表和网络列表进行迭代,并使用相同的
资源“vsphere\u virtual\u machine”“machine”
machines
中的每个条目创建一个VM

多谢各位

编辑:

vars文件:

variable "machines" {
//  type = map(string)
default = {
  "VM1" = {
    "name" = "VM_01"
    "ip" = "192.168.10.10"
    "procs" = 8
    "ram" = 8192
    "network" = "VM_Network_A10"
    "gateway" = "192.168.10.254"
    "template" = "Templates/Template1"
    "guest_id" = "centos64Guest"
    "annotation" = "VM_1"
  }
  "VM2" = {
    "name" = "VM_02"
    "ip" = "192.168.10.11"
    "procs" = 4
    "ram" = 4096
    "network" = "VM_Network_A10"
    "gateway" = "192.168.10.254"
    "template" = "Templates/Template1"
    "guest_id" = "centos64Guest"
    "annotation" = "VM_2"
  }
  "VM3" = {
    "name" = "VM_03"
    "ip" = "192.168.11.10"
    "procs" = 1
    "ram" = 4096
    "network" = "VM_Network_A11"
    "gateway" = "192.168.11.254"
    "template" = "Templates/Template2"
    "guest_id" = "rhel4Guest"
    "annotation" = "VM_3"
  }
main.yml:

data "vsphere_virtual_machine" "template" {
  for_each      = var.machines
  name          = each.value.template
  datacenter_id = data.vsphere_datacenter.dc.id
}
data "vsphere_network" "network" {
  for_each      = var.machines
  name          = each.value.network
  datacenter_id = data.vsphere_datacenter.dc.id
}

resource "vsphere_virtual_machine" "machine" {
  for_each          = var.machines
  name              = "${var.site}${var.env}${each.value.name}"
  resource_pool_id  = data.vsphere_compute_cluster.cluster.resource_pool_id
  datastore_id      = data.vsphere_datastore.datastore.id
  folder            = var.vm_folder

  num_cpus          = each.value.procs
  memory            = each.value.ram
  guest_id          = each.value.guest_id
  annotation        = each.value.annotation

  //  disk {
  //    label            = "${var.site}${var.env}${each.value.name}.vmdk"
  //    size             = data.vsphere_virtual_machine.template[each.key].disks[0].size
  //    thin_provisioned = data.vsphere_virtual_machine.template[each.key].disks[0].thin_provisioned
  //  }

  dynamic "disk" {
    for_each = [for s in data.vsphere_virtual_machine.template[each.key].disks: {
    label =  index(data.vsphere_virtual_machine.template[each.key].disks, s)
    //      unit_number =  index(data.vsphere_virtual_machine.template[each.key].disks, s)
    size = s.size
    thin_provisioned = contains(keys(s),"thin_provisioned") ? s.thin_provisioned : "true"
    }]
    content {
      label = disk.value.label
      //      unit_number = disk.value.unit_number
      size = disk.value.size
      //      datastore_id = "${data.vsphere_datastore.datastore.id}"
      thin_provisioned = disk.value.thin_provisioned
    }
  }

  //  scsi_type = data.vsphere_virtual_machine.template[each.key].scsi_type
  network_interface {
  network_id   = data.vsphere_network.network[each.key].id
  adapter_type = data.vsphere_virtual_machine.template[each.key].network_interface_types[0]
  }

  clone {
    template_uuid = data.vsphere_virtual_machine.template[each.key].id

    customize {
      linux_options {
      host_name = "${var.site}${var.env}${each.value.name}"
      domain    = var.domain
     }

     network_interface {
       ipv4_address = each.value.ip
       ipv4_netmask = var.network_netmask
     }

     ipv4_gateway    = var.app_gateway
     dns_server_list = var.network_dns
     dns_suffix_list = [var.domain]
   }
 }
}

上述方法可行,但仍然存在一个问题,我得到的错误是:

Error: disk: duplicate SCSI unit_number 0
你知道我该怎么修吗? 谢谢!

已解决! 我不得不取消注释
单元号
,因为对于第一个磁盘
单元号
默认为0,但是下一个磁盘需要显式地设置它

dynamic "disk" {
  for_each = [for s in data.vsphere_virtual_machine.template[each.key].disks: {
  label =  index(data.vsphere_virtual_machine.template[each.key].disks, s
  unit_number =  index(data.vsphere_virtual_machine.template[each.key].disks, s)
  size = s.size
  thin_provisioned = contains(keys(s),"thin_provisioned") ? s.thin_provisioned : "true"
}]
content {
  label = disk.value.label
  unit_number = disk.value.unit_number
  size = disk.value.size
  //      datastore_id = "${data.vsphere_datastore.datastore.id}"
  thin_provisioned = disk.value.thin_provisioned
}
}

注释1/2…var.vsphere\u vm\u template和var.network的差异值是否会与映射变量中提到的作为网络和模板的差异值相同?如果是,则您应该为每个循环使用两个数据源:data“vsphere\u virtual\u machine”“template”…name=each.value.template data“vsphere\u network”“network”…name=each.value.networkComment 2/2…当您这样做时,我猜您将能够像这样引用差异网络和模板。data.vsphere\u virtual\u machine.template[each.key].id data.vsphere\u network.network[each.key].id我希望我有一个虚拟机设置来测试这一点以确定,但我猜它应该会工作。尝试一下,检查tf计划是否如您预期的那样。谢谢,@giridhar jThanks发布最终解决方案。