Using Vagrant for Windows VMs provisioning

Using Vagrant for creating Consul cluster on Linux probably was fun. But what about Windows hosts? Believe it or not, but more than half of developers are actually using Windows, so for most of the folks seeing how Vagrant creates Linux VMs is pretty useless.

However, you can create and provision Windows VMs with Vagrant with little to no problem. In fact, Windows support has been around for years. But there’re some things to keep in mind though.

Things to keep in mind

Licensing

Because it’s not particularly free OS, one cannot just pick random Windows box and put it into production. You can find something in evaluation mode to experiment on, or create your own box, but at some point you’ll need to take care of Windows activation.

Remoting into VM

Connecting to Windows VM via vagrant ssh is doable, but not without SSH server installed onto guest OS. vagrant powershell on the other hand is more Windows friendly mean of remoting to guest OS. But even though PowerShell works on Linux now, the piece responsible for remote connections is not quite there yet, so unless you’re using Windows host OS, this command is not for you. Surprisingly, vagrant rdp – remote desktop protocol client – is the only more or less cross platform (Linux, Mac) way of getting into Windows guest OS.

Performance

Unless Windows box creator indicated that VM should be created with doubled size of CPU cores and memory, you’ll have to do that by yourself.

Provisioning

Provisioning should be done in PowerShell, hurrah! Don’t get me wrong, I used to hate PowerShell, but spending so much time with it gave me some sort of Stockholm syndrome, so now I think it’s quite OK. Another thing is that Vagrant communicates to Windows guest OS via WinRM, so again, unless box creator opened WinRM ports and configured Vagrant communicator to use them (config.vm.communicator = "winrm") you’ll need to do it by yourself in Vagrantfile.

Plan for today

We still have a cluster of three Linux hosts with Consul agents on them. What about adding the fourth one on Windows? That should be easy.

Step 0. Creating blank Windows VM

I found mwrock/Windows2016 evaluation box to be reasonably well maintained, so I’ll use it for today. We can start with configuring a standalone Consul Windows VM and when it’s done we can merge it with the rest of the cluster.

As with Linux VMs, vagrant init mwrock/windows2016 --minimal will produce pretty standard Vagrantfile:

vagrant up on the other hand will fetch 5 holy gigs of Windows box and after a few minutes of meditation on Microsoft masterpiece will end up with running Windows Server 2016 instance:

Windows Server 2016

You can login into the VM using “vagrant” as user name and “vagrant” as a password. vagrant rdp command will also do, but depending on RDP gods’ mood you might need to do an extra click.

RDP command result on Mac
‘vagrant rdp’ command result on Mac

Step 1. Setting up a host name and static IP address

These steps are absolutely identical to ones we did for Linux hosts last time. That’s the beauty of Vagrant. It’s just a few more lines in Vagrantfile:

Execute vagrant reload to reconfigure the VM and then we can go to the VM itself to confirm that Vagrantfile changes indeed worked:

Confirm Vagrantfile changes

Step 2. Download and “install” Consul

Declaring Windows provisioning steps in Vagrant is also almost identical to declaring them for Linux hosts. The only difference is that instead of .sh files we have to provide .ps1 for PowerShell:

Provisioning Consul agent in PowerShell syntactically does look different from provision.sh we created the last time, but it has the same logic: download and unzip. I added a few extra steps like checking if destination directory exists, removing source archive after unzipping, creating directory for Consul data (we’ll need that later) and printing out Consul version to make sure it’s working. But only three lines are really, truly necessary:

I also had to explicitly tell what TLS protocol to use for HTTPS requests, as HashiCorp’s web site (as almost everybody else’s) uses TLS 1.2 for encryption and that’s not something spoken by PowerShell’s Invoke-WebRequest by default. What a surprise.

But let’s apply the provisioning file and see if it works:

Yup, it’s all good.

Step 3. Configure and start Consul agent

With little adaptation agent’s config JSON from last article can be used for Windows agent as well. It’s mostly about the slashes:

And finally, starting the executable:

The line above will start Consul agent as a foreground process, so provisioning step will never end. That’s OK for now, but we could’ve easily fixed that with something like PowerShell’s Start-Process cmdlet:

Now, vagrant provision one more time and enjoy running Consul agent that can’t find the rest of the cluster:

We can fix that by starting Linux cluster we created before, or by implementing step 4.

Step 4. Optional. Merge Vagrantfiles

I already merged today’s Vagrantfile for Windows host with one created the last time. The result is on github, “winhost” branch. There were nothing difficult or interesting enough to put it here, but resulting Vagrantfile can do some magical stuff. It can create four virtual machines with different operating systems and configure them to behave as one Consul cluster. Imagine how long would it take to do that manually. Especially the Windows part.

That’s the beauty of automation: vagrant up, wait for few minutes and boom:

Consul cluster with windows host

Conclusion

Automating Windows VMs is not a myth. It’s something very doable and surprisingly easy to follow. Yes, there’re some problems with licensing and high resource constraints, but if you’re configuring VMs in a cloud, it already provides images with license taken care of, so configuring those hosts with Vagrant is no way different from configuring ones on Linux. There’s just no reason to do that manually anymore.

Leave a Reply

Your email address will not be published. Required fields are marked *