Tag Archives: Template

Quick Fix: Deploying Multiple Ubuntu 18.04 VMs From Template with DHCP Results Same in IP Allocation

In the continuing work I’ve been doing with Terraform, i’ve come across a number of gotchyas when working with VM Templates and deploying them on mass. The nature of the work is that i’m creating and destroying VMs often. Generally speaking I like using Static IP addresses but for the project i’m working on I needed to be able to have an option to deploy and configure the networking with DHCP. Windows and CentOS gave me no issues, however when I went to deploy the Ubuntu 18.04 template I started getting errors on the plan execution.

When I looked at the output of the Terraform where export the VM IP addresses, the json output showed that all the cloned VMs had been assigned the same IP address.

At first I assumed it was due to the same MAC address being assigned by ESXi to the cloned VMs which was resulting in the machines being allocated the same IP, however when I checked the MAC addresses they where all different.

What is Machine-ID:

After some digging online I came across a change in behaviour where Ubuntu uses the machine-id to request DHCP addresses. Ubuntu server default networking goes through cloud-init which by default sends /etc/machine-id in the DHCP request. This leads to the duplicate IP situation.

The /etc/machine-id file contains the unique machine ID of the local system that is set during installation or boot. The machine ID is a single newline-terminated, hexadecimal, 32-character, lowercase ID. When decoded from hexadecimal, this corresponds to a 16-byte/128-bit value. This ID may not be all zeros.

The machine ID is usually generated from a random source during system installation or first boot and stays constant for all subsequent boots. Optionally, for stateless systems, it is generated during runtime during early boot if necessary.

Quick Fix:

From a template perspective there is a quick fix that can be applied where the machine-id file is blanked out. This means upon first boot a new ID is generated. You can’t just delete the machine-id file as it needs to exist. If it doesn’t exist the deployment will fail as it expects it to be there in some form.

The simplest way I achieved this was by zero’ing out the file:

Once done, the VM can be saved again as a template and the cloning operation will result in unique IPs being handed out by the DHCP server.





Using Variable Maps to Dynamically Deploy vSphere VMs with Terraform

I’ve been working on a project over the last couple of weeks that has enabled me to sharpen my Terraform skills. There is nothing better than learning by doing and there is also nothing better than continuously improving code through more advanced constructs and methods. As this project evolved it became apparent that I would need to be able to optimize the Terraform/PowerShell to more easily deploy VMs based on specific vSphere templates.

Rather than have one set of Terraform declarations per template (resulting in a lot of code duplication), or having the declaration variables tied to specific operating systems changing (resulting in more manual change) depending on the what was being deployed, I looked for a way to make it even more “singularly declarative”.

Where this became very handy was when I was looking to deploy VMs based on Linux Distro. 98% of the Terraform code is the same no matter if Ubuntu, or CentOS was being used. The only difference was the vSphere Template being used to clone the new VM from, the Template Password and also, in this case a remote-exec call that needed to be made to open a Firewall port.

To get this working I used Terraform variable maps. As you can see below, the idea behind using maps is to allow groupings of like variables in one block declaration. These map values are then fed through to the rest of the Terraform code. Below is an example of a maps.tf file that I have seperate to the variables.tf file. This was an easier way to logically seperate what was being configured using maps.

At the top I have a standard variable that is the only variable that changes and needs setting. If ubuntu is set as the vsphere_linux_distro then all the map values that are ubuntu = will be used. The same if that variable is set to centos.

This is set in the terraform.tfvars file, and links back to the mappings. From here Terraform will lookup the linux_template variable and map it with the various mapped values.

The above data source that dictates what template is used builds the name from the lookup function of the base variable and the map value.

Above, the values we set in the maps are being used to execute the right command depending if it is Ubuntu or Centos and also to use the correct password depending on the linux_distro set. As mentioned, the declared variable can either be set in the terraform.tfvars file, or passed through at the time the plan is executed.

The result is a more controlled and easily managed way to use Terraform to deploy VMs from different pre-existing VM templates. The variable mappings can be built up over time and used as a complete library or different operating systems with different options. An other awesome feature of Terraform!



Quick Fix – OS Not Found Deploying Windows Template with Terraform

During the first plan execution of a new VM based on a Windows Server Core VM Template, my Terraform plan timed out on Guest Customizations. The same plan had worked without issue previously with an existing Windows Template, so I was a little confused as to what had gone wrong. When I checked the console of the cloned VMs in vSphere, I found that it was stuck at the boot screen not able to find the Operating System.

Operating System not found – Obviously having issues booting into the templated disk.

After a little digging around, I came across this post which describes the error being related to the VM Template being configured with EFI Firmware which is now the default for vSphere 6.7 VMs. Upon cloning, Terraform deploys the new VM with a BIOS Firmware resulting in the disk not able to boot.

Checking the VM Template, it did in-fact have EFI set.

An option was to reconfigure the Template and make it default to BIOS, however the Terraform vSphere Provider was updated last year to include an option to set the Firmware on deployment.

In the instance declaration file we can set firmware as shown below

If we set it up such that it reads that value from a variable we only have to configure the efi or bios setting once in the terraform.tfvars files.

In the variables.tf file the variable is set and has a default value of bios set.

Once this was configured, the plan was able to successfully deploy the new Windows Template without issue and Guest Customizations where able to continue.

Terraform Version: 0.11.7