Run WordPress on Ubuntu using Terraform, Ansible and Docker

Using Terraform to provision the VM

Once I had a VM template in Vsphere, I could use Terraform to create a VM. Managing VMs this way has many advantages:

  • Allows an arbitrary number of identical VMs to be quickly provisioned.
  • VMs can be destroyed just as quickly. This is especially useful when practicing something new or developing anything related to Infrastructure as Code.
  • Resources can be modified as code. For example, adding memory or another vCPU to a VM is as simple as modifying code and applying the change.
  • VMs can be re-created the same way eliminating the ‘snowflake’ effect of doing it manually.
  • The template itself can be patched and updated as needed.
  • Changes to the VMs or any other infrastructure can be predicted and planned using ‘dry-run’ techniques. For example, Terraform has a ‘plan’ mode that tells you what will be done before any action it taken.
  • Since the definition of infrastructure is now code, it can be linted, tested and version-controlled.

To get started, I needed to declare the use of the Vsphere provider. Here’s the contents of the main.tf file:

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
}

Next, I created a separate file for variables. These variable are common to my environment, and not specific to any VM. I called this file variables.tf.

variable "vsphere_user"{
    type = string
    default = "***************"
}

variable "vsphere_password"{
    type = string
    default = "***************"
}

variable "vsphere_server"{
    type = string
    default = "***************"
}

variable "vsphere_datacenter"{
    type = string
    default = "***************"
}

variable "vsphere_datastore"{
    type = string
    default = "***************"
}

variable "vsphere_vm_network"{
    type = string
    default = "***************"
}

variable "vsphere_cluster" {
  type = string
    default = "***************"
}

variable "network_domain"{
    type = string
    default = "***************"
}

variable "dns_servers"{
    type = list(string)
    default = "***************"
}

variable "default_gateway" {
    type = string
    default = "***************"
}

variable "netmask" {
    type = number
    default = 24  
}

Note that in the example above, it’s not advisable to store credentials in source code. These should be stored in the environment or in a secret store such as Hashicorp Vault. The above is only used for this oversimplified example.

The last piece of the Terraform puzzle was to write a block of code to create and manage the actual VM:

data "vsphere_datacenter" "dc" {
  name = "${var.vsphere_datacenter}"
}

data "vsphere_datastore" "datastore" {
  name          = "${var.vsphere_datastore}"
  datacenter_id = "${data.vsphere_datacenter.dc.id}"
}

data "vsphere_compute_cluster" "cluster" {
  name          = "${var.vsphere_cluster}"
  datacenter_id = "${data.vsphere_datacenter.dc.id}"
}

data "vsphere_network" "network" {
  name          = "${var.vsphere_vm_network}"
  datacenter_id = "${data.vsphere_datacenter.dc.id}"
}

data "vsphere_virtual_machine" "template" {
  name          = "tpl-ubuntu-18.04"
  datacenter_id = "${data.vsphere_datacenter.dc.id}"
}

resource "vsphere_virtual_machine" "vm" {
  name             = "wordpress.test.local"
  resource_pool_id = "${data.vsphere_compute_cluster.cluster.resource_pool_id}"
  datastore_id     = "${data.vsphere_datastore.datastore.id}"

  num_cpus = 2
  memory   = 4096
  guest_id = "${data.vsphere_virtual_machine.template.guest_id}"

  scsi_type = "${data.vsphere_virtual_machine.template.scsi_type}"
  
  network_interface {
    network_id = "${data.vsphere_network.network.id}"
    adapter_type = "${data.vsphere_virtual_machine.template.network_interface_types[0]}"
  }

  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}"

    customize {
      linux_options {
        host_name = "wordpress"
        domain    = "${var.network_domain}"
      }

      network_interface {
        ipv4_address = "10.0.1.38"
        ipv4_netmask = "${var.netmask}"
      }

      ipv4_gateway = "${var.default_gateway}"
      dns_server_list = "${var.dns_servers}"
    }
  }
}

Note that many of the inputs to this file are references to the contents of the variables.tf file discussed above. Note also that the template name corresponds to the VM template for the Ubuntu VM template I created in the previous step.

To create a VM from all this, it is minimally necessary to run just two Terraform commands:

terraform plan
terraform apply

I wound up with a VM that was cloned from my template:

Pages: 1 2 3 4 5 6


Comments

One response to “Run WordPress on Ubuntu using Terraform, Ansible and Docker”

  1. Great content! Keep up the good work!

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.