I recently posted about using Terraform, vCenter and Chef, and promised a follow up about extending the Terraform plans to work with Windows and multiple Virtual Machines. Here is part two that will continue to build off of this plan: https://gist.github.com/jjasghar/f061f493ad8f631a6d4b5b5085c7cb35
Windows
Open up the following link to show off the .diff
that has Windows working with the above Terraform plan.
https://gist.github.com/jjasghar/dbd7348240f23a26a31cd7a02dcb4267
If you don’t know how to read diff
s, the green or +
lines are lines I’ve added, while the red or -
are lines I have removed.
With a successful Linux VM build, the next natural progression is to get Windows working with the same base plan. There is some prep work that is required down this path and I chose the one that made the most sense for me. You’ll need to figure out what is the correct path for you here, and it will probably require talking to your VMware Administrators and Windows Licensing people to make sure you’re in compliance with your environments rules.
I don’t use Customization Specs very heavily so I’m going to move past it. If you do use them, you’ll need to first remove this line, that skips customization specs and just request the template in it’s base form.
+ skip_customization = true
If you don’t have this line, and no customization spec, you’ll find that Terraform sysprep
s the machine, and can wipe out WinRM settings. For me, this was a gotcha that caused a long delay in figuring out how to get Terraform to request a Windows VM. These settings are required for Chef to be bootstrapped into your Windows VM, you need to enable and set some WinRM settings. Taken from the winrm-cli README, you need to set the following at a PowerShell prompt:
winrm quickconfig # say y here ;) winrm set winrm/config/service/Auth '@{Basic="true"}' winrm set winrm/config/service '@{AllowUnencrypted="true"}' winrm set winrm/config/winrs '@{MaxMemoryPerShellMB="1024"}'
Take either a snapshot of the Virtual Machine, or create a template out of it, and then change this line to that name.
+ template = "template-windows2012R2"
The next thing to take notice of is the diff
of the variables.tf
. Scroll down to the next file and look at Lines 16 to 25. You’ll see the changes that are required to talk to the template I created.
- # Default to SSH - connection_type = "ssh" + # Default to winrm + connection_type = "winrm" # User to connect to the server - connection_user = "admini" + connection_user = "Administrator" # Password to connect to the server - connection_password = "admini" + connection_password = "Admini@"
Notice the WinRM change, for the connection_type
the user of Administrator
, and my super secure Admini@
local administrator password. If you scroll back up to Line 55 in the diff
you’ll notice one more setting I set for the connection.
+ https = false
For the settings for WinRM above, we connect over http
and by default Terraform connects over https
. This option forces the correct protocol.
Just to make sure this is clear, the final major change is the middle stanza of lines 22 to 38.
- # my template is broken, but as you can see here's some pre-chef work done :) - provisioner "remote-exec" { - inline = [ - "sudo rm /var/lib/dpkg/lock", - "sudo dpkg --configure -a", - "sudo apt-get install -f", - "sudo apt autoremove -y", - # This was interesting here, i needed to add a host to /etc/hosts, this injects the sudo password, then tee's the /etc/hosts - "echo admini | sudo -S echo '10.0.0.15 chef chef.tirefi.re' | sudo tee -a /etc/hosts" - ] - connection { - type = "${var.connection_thingys.["connection_type"]}" - user = "${var.connection_thingys.["connection_user"]}" - password = "${var.connection_thingys.["connection_password"]}" - } - } -
Not having specific Ubuntu available commands and bash
on my Windows VM, these commands would ultimately fail on run. I am pretty confident that you can run PowerShell
commands instead of bash
here, though to be honest I haven’t tried it. Reading the remote-exec
docs it seems that The remote-exec provisioner supports both ssh and winrm type connections
which at least imply it can run whatever commands you type there.
Multiple machines
Now that we’ve walked through creating a virtual machine of both Linux and Windows based operating systems, we need to figure out how to make multiple machines spin up at once. This was surprisingly easy as soon as the base understanding of the .tf
plans are put together. Lets take a look at this diff to show how to extend the base plan to 3 virtual machines.
Looking first at the variables.tf
diff, you’ll notice we added three lines for a default number of 3 and called it count
. This should be pretty straight forward, and if you needed to override it, you know how to from my previous post. Because we don’t know how many nodes we want, we have to remove line 18 and 19 so we don’t hard code the default name now.
- # A default node name - node_name_default = "terraform-1"
Scroll back up to the main diff
file, you’ll see that if you give the vsphere_virtual_machine
resource a count
it will create that many machines, as we do on line 8. There are a lot of examples on how to name the machines, I chose from:
variable "count" { default = 2 } resource "aws_instance" "web" { # ... count = "${var.count}" # Tag the instance with a counter starting at 1, ie. web-001 tags { Name = "${format("web-%03d", count.index + 1)}" } }
…and edited it to my liking on line 12. This way, my machines will now be called terraform-0X
where X
is the number of the machine count we created. Finally, line 20 and 21 create the node objects on the Chef Server with the same name of the machine inside vCenter, which helps keep things in line.
Clean up
If you’ve played with these Terraform plans, the easiest way is to run terraform destroy
to nuke the machines from vCenter. It won’t delete the node objects from the Chef Server. That’s by design and the reason why we have the recreate_client
line set to true
.
I hope this helps bootstrap your use cases of Terraform, vCenter, and Chef, and makes your path to success that much easier. Starting off from nothing with these three technologies can be hard. Start with these simple examples and you’ll find yourself able to do more advanced things before you know it.