Deploy VMware Cloud Foundation Cloud Builder using the vSphere Terraform Provider

As part of my series on deploying and managing VMware Cloud Foundation using Terraform, this post will focus on deploying the VMware Cloud Foundation Cloud Builder appliance using the vSphere Terraform provider. I’ve used this provider in the past to deploy the NSX Manager appliance.

Check out the other posts on Terraform with VMware Cloud Foundation here:

Deploy Cloud Builder with the vSphere Terraform Provider

As before, you first need to define your provider configuration

# providers.tf
 
terraform {
  required_providers {
    vsphere = {
      source  = "hashicorp/vsphere"
      version = "2.5.1"
    }
  }
}
provider "vsphere" {
  user                 = var.vsphere_user
  password             = var.vsphere_password
  vsphere_server       = var.vsphere_server
  allow_unverified_ssl = true
}

Then we define our variables

# variables.tf
 
# vSphere Infrastructure Details
variable "data_center" { default = "sfo-m01-dc01" }
variable "cluster" { default = "sfo-m01-cl01" }
variable "vds" { default = "sfo-m01-vds01" }
variable "datastore" { default = "vsanDatastore" }
variable "compute_pool" { default = "sfo-m01-cl01" }
variable "compute_host" {default = "sfo01-m01-esx01.sfo.rainpole.io"}
variable "vsphere_server" {default = "sfo-m01-vc01.sfo.rainpole.io"}
 
# vCenter Credential Variables
variable "vsphere_user" {}
variable "vsphere_password" {}
 
# Cloud Builder Deployment
variable "mgmt_pg" { default = "sfo-m01-vds01-pg-mgmt" }
variable "vm_name" { default = "sfo-cb01" }
variable "local_ovf_path" { default = "F:\\binaries\\VMware-Cloud-Builder-4.5.2.0-22223457_OVF10.ova" }
variable "ip0" { default = "172.16.225.66" }
variable "netmask0" { default = "255.255.255.0" }
variable "gateway" { default = "172.16.225.1" }
variable "dns" { default = "172.16.225.4" }
variable "domain" { default = "sfo.rainpole.io" }
variable "ntp" { default = "ntp.sfo.rainpole.io" }
variable "searchpath" { default = "sfo.rainpole.io" }
variable "ADMIN_PASSWORD" { default = "VMw@re1!" }
variable "ROOT_PASSWORD" { default = "VMw@re1!" }
variable "hostname" { default = "sfo-cb01.sfo.rainpole.io" }

Note the vCenter Server credentials in the above variables.tf do not have default values. We will declare these sensitive values in a terraform.tfvars file and add *.tfvars to our .GitIgnore file so they are not synced to our Git repo.

# terraform.tfvars
 
# vSphere Provider Credentials
vsphere_user     = "administrator@vsphere.local"
vsphere_password = "VMw@re1!"

Now that we have all of our variables defined we can define our main.tf to perform the deployment. As part of this, we first need to gather some data from the target vCenter Server, so we know where to deploy the appliance.

# main.tf
 
# Data source for vCenter Datacenter
data "vsphere_datacenter" "datacenter" {
  name = var.data_center
}
 
# Data source for vCenter Cluster
data "vsphere_compute_cluster" "cluster" {
  name          = var.cluster
  datacenter_id = data.vsphere_datacenter.datacenter.id
}
 
# Data source for vCenter Datastore
data "vsphere_datastore" "datastore" {
  name          = var.datastore
  datacenter_id = data.vsphere_datacenter.datacenter.id
}
 
# Data source for vCenter Portgroup
data "vsphere_network" "mgmt" {
  name          = var.mgmt_pg
  datacenter_id = data.vsphere_datacenter.datacenter.id
}
 
# Data source for vCenter Resource Pool. In our case we will use the root resource pool
data "vsphere_resource_pool" "pool" {
  name          = format("%s%s", data.vsphere_compute_cluster.cluster.name, "/Resources")
  datacenter_id = data.vsphere_datacenter.datacenter.id
}
 
# Data source for ESXi host to deploy to
data "vsphere_host" "host" {
  name          = var.compute_host
  datacenter_id = data.vsphere_datacenter.datacenter.id
}
 
# Data source for the OVF to read the required OVF Properties
data "vsphere_ovf_vm_template" "ovfLocal" {
  name             = var.vm_name
  resource_pool_id = data.vsphere_resource_pool.pool.id
  datastore_id     = data.vsphere_datastore.datastore.id
  host_system_id   = data.vsphere_host.host.id
  local_ovf_path   = var.local_ovf_path
  ovf_network_map = {
    "Network 1" = data.vsphere_network.mgmt.id
  }
}
 
# Deployment of VM from Local OVA
resource "vsphere_virtual_machine" "cb01" {
  name                 = var.vm_name
  datacenter_id        = data.vsphere_datacenter.datacenter.id
  datastore_id         = data.vsphere_ovf_vm_template.ovfLocal.datastore_id
  host_system_id       = data.vsphere_ovf_vm_template.ovfLocal.host_system_id
  resource_pool_id     = data.vsphere_ovf_vm_template.ovfLocal.resource_pool_id
  num_cpus             = data.vsphere_ovf_vm_template.ovfLocal.num_cpus
  num_cores_per_socket = data.vsphere_ovf_vm_template.ovfLocal.num_cores_per_socket
  memory               = data.vsphere_ovf_vm_template.ovfLocal.memory
  guest_id             = data.vsphere_ovf_vm_template.ovfLocal.guest_id
  scsi_type            = data.vsphere_ovf_vm_template.ovfLocal.scsi_type
 
  wait_for_guest_net_timeout = 5
 
  ovf_deploy {
    allow_unverified_ssl_cert = true
    local_ovf_path            = var.local_ovf_path
    disk_provisioning         = "thin"
    ovf_network_map   = data.vsphere_ovf_vm_template.ovfLocal.ovf_network_map
 
  }
  vapp {
    properties = {
      "ip0"               = var.ip0,
      "netmask0"          = var.netmask0,
      "gateway"          = var.gateway,
      "dns"             = var.dns,
      "domain"           = var.domain,
      "ntp"              = var.ntp,
      "searchpath"       = var.searchpath,
      "ADMIN_USERNAME"  = "admin",
      "ADMIN_PASSWORD"           = var.ADMIN_PASSWORD,
      "ROOT_PASSWORD"       = var.ROOT_PASSWORD,
      "hostname"           = var.hostname
    }
  }
  lifecycle {
    ignore_changes = [
      #vapp # Enable this to ignore all vapp properties if the plan is re-run
      vapp[0].properties["ADMIN_PASSWORD"],
      vapp[0].properties["ROOT_PASSWORD"],
      host_system_id # Avoids moving the VM back to the host it was deployed to if DRS has relocated it
    ]
  }
}

Now we can run the following to initialise Terraform and the required vSphere provider

terraform init 

One the provider is initialised, we can then create a terraform plan to ensure our configuration is valid.

terraform plan -out=DeployCB

Now that we have a valid configuration we can apply our plan to deploy the Cloud Builder appliance.

terraform apply DeployCB

One thought on “Deploy VMware Cloud Foundation Cloud Builder using the vSphere Terraform Provider

Leave a comment