🛠️ Terraform + vSphere = A Match Made in Cloud Heaven ☁️ Link to heading
Terraform is a powerhouse for Infrastructure as Code (IaC) that lets you automate your VM provisioning process on VMware vSphere. Whether you’re a seasoned pro or just dipping your toes into automation, this guide will take you step by step through the process of using Terraform with vSphere to get your virtual machines (VMs) up and running in no time!
🔥 Prerequisites Link to heading
Before you dive in, make sure you have the following:
- 🌍 A running vSphere environment with access to vCenter.
- ⚙️ Terraform installed on your machine (You can grab it here).
- 🧑💻 The necessary permissions to create and manage VMs.
- 🖼️ An existing VM template or clone for deployment (I have prebuilt a golden image).
(https://github.com/vmware-samples/packer-examples-for-vsphere/tree/develop/terraform/vsphere-role) Is a good place to start, this repo has the get starting templates to build templates with Packer. I have linked the folder which adds the correct roles to the user in vSphere as its quite lengthy doing it manually.
I had used this as a guide to give my Terraform vSphere user the least privilege roles.
🛠️ Step 1: Build the Terraform Image from a Clone Link to heading
Let’s kick things off by creating a VM from an existing clone in vSphere. Why a clone? It ensures consistency and speeds up deployment – plus, Terraform does all the hard work for you! 🙌
1.1. Terraform Configuration Link to heading
Create a file called main.tf
with the following structure:
provider "vsphere" {
vsphere_server = var.vsphere_server
user = var.vsphere_username
password = var.vsphere_password
allow_unverified_ssl = var.vsphere_insecure
}
data "vsphere_datacenter" "datacenter" {
name = var.vsphere_datacenter
}
data "vsphere_network" "network" {
name = var.vsphere_network
datacenter_id = data.vsphere_datacenter.datacenter.id
}
data "vsphere_compute_cluster" "cluster" {
name = var.vsphere_cluster
datacenter_id = data.vsphere_datacenter.datacenter.id
}
data "vsphere_resource_pool" "pool" {
name = format("%s%s", data.vsphere_compute_cluster.cluster.name, "/Resources")
datacenter_id = data.vsphere_datacenter.datacenter.id
}
data "vsphere_datastore" "datastore" {
name = var.vsphere_datastore
datacenter_id = data.vsphere_datacenter.datacenter.id
}
data "vsphere_virtual_machine" "template" {
name = var.vsphere_template
datacenter_id = data.vsphere_datacenter.datacenter.id
}
resource "vsphere_virtual_machine" "vm" {
name = var.vm_name
folder = var.vsphere_folder
num_cpus = var.vm_cpus
memory = var.vm_memory
firmware = var.vm_firmware
efi_secure_boot_enabled = var.vm_efi_secure_boot_enabled
guest_id = data.vsphere_virtual_machine.template.guest_id
datastore_id = data.vsphere_datastore.datastore.id
resource_pool_id = data.vsphere_resource_pool.pool.id
network_interface {
network_id = data.vsphere_network.network.id
}
disk {
label = "disk0"
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
}
clone {
template_uuid = data.vsphere_virtual_machine.template.id
}
lifecycle {
ignore_changes = [
clone[0].template_uuid,
]
}
extra_config = {
"guestinfo.metadata" = base64encode(file("${path.module}/metadata.yml"))
"guestinfo.metadata.encoding" = "base64"
"guestinfo.userdata" = base64encode(file("${path.module}/userdata.yml"))
"guestinfo.userdata.encoding" = "base64"
}
}
In this config, you’re telling Terraform to create a VM based on a template and applying some basic customisations. 🎨
⚡ Step 1.2: Add The Variables Link to heading
Add a variables.tfvars
file:
The Terraform configuration file for managing infrastructure with vSphere. It defines a set of variables that will be used to configure various aspects of a virtual machine (VM) and vSphere infrastructure.
##################################################################################
# VARIABLES
##################################################################################
# Credentials
vsphere_server = "vcenter_IP"
vsphere_username = "administrator@vsphere.local"
vsphere_password = "vcenter_password"
vsphere_insecure = true
# vSphere Settings
vsphere_datacenter = "Datacenter"
vsphere_cluster = "cluster"
vsphere_datastore = "cluster"
vsphere_folder = "folder"
vsphere_network = "network"
vsphere_template = "Debian 12 Template"
# Virtual Machines Settings
vm_name = "golden-image-staging"
vm_cpus = 8
vm_memory = 4096
vm_firmware = "efi"
vm_efi_secure_boot_enabled = true
⚡ Step 2: Initialize Terraform Link to heading
Before you get rolling, you’ll need to initialise your Terraform project.
Run this command to get things set up:
terraform init
This command does the following:
- Downloads the necessary providers.
- Prepares the backend for storing state.
- Validates your configuration files and ensures there are no glaring issues. ✅
🎯 Step 3: Plan and Build the VM Link to heading
Time to see the magic unfold! First, let’s run a dry-run to check what Terraform will do:
terraform plan
If everything looks good, it’s showtime! Apply the changes and let Terraform work its charm:
terraform apply
You’ll be prompted to confirm. Type yes
and hit Enter. 🎉
After the magic happens, your new VM will be ready to go in vSphere! 🚀
✨ Creating a New VM Without Editing an Existing One Link to heading
I only note this part since I had a slight hiccup as I had edited/replaced the VM I had just built!
By default, Terraform keeps track of all your resources in a file called terraform.tfstate
. If you reapply, it will modify existing resources, which can be a little… risky! 😬
4.1. Use a Different Terraform State File Link to heading
To avoid modifying your current VM, you can use a fresh state file by running this command:
terraform apply -state=new_vm.tfstate
This tells Terraform to treat the new VM as a new and independent resource, giving you peace of mind. 😌
🏁 Conclusion Link to heading
Boom! You’re now a Terraform wizard in vSphere. 🧙♂️ By using Terraform’s powerful state management and automation, you can streamline your VM creation process, ensuring consistency and minimising human error. No more manual VM juggling—let Terraform handle the heavy lifting!
Afterthoughts Link to heading
I want to secure the variables file either by using .env file, setting environment variables on the host or using Hashicorp vault.
At the present time as I am rebuilding my SOC SIEM Lab I hope to come back and add further security enhancements.!