使用Terraform创建多个新实例
我已经编写了一个Terraform脚本,它应该从一个模板创建多个服务器实例。我现在创建了两个不同的变量文件 但是,当我运行脚本时,将使用第一个变量文件创建一个新实例,但使用第二个变量文件时,第一个实例总是被覆盖/更改。我不知道为什么Terraform会引用以前新创建的实例。我怎样才能防止这种情况 服务器-1.tfvars:使用Terraform创建多个新实例,terraform,vsphere,terraform-provider-vsphere,Terraform,Vsphere,Terraform Provider Vsphere,我已经编写了一个Terraform脚本,它应该从一个模板创建多个服务器实例。我现在创建了两个不同的变量文件 但是,当我运行脚本时,将使用第一个变量文件创建一个新实例,但使用第二个变量文件时,第一个实例总是被覆盖/更改。我不知道为什么Terraform会引用以前新创建的实例。我怎样才能防止这种情况 服务器-1.tfvars: vsphere_user = "administrator@vsphere.local" vsphere_pass
vsphere_user = "administrator@vsphere.local"
vsphere_password = "#Password"
vsphere_server = "vsphere.server"
vsphere_datacenter = "Datacenter"
vsphere_datastore = "Storage_1"
vsphere_compute_cluster = "Cluster"
vsphere_network = "Network_1"
vsphere_virtual_machine_template = "Template_Microsoft_Windows_Server_2019_x64_english"
system_name = "server-1"
system_cores = 2
system_cores_per_socket = 2
system_memory = 2048
system_local_admin_password = "#Password"
system_ipv4_address = "172.22.15.11"
system_ipv4_netmask = 24
system_dns_server_list = ["172.22.15.101"]
system_ipv4_gateway = "172.22.15.1"
system_disk1_size = 75
system_domain_admin_user = "Administrator"
system_domain_admin_password = "#Password"
服务器-2.tfvars:
vsphere_user = "administrator@vsphere.local"
vsphere_password = "#Password"
vsphere_server = "vsphere.server"
vsphere_datacenter = "Datacenter"
vsphere_datastore = "Storage_1"
vsphere_compute_cluster = "Cluster"
vsphere_network = "Network_1"
vsphere_virtual_machine_template = "Template_Microsoft_Windows_Server_2019_x64_english"
system_name = "server-2"
system_cores = 2
system_cores_per_socket = 2
system_memory = 2048
system_local_admin_password = "#Password"
system_ipv4_address = "172.22.15.12"
system_ipv4_netmask = 24
system_dns_server_list = ["172.22.15.101"]
system_ipv4_gateway = "172.22.15.1"
system_disk1_size = 75
system_domain_admin_user = "Administrator"
system_domain_admin_password = "#Password"
provider.tf:
provider "vsphere" {
user = var.vsphere_user
password = var.vsphere_password
vsphere_server = var.vsphere_server
allow_unverified_ssl = true
}
data.tf:
# Data Sources
# Datacenter
data "vsphere_datacenter" "dc" {
name = var.vsphere_datacenter
}
# Datastore
data "vsphere_datastore" "datastore" {
name = var.vsphere_datastore
datacenter_id = data.vsphere_datacenter.dc.id
}
# Cluster
data "vsphere_compute_cluster" "cluster" {
name = var.vsphere_compute_cluster
datacenter_id = data.vsphere_datacenter.dc.id
}
# Network
data "vsphere_network" "network" {
name = var.vsphere_network
datacenter_id = data.vsphere_datacenter.dc.id
}
# Template
data "vsphere_virtual_machine" "template" {
name = var.vsphere_virtual_machine_template
datacenter_id = data.vsphere_datacenter.dc.id
}
resource.tf:
# Virtual Machine Resource
resource "vsphere_virtual_machine" "server-instance" {
# System
firmware = "efi"
guest_id = data.vsphere_virtual_machine.template.guest_id
scsi_type = data.vsphere_virtual_machine.template.scsi_type
# VM-Name
name = var.system_name
resource_pool_id = data.vsphere_compute_cluster.cluster.resource_pool_id
datastore_id = data.vsphere_datastore.datastore.id
# CPU
num_cpus = var.system_cores
num_cores_per_socket = var.system_cores_per_socket
cpu_hot_add_enabled = true
cpu_hot_remove_enabled = true
# Memory
memory = var.system_memory
memory_hot_add_enabled = true
# Network
network_interface {
network_id = data.vsphere_network.network.id
adapter_type = "e1000e"
}
# Storage
# Drive 0 (C)
disk {
label = "disk0"
unit_number = 0
size = data.vsphere_virtual_machine.template.disks.0.size
eagerly_scrub = data.vsphere_virtual_machine.template.disks.0.eagerly_scrub
thin_provisioned = data.vsphere_virtual_machine.template.disks.0.thin_provisioned
}
# Drive 1 (D)
disk {
label = "disk1"
unit_number = 1
size = var.system_disk1_size
eagerly_scrub = data.vsphere_virtual_machine.template.disks.1.eagerly_scrub
thin_provisioned = data.vsphere_virtual_machine.template.disks.1.thin_provisioned
}
# Template clone and OS settings
clone {
template_uuid = data.vsphere_virtual_machine.template.id
customize {
windows_options {
computer_name = var.system_name
admin_password = random_password.password.result
join_domain = var.system_domain
domain_admin_user = var.system_domain_admin_user
domain_admin_password = var.system_domain_admin_password
auto_logon = true
}
network_interface {
ipv4_address = var.system_ipv4_address
ipv4_netmask = var.system_ipv4_netmask
dns_server_list = var.system_dns_server_list
}
ipv4_gateway = var.system_ipv4_gateway
}
}
}
password.tf:
# Import the Random Password Provider
terraform {
required_providers {
random = {
source = "hashicorp/random"
}
}
}
resource "random_password" "password" {
length = 25
upper = true
lower = true
number = true
special = true
min_upper = 2
min_lower = 2
min_numeric = 2
min_special = 1
override_special = "!@#$%&*()-_=+[]{}<>:?"
}
#导入随机密码提供程序
地形{
必需的\u提供者{
随机={
source=“hashicorp/random”
}
}
}
资源“随机密码”“密码”{
长度=25
上限=真
下限=真
数字=真
特殊=真实
最小上限=2
最小值=2
最小数值=2
最小值=1
覆盖_special=“!@$%&*()-=+[]{}:?”
}
Terraform的模型是,配置中的每个资源实例都绑定到零个或一个远程对象——如果尚未创建远程对象,则绑定到零个,然后在第一次创建对象后绑定到一个
Terraform模型的另一个重要特征是它是声明性的。您不应该将terraformapply
理解为“创建所有这些东西”,而应该理解为“采取任何必要的措施使远程系统与此配置匹配”。在第一次运行时,通常会导致许多创建操作,但在后续运行中,您通常会对已经存在的对象进行更改,因为提供程序旨在找到中断最少的方式来更改远程系统以匹配更新的配置
记住这一点,当您使用vsphere\u virtual\u machine.server instance
的参数的不同值重新运行Terraform时,Terraform(以及vsphere
提供程序)理解到,您希望更改先前创建的现有对象,而不是创建新对象
为了同时存在多个虚拟机,必须有多个对应的资源实例,每个虚拟机对应一个实例。在Terraform的模型中,每个资源块可以表示一个或多个资源实例;获取两个资源实例最简单的方法是编写两个resource
块,因此每个块将声明一个实例:
resource "vsphere_virtual_machine" "server_1" {
# ...
}
resource "vsphere_virtual_machine" "server_2" {
# ...
}
但是,如果您的多个实例是以一种可以使用Terraform语言中的表达式表达的方式系统地创建的,那么您还有一些其他选项
如果你认为所有的虚拟机在某种意义上都是“拷贝”,所有的功能都是等价的,那么你可以选择使用,这会导致资源
块具有多个与其关联的资源实例(由计数
表达式给出的数字),这些资源实例除了在特殊符号计数.index
中表示的一些细微差异外,在很大程度上具有相同的配置,其中给出了当前索引的索引:
resource "vsphere_virtual_machine" "server" {
count = 2
# VM-Name
name = "${var.system_name}-${count.index}"
resource_pool_id = data.vsphere_compute_cluster.cluster.resource_pool_id
datastore_id = data.vsphere_datastore.datastore.id
# System
firmware = "efi"
guest_id = data.vsphere_virtual_machine.template.guest_id
scsi_type = data.vsphere_virtual_machine.template.scsi_type
# CPU
num_cpus = var.system_cores
num_cores_per_socket = var.system_cores_per_socket
cpu_hot_add_enabled = true
cpu_hot_remove_enabled = true
# Memory
memory = var.system_memory
memory_hot_add_enabled = true
# Network
network_interface {
network_id = data.vsphere_network.network.id
adapter_type = "e1000e"
}
# Storage
# Drive 0 (C)
disk {
label = "disk0"
unit_number = 0
size = data.vsphere_virtual_machine.template.disks.0.size
eagerly_scrub = data.vsphere_virtual_machine.template.disks.0.eagerly_scrub
thin_provisioned = data.vsphere_virtual_machine.template.disks.0.thin_provisioned
}
# Drive 1 (D)
disk {
label = "disk1"
unit_number = 1
size = var.system_disk1_size
eagerly_scrub = data.vsphere_virtual_machine.template.disks.1.eagerly_scrub
thin_provisioned = data.vsphere_virtual_machine.template.disks.1.thin_provisioned
}
# Template clone and OS settings
clone {
template_uuid = data.vsphere_virtual_machine.template.id
customize {
windows_options {
computer_name = var.system_name
admin_password = random_password.password.result
join_domain = var.system_domain
domain_admin_user = var.system_domain_admin_user
domain_admin_password = var.system_domain_admin_password
auto_logon = true
}
network_interface {
ipv4_address = var.system_ipv4_address
ipv4_netmask = var.system_ipv4_netmask
dns_server_list = var.system_dns_server_list
}
ipv4_gateway = var.system_ipv4_gateway
}
}
}
以上内容与您包含的资源“vsphere\u virtual\u machine”“server”
相同,只是我在开始时添加了count=2
,并更改了name
,因此它将var.system\u name
视为一个名称前缀,而不是一个完整的名称,添加当前索引以创建完整的唯一名称。我想您可能还需要对system\u ipv4\u address
遵循类似的策略,可能需要使用来系统地计算IP地址,但为了简单起见,我将在这里省略这一点
如果我们还更改变量文件,使var.system\u name
只是“server”
而不是“server-1”
,那么这将从单个资源块声明两个资源实例:
vsphere\u virtual\u machine.server[0]
与name=“server-0”
vsphere\u virtual\u machine.server[1]
与name=“server-1”
在您共享的示例中,似乎count
最适合您的情况,因为您的服务器虚拟机在其他方面的配置都是相同的。但是,如果您需要将每个服务器视为完全独立的配置,以便它们都具有可能不同的参数,那么您还有另一个选项,形式为。与count
一样,它从单个资源块声明多个资源实例,但它为映射中的每个元素声明多个资源实例,而不仅仅是将整数增加到特定限制
这种方法确实需要对输入变量使用稍微不同的策略,因为我们需要输入是对象的映射,其中映射的每个元素表示一个虚拟机:
variable "virtual_machines" {
type = map(object({
system_cores = number
system_cores_per_socket = number
system_memory = number
system_ipv4_address = string
# (and so on, for all of the attributes that vary between
# your virtual machines)
}))
}
因为这是定义所有虚拟机的单个变量,所以您还需要更改.tfvars
文件,以不同的方式进行设置:
vsphere_user = "administrator@vsphere.local"
vsphere_password = "#Password"
vsphere_server = "vsphere.server"
vsphere_datacenter = "Datacenter"
vsphere_datastore = "Storage_1"
vsphere_compute_cluster = "Cluster"
vsphere_network = "Network_1"
vsphere_virtual_machine_template = "Template_Microsoft_Windows_Server_2019_x64_english"
virtual_machines = {
server-1 = {
system_cores = 2
system_cores_per_socket = 2
system_memory = 2048
system_ipv4_address = "172.22.15.11"
# ...
}
server-2 = {
system_cores = 2
system_cores_per_socket = 2
system_memory = 2048
system_ipv4_address = "172.22.15.12"
# ...
}
}
每个
集合都有的资源
块将如下所示:
resource "vsphere_virtual_machine" "server" {
for_each = var.virtual_machines
# VM-Name
name = each.key
resource_pool_id = data.vsphere_compute_cluster.cluster.resource_pool_id
datastore_id = data.vsphere_datastore.datastore.id
# System
firmware = "efi"
guest_id = data.vsphere_virtual_machine.template.guest_id
scsi_type = data.vsphere_virtual_machine.template.scsi_type
# CPU
num_cpus = each.value.system_cores
num_cores_per_socket = each.value.system_cores_per_socket
cpu_hot_add_enabled = true
cpu_hot_remove_enabled = true
# Memory
memory = each.value.system_memory
memory_hot_add_enabled = true
# Network
network_interface {
network_id = data.vsphere_network.network.id
adapter_type = "e1000e"
}
# Storage
# Drive 0 (C)
disk {
label = "disk0"
unit_number = 0
size = data.vsphere_virtual_machine.template.disks.0.size
eagerly_scrub = data.vsphere_virtual_machine.template.disks.0.eagerly_scrub
thin_provisioned = data.vsphere_virtual_machine.template.disks.0.thin_provisioned
}
# Drive 1 (D)
disk {
label = "disk1"
unit_number = 1
size = each.value.system_disk1_size
eagerly_scrub = data.vsphere_virtual_machine.template.disks.1.eagerly_scrub
thin_provisioned = data.vsphere_virtual_machine.template.disks.1.thin_provisioned
}
# Template clone and OS settings
clone {
template_uuid = data.vsphere_virtual_machine.template.id
customize {
windows_options {
computer_name = each.value.system_name
admin_password = random_password.password.result
join_domain = each.value.system_domain
domain_admin_user = each.value.system_domain_admin_user
domain_admin_password = each.value.system_domain_admin_password
auto_logon = true
}
network_interface {
ipv4_address = each.value.system_ipv4_address
ipv4_netmask = each.value.system_ipv4_netmask
dns_server_list = each.value.system_dns_server_list
}
ipv4_gateway = each.value.system_ipv4_gateway
}
}
}
同样,这与您原来的资源
块基本相同,但我为_each=var.virtual_machines
添加了,将名称
设置为each.key
以使用映射键作为名称,并将对变量的所有其他引用替换为对each.value
属性的引用,它表示映射中当前元素的值
在这种情况下,此资源块将声明以下资源实例:
vsphere\u虚拟机.server[“server-0”]
与name=“server-0”
vsphere\u虚拟机.server[“server-1”]
与name=“server-1”