Following on from this post covering how to deploy vSphere virtual machines using Terraform, I thought I’d take a look at how I could deploy vCenter itself, with the aim of speeding up vCenter deployments in my home lab. The objective here was to have Terraform deploy a new vCenter appliance onto my ESXi host, then carry out some initial configuration of vCenter using the Terraform vCenter provider.
Deploying vCenter using the CLI
Most commonly, vCenter is installed using the graphical UI, which can take a little time to step though the configuration screens. However, there is also a command line install option – where the configuration can be passed to the installer in the form of a configuration file, greatly speeding up the time it takes to deploy. This command line install tool is what will make it possible to use Terraform to help us deploy vCenter – more on this later – first I’ll cover how to deploy vCenter using the CLI.
The CLI installer is documented here, and is recommended reading to better understand how the CLI installer functions. For this example, I created a configuration file, called vctemplate.json, which contains the information needed to deploy the appliance, including the ESXi hostname where the appliance will be deployed, the VM name, passwords, the datastore, and the networking configuration. My example file looks like this:
{ "__version": "2.13.0", "__comments": "Sample template to deploy a vCenter Server Appliance with an embedded Platform Services Controller on an ESXi host.", "new_vcsa": { "esxi": { "hostname": "esxihostname", "username": "root", "password": "Pa55w0rd!!", "deployment_network": "VM Network", "datastore": "DATASTORE-01" }, "appliance": { "__comments": [ "You must provide the 'deployment_option' key with a value, which will affect the VCSA's configuration parameters, such as the VCSA's number of vCPUs, the memory size, the storage size, and the maximum numbers of ESXi hosts and VMs which can be managed. For a list of acceptable values, run the supported deployment sizes help, i.e. vcsa-deploy --supported-deployment-sizes" ], "thin_disk_mode": true, "deployment_option": "small", "name": "vcenter" }, "network": { "ip_family": "ipv4", "mode": "static", "ip": "172.16.1.100", "dns_servers": [ "172.16.1.110" ], "prefix": "24", "gateway": "172.16.1.1", "system_name": "vcsa.test.local" }, "os": { "password": "Pa55w0rd999", "ntp_servers": "time.nist.gov", "ssh_enable": true }, "sso": { "password": "Pa55w0rd999!", "domain_name": "vsphere.local" } }, "ceip": { "settings": { "ceip_enabled": false } } }
Before going any further, we need to have downloaded the vCenter ISO, and unpackaged it to a local folder. Once the executables are accessible, we can run the following command to deploy the appliance, passing it the location of the configuration file as a parameter:
E:/VMware-VCSA-all-6.7.0-8217866/vcsa-cli-installer/win32/vcsa-deploy.exe install --accept-eula --acknowledge-ceip --terse --no-ssl-certificate-verification vctemplate.json
This command will deploy a new vCenter appliance using the configuration detailed in the vctemplate.json file.
Deploying vCenter Using Terraform
So now we have a working way of deploying vCenter using the CLI, we can work this into a Terraform plan. I’ve broken the plan down into two modules, one to deploy the vCenter appliance, and the other to carry out some vCenter configuration including creating a datacenter, and some inventory folders. My terraform plans directory structure looks like this:
I’ll go into each of these in turn. The main.tf file in the ‘vcbuild’ module looks like this:
variable "vcentername" { description = "vcenter name" default = "myvcenter" } variable "vcpassword" { description = "vcpassword" default = "Pa55w0rd123!!" } variable "esxipassword" { description = "esxi password" default = "Pa55w0rd999!" } variable "vcip" { description = "ip address" default = "192.168.1.100" } variable "dnsserver" { description = "dns server" default = "192.168.1.101" } variable "ipprefix" { description = "prefix" default = "24" } variable "gateway" { description = "gateway" default = "192.168.1.1" } variable "vchostname" { description = "vc hostname" default = "mycenter.test.local" } data "template_file" "task" { template = "${file("c:\files\vcsatemplate.json")}" vars { vcname = "${var.vcentername}" esxipassword = "${var.esxipassword}" vcpassword = "${var.vcpassword}" vchostname = "${var.vchostname}" ipaddress = "${var.vcip}" dnsserver = "${var.dnsserver}" ipprefix = "${var.ipprefix}" gateway = "${var.gateway}" } } resource "local_file" "foo" { content = "${data.template_file.task.rendered}" filename = "c:\files\vctemplate.json" } resource "null_resource" "vc" { provisioner "local-exec" { command = "c:\files\VMware-VCSA-all-6.7.0-8217866/vcsa-cli-installer/win32/vcsa-deploy.exe install --accept-eula --acknowledge-ceip --terse --no-ssl-certificate-verification c:\files\vctemplate.json" } }
This module/plan runs the CLI command to deploy vCenter, using an answer file – however we’re able to use variables defined here to overwrite the values in the imported vcsatemplate.json file. Using Terraform, we are able to import the file, replace the values using the variables here, before exporting the .json file and using it to deploy vCenter.
Once this module has run, the vcconfig module kicks in to configure vCenter itself. The vcconfig modules main.tf file looks like this:
variable "datacenter" { default = "dc" } variable "vcpassword" { description = "vcpassword" default = "Pa55w0rd999!!!" } variable "network_interfaces" { default = [ "vmnic0", "vmnic1", "vmnic2", "vmnic3", ] } variable "vchostname" { description = "vc host" default = "vcsa.test.local" } provider "vsphere" { user = "administrator@vsphere.local" password = "${var.vcpassword}" vsphere_server = "${var.vchostname}" # If you have a self-signed cert allow_unverified_ssl = true } resource "vsphere_datacenter" "dc" { name = "${var.datacenter}" } data "vsphere_datacenter" "dc" { name = "${var.datacenter}" depends_on = ["vsphere_datacenter.dc"] } resource "vsphere_compute_cluster" "compute_cluster" { name = "Compute" datacenter_id = "${data.vsphere_datacenter.dc.id}" drs_enabled = true drs_automation_level = "fullyAutomated" ha_enabled = true } resource "vsphere_compute_cluster" "management_cluster" { name = "Management" datacenter_id = "${data.vsphere_datacenter.dc.id}" drs_enabled = true drs_automation_level = "fullyAutomated" ha_enabled = true } resource "vsphere_folder" "infrafolder" { path = "Infrastructure" type = "vm" datacenter_id = "${data.vsphere_datacenter.dc.id}" } resource "vsphere_folder" "templatesfolder" { path = "Templates" type = "vm" datacenter_id = "${data.vsphere_datacenter.dc.id}" } resource "vsphere_distributed_virtual_switch" "dvs" { name = "mydatacenter-dvs" datacenter_id = "${data.vsphere_datacenter.dc.id}" uplinks = ["uplink1", "uplink2", "uplink3", "uplink4"] active_uplinks = ["uplink1", "uplink2"] standby_uplinks = ["uplink3", "uplink4"] }
This module/plan connects to the newly deployed vCenter, and creates a bunch of vCenter resources including a DataCenter, dvSwitch and some inventory folders. Using the Terraform vSphere provider in this way, we can get a mostly configured vCenter instance up and running very quickly. The parent main.tf file pulls it all together – it is here that we tell Terraform to run the modules detailed above:
module "vcbuild" { source = "modules/vcbuild" } module "vcconfig" { source = "modules/vcconfig" }
Now, this was just a quick proof of concept plan to show how you can deploy and configure a vCenter appliance using Terraform. If using in a production setting I would further develop the Terraform plans to dynamically generate passwords, and variables would be defined and populated in a .tfvars. When testing this plan, I could have a new vCenter, with some resources defined, up and running in around 15 minutes which is a great result – and certainly beats deploying manually in my home lab!