Vmware Terraform

Using Terraform with VMware Vsphere

VMware is one of the officially supported provider of Terraform. We can reap all the benefits that we can use Terraform for using Terraform to manage infrastructure in AWS, Azure GCP or other cloud provider. AWS and other cloud platforms might have a lot of constructs as a prerequisite to get it working. However we just need few information prior to launching a virtual machine in VMWare Vsphere. Following is the basic construct of how the files in a typical terrafrom project are gouped.

  • main.tf - contains the main section for provisioning resources using terraform
  • variables.tf - contians variable for use in main.tf
  • output.tf - contains output that can be displayed at the end of resource provisioning
  • data.tf - contains data to be used for provisioning resources
  • terraform.tfvars - contains values for the variables defined in variables.tf file

Creation of a virtual machine using template in VMware Vsphere

provider "vsphere" {
  user                 = var.vsphere_user
  password             = var.vsphere_password
  vsphere_server       = var.vsphere_server
  allow_unverified_ssl = true
  vim_keep_alive       = 30
}
data "vsphere_datacenter" "dc" {
  name = "datacenter.nepal.np"
}

data "vsphere_datastore" "datastore" {
  name          = "${var.vsphere_datastore}.storage.datacenter.nepal.np"
  datacenter_id = data.vsphere_datacenter.dc.id
}

data "vsphere_resource_pool" "pool" {
  name          = var.vsphere_resourcepool
  datacenter_id = data.vsphere_datacenter.dc.id
}

data "vsphere_network" "nw" {
  name          = var.vsphere_network
  datacenter_id = data.vsphere_datacenter.dc.id
}

data "vsphere_virtual_machine" "template" {
  name          = var.vsphere_template
  datacenter_id = data.vsphere_datacenter.dc.id

}
resource "vsphere_virtual_machine" "vm" {
  count = 50
  name             = "${var.vshpere_vmname}${5+count.index}"
  resource_pool_id = data.vsphere_resource_pool.pool.id
  datastore_id     = data.vsphere_datastore.datastore.id
  num_cpus         = var.vsphere_vm_cpu
  memory           = var.vsphere_vm_ram
  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.nw.id
    adapter_type = data.vsphere_virtual_machine.template.network_interface_types[0]
  }

  disk {
    label            = "disk0"
    size             = data.vsphere_virtual_machine.template.disks.0.size
    thin_provisioned = data.vsphere_virtual_machine.template.disks.0.thin_provisioned
    eagerly_scrub = data.vsphere_virtual_machine.template.disks.0.eagerly_scrub
  }
  clone {
    template_uuid = data.vsphere_virtual_machine.template.id
    timeout       = 30

    customize {
      windows_options {
        computer_name = "TF-${5 + count.index}"
        admin_password = "changeme"
        auto_logon = true
        auto_logon_count = 1
      }
      network_interface {
        ipv4_address = "10.15.11.${5 + count.index}"
        ipv4_netmask = 24
      }
      ipv4_gateway    = "10.15.11.1"
      dns_server_list = ["10.10.30.2"]
    }
  }
}

auto_logon and auto_logon_count values are important from sysprep prespective when launching new instances in VMware. We can avoid the count parameter. However it has been kept to facilitate the creation of multiple instances if needed.

variable file in Terraform

We have used a lot of variables in main.tf file. The variables.tf holds the definitions for the variables used on the main.tf file.

variable "vsphere_user" {
  default   = ""
  sensitive = true
}
variable "vsphere_password" {
  default   = ""
  sensitive = true
}
variable "vsphere_server" {
  default     = ""
  description = "address of the vsphere server"
}
variable "vsphere_template" {
  default     = ""
  type        = string
  description = "name of the vsphere template"
}
variable "vsphere_network" {
  type        = string
  description = "name of the vsphere network"
}
variable "vsphere_resourcepool" {
  type        = string
  description = "name of vsphere resource pool"
}
variable "vsphere_datastore" {
  type        = string
  description = "name of vsphere datastore"
}
variable "vshpere_vmname" {
  type        = string
  description = "name of vsphere instance"
}
variable "vsphere_vm_ram" {
  type        = number
  description = "vsphere instance ram"
}
variable "vsphere_vm_cpu" {
  type        = number
  description = "vsphere instance cpu"
}

Much of the variables used in main.tf are defined on variables.tf file. Some of the data values that are used in the main.tf are obtained from querying the template we created earlier to use with this deployment. Template in VMware can be considered equivalent to ami in the aws world and azure images in the azure world. We can also use another Hashicorp tool Packer to create templates or use the normal VMware ISO installation and then convert it to template. Here are certain variables whose values need to be passed for running terraform script successfully. These values containing username, password and vcenter IP address are supplied on terraform.tfvars file.

vsphere_user         = "vcenteruser"
vsphere_password     = "Iamnotasecretanymore"
vsphere_server       = "vcenter"
vsphere_template     = "Windows2016"
vsphere_resourcepool = "Performance"
vsphere_network      = "10.15.11.0/24"
vsphere_datastore    = "san19vol80"
vshpere_vmname       = "Windows_2016_10.15.11."
vsphere_vm_ram       = 4096
vsphere_vm_cpu       = 2

We have set the IP address of the service statically. However in cases where the IP address is dynamic. We can use the output.tf to get the results of running terraform script. This example has the IP address assigned to the machine as the output displayed when the command executes successfully.

output "Instance_ip_addresses" {
    value = vsphere_virtual_machine.vm.*.guest_ip_addresses
    description = "IP address of virtual machines"
}

If it is the first time we are running terrafrom script. We might also need to download the provisioner need to create resources in vcenter. We can achieve this using the following command. If it is the second time we can escape this part.

terrafrom init

Equipped with all the configuration files needed we can validate our configuration files using

terraform validate

Create a plan for execution of the terraform script we just created

terraform plan

Apply the configuration to the vcenter and create the resource using the command

terraform apply

Once we are done with our testing we can destroy the resources created using the command

terraform destroy