Terraform - The Basics
This post is about using Terraform to build up and tear down VMware VMs. I've used PowerCLI for various operations in the past but Terraform is broader in that you can use it with Amazon, Azure i.e. more than just VMware. The full list is here:
https://www.terraform.io/docs/providers/index.html
Now, I doubt the options will go as deep as PowerCLI but having a common tool you can use across all these platforms allows a team to develop a standardised approach and limit the use of different tools for different platforms for common tasks.
This article focuses on VMware as it gives you a chance to test this in a lab environment. You can use Terraform to work with more than VMs too - port groups, datastores, tags, snapshots etc!
So, let's get started and download the latest version of Terraform from the link below:
https://www.terraform.io/downloads.html
I've grabbed the 64-bit Windows edition and extracted the contents to a folder on my PC. All the zip contains is a single EXE file! How's that for light?! You can put this file in your PATH so you can invoke it form anywhere or just open a command prompt and change into that directory and you're ready to go. I'd recommend Notepad ++ or similar as we'll be working with a few text files that feed Terraform the neccessary instructions about what you want it to do.
Ok, you see that build.tf file - this is a very basic intro as normally you split things out differently but to get started this will work fine. Create a new text file called "build.tf" in the same folder as Terraform to contain the following:
provider "vsphere" {
user = "${var.vsphere_user}"
password = "${var.vsphere_password}"
vsphere_server = "${var.vsphere_server}"
# if you have a self-signed cert
allow_unverified_ssl = true
}
variable "vsphere_user" {
default = "administrator@vsphere.local"
}
variable "vsphere_password" {
default = "YOUR PASSWORD HERE"
}
variable "vsphere_server" {
default = "labvc.lab.local"
}
data "vsphere_datacenter" "dc" {
name = "Labdc"
}
data "vsphere_datastore" "datastore" {
name = "Datastore0"
datacenter_id = "${data.vsphere_datacenter.dc.id}"
}
data "vsphere_resource_pool" "pool" {
name = "Labcl/Resources"
datacenter_id = "${data.vsphere_datacenter.dc.id}"
}
data "vsphere_network" "network" {
name = "VM Network"
datacenter_id = "${data.vsphere_datacenter.dc.id}"
}
resource "vsphere_virtual_machine" "vm" {
name = "terraform-test"
resource_pool_id = "${data.vsphere_resource_pool.pool.id}"
datastore_id = "${data.vsphere_datastore.datastore.id}"
num_cpus = 2
memory = 1024
guest_id = "other3xLinux64Guest"
wait_for_guest_net_timeout = 0
network_interface {
network_id = "${data.vsphere_network.network.id}"
}
disk {
label = "disk0"
size = 20
}
}
You'll need to edit the script to match your environment, there are 3 variables:
and 4 data fields:
Update these 7 fields above, otherwise you'll get errors. Yes, you can use Datastore clusters and get all fancy but for now we're picking a single VM on a fixed environment!
Now you're ready to initialise Terraform and create your first VM. Run the command "Terraform init" and it will download the vSphere provider for you - internet access is a requirement here:user = "${var.vsphere_user}"
password = "${var.vsphere_password}"
vsphere_server = "${var.vsphere_server}"
# if you have a self-signed cert
allow_unverified_ssl = true
}
variable "vsphere_user" {
default = "administrator@vsphere.local"
}
variable "vsphere_password" {
default = "YOUR PASSWORD HERE"
}
variable "vsphere_server" {
default = "labvc.lab.local"
}
data "vsphere_datacenter" "dc" {
name = "Labdc"
}
data "vsphere_datastore" "datastore" {
name = "Datastore0"
datacenter_id = "${data.vsphere_datacenter.dc.id}"
}
data "vsphere_resource_pool" "pool" {
name = "Labcl/Resources"
datacenter_id = "${data.vsphere_datacenter.dc.id}"
}
data "vsphere_network" "network" {
name = "VM Network"
datacenter_id = "${data.vsphere_datacenter.dc.id}"
}
resource "vsphere_virtual_machine" "vm" {
name = "terraform-test"
resource_pool_id = "${data.vsphere_resource_pool.pool.id}"
datastore_id = "${data.vsphere_datastore.datastore.id}"
num_cpus = 2
memory = 1024
guest_id = "other3xLinux64Guest"
wait_for_guest_net_timeout = 0
network_interface {
network_id = "${data.vsphere_network.network.id}"
}
disk {
label = "disk0"
size = 20
}
}
You'll need to edit the script to match your environment, there are 3 variables:
- vsphere_user (use a UPN for this - e.g. user@domain.com)
- vsphere_password
- vsphere_server
and 4 data fields:
- vsphere_datacenter
- vsphere_datastore
- vsphere_resource_pool
- vsphere_network
Update these 7 fields above, otherwise you'll get errors. Yes, you can use Datastore clusters and get all fancy but for now we're picking a single VM on a fixed environment!
Now run the command "Terraform plan" and you will see the following:
Truncated here to save space........
It shows it's going to add 1 VM. Now we're ready to apply the change:
Enter the command "Terraform apply" and enter "yes" to the prompt:
Truncated here to save space........
Truncated here to save space........
This is just to demonstrate an API call to create a VM with Terraform works and it only took you what, 10 minutes to set up?!!
If we check VMware we'll see the following:
The VM has been created and powered on.
The code used here is taken from the example usage in this URL:
https://www.terraform.io/docs/providers/vsphere/index.html
If you try to run it raw you'll get hit with missing variables - these are the user/password/vcenter variable fields I've added into my code above.
Now we're ready to tear back down the VM we've created. If you have a quick look at the Terraform folder you'll see it has a new file and folder in it:
The terraform.tfstate file you can open to see it's tracking what we've just built. We just need to execute the following command "Terraform destroy", it shows this will destro 1 VM, Enter "yes" to confirm:
This trigger the following tasks in vCenter:
If you reload terraform.tfstate you'll see the data has shrunk and the VM it previously recorded has been removed which reflects the current state.
So what's the big deal with creating a single VM with a script? Well, it's repeatable, you can create 100's of VMs this way, over and over again, build them up and tear them down. If your Devs update a template daily, this allows them to update a platform overnight to run the new code. This necessitates the use of VMs as essentially stateless however so config files and databases are held off those VMs.
Have a look at the following book for a good read about DevOps that is presented as story of a company trying to move to DevOps but meeting resistance along the way:
The Phoenix Project
https://www.amazon.co.uk/Phoenix-Project-DevOps-Helping-Business-ebook/dp/B00AZRBLHO
This is an older book based around a manufacturing plant faced with imminent closure in 3 months unless they improve their productivity:
The Goal
https://www.amazon.co.uk/Goal-Process-Ongoing-Improvement-ebook/dp/B002LHRM2O
Both are easily the best business reads I've enjoyed in recent years, well worth checking out!
We'll leave it there. In my next post I'll show you how to split up the build.tf file in a better way so you can align more with a DevOps approach.