Automation doesn’t mean only the ability to automate some process and repeating it over and over again. It means also the ability to automate every automated process – if it’s possible of course. So even if we can automatically deploy VM, why shouldn’t we try to deploy multiple machines? Everything is fine until we need to deploy three, four or more same virtual servers. It would be very annoying unless we automate also this process – process of deploying multiple vSphere VMs with Terraform.
If you haven’t read my previous article, you can do it here: Deploying vSphere VM with Terraform. I explained how to create a single VM. It can be used to deploy the same VM many times, but you have to do it manually. It means you need to iterate the following steps:
- run terraform apply
- wait for the completion of the deploy
- change important elements (IP, hostname etc.)
If you want to deploy – for example – three virtual machines with the consecutive addresses and/or hostnames, probably you would prefer to do it with only one run. Of course, it is possible, and I will show you that.
Prepare configuration for creating multiple vSphere VMs with Terraform
Terraform configuration files don’t allow to use loops in the typical meaning of this word. Anyway, it doesn’t mean that you cannot iterate anything. Terraform allows using a meta-parameter called “count”. According to the documentation:
count (int) – The number of identical resources to create. This doesn’t apply to all resources.
That’s simple, right? It means exactly, that you can use this meta-parameter for creating multiple same resources. It is added in the resource section, like here:
resource "vsphere_virtual_machine" "some-vm" { count = "3" name = "test-vm" vcpu = 2 memory = 4096 # ... }
In this scenario, we want to create three virtual machines with 2 vCPUs and 4 GB RAM. But do you see the problem? Yes, it’s the name of the virtual machine. If we leave this configuration, all of the VMs have the same name and hostname, what is unacceptable. Fortunately, it’s easy to change. We can use count.index for iterating the VMs names. For example:
resource "vsphere_virtual_machine" "some-vm" { count = "3" name = "test-vm-${cound.index + 1}" vcpu = 2 memory = 4096 # ... }
This code will create three virtual machines named:
- test-vm-1
- test-vm-2
- test-vm-3
Please notice, that we can perform a simple math like addition. It’s very useful when we want to manipulate the individual values. It can be used also with the IP address, like:
network_interface { label = "${lookup(var.vmnetlabel, var.vmdomain)}" ipv4_address = "10.5.5.${10 + count.index}" ipv4_gateway = "10.5.5.1" ipv4_prefix_length = "24" }
In this example, we will get virtual machines with the following addresses (assuming that count variable is equal 3):
- 10.5.5.10
- 10.5.5.11
- 10.5.5.12
As you can see, counting starts at 0, and it’s not a surprise. It’s a normal iteration, and if you are familiar with some programming language you know that every loop starts iterate at 0 (in the most of the cases). You should remember that to avoid the wrong configuration. But, who cares? It’s possible to run terraform destroy, fix your HCL config files and run terraform one more time!
How to practice?
It’s very easy, so you can try making some exercises with your vSphere infrastructure. You will be notified by Terraform in case of any bad syntax. So the worst thing you can expect is the syntax error. Try, learn and automate your daily work!
If you want to see the more complex example, please visit my GitHub repository:
I just started the automating the IT infrastructure related day to day activities with Terraform. In this process I trying to provision VMs in VMware vSphere environment.
VM got created in vCenter, however Gateway IP aadderss & DNS IP address are not got assigned in the VM
can you please help me.
Thank you
M Rao
Can you please share your valuable inputs to automate the creation of VM activity.
Thank you
Hi! Unfortunately, I’ve not been working with Terraform and vSphere anymore. 🙁 As far as I know, there were many changes to vSphere provider, and the network is one of the most changed parts. I’m afraid that my configs are not valid anymore. As far as I remember, ipv4_gateway is not a part of the network_interface section anymore.
Maybe something like this will help? But I don’t have a possibility to test that configuration:
clone {
template_uuid = "${data.vsphere_virtual_machine.template.id}"
customize {
linux_options {
host_name = "TEST-${count.index +1}"
domain = "test.internal"
}
network_interface {
ipv4_address = "10.20.30.${40 + count.index}"
ipv4_netmask = "24"
}
ipv4_gateway = "10.20.30.1"
}
}
Please see the vSphere Provider documentation: https://www.terraform.io/docs/providers/vsphere/r/virtual_machine.html#cloning-and-customization-example
Hi, In vsphere i was able to create an multiple vm’s in the first attempt of “terraform apply” , when i’m trying to create a 3 more vm’s in the second attempts , during the 2nd time terraform not picks the new available ip’s automatically from vsphere , however it says no changes required ( since it’s refers existing vm’s) appreciate of any help on this issue
I’m afraid, that I’m a little bit out of date with Terraform and vSphere. 🙁 But if I understand well, first you have for example loop over
count = 2
and before the second attempt, you change that to
count = 5
right? Because if you try to do something like this:
1. Set count to 3.
2. Run terraform apply
3. Wait to the end
4. Run terraform apply one more time WITHOUT changing count
then it doesn’t work in fact. And it won’t work. But if you change the value of count, then I don’t have any idea. 🙁
Hello Emil,
I am actually trying to deploy the linux servers into vpshere vcenter through terraform script,But i have query when i want to deploy the multi servers into multi compute cluster in vcenter. like for 3 servers into 3 clusters like Round Robbin method. Can we achieved in terraform script
Hi!
Unfortunately, I don’t think I can help you. 🙁 I’ve not been in vSphere for a long time – about two years at least. So I’m not familiar with current modules. 🙁