BT

Facilitating the Spread of Knowledge and Innovation in Professional Software Development

Write for InfoQ

Topics

Choose your language

InfoQ Homepage Articles Cloud Automation in a Windows World

Cloud Automation in a Windows World

There are a couple different perspectives one can take to stack up today’s Windows automation landscape. One is to compare the state of Windows automation as it stands today with its state five years ago. This might lead one to feel impressed with how much the technology has grown and you may look optimistically to the future. The other perspective is to compare today’s Windows automation ecosystem with the tooling that surrounds Linux based infrastructures. At first glance things may not look so different but the closer you look and the more you tinker, you become aware of the fact that there is an undeniable gap in maturity.

Both comparisons present a relevant back story to the present state of Windows automation. In this article, I’d like to explore both of these perspectives by looking at real world Windows automation scenarios today. How is Windows being automated in 2014? What are the pain points? How does this differ from the Linux world? Is Windows and Linux converging toward a similar automation path or is it oil and water as each fight to maintain an identity and a market.

Your Windows automation might not be my Windows automation

There are several different approaches one can take with Windows automation. They tend to fall in to one of three camps:

  • No automation 
  • Enterprise solutions.
  • Open source (not necessarily free)

The first looks at the field of yaks to be shaved and decides not to automate. The second provides glossy reporting, a surprising amount of pointing and clicking, and possibly a limited programmable API surface. The third provides a lot of flexibility with raw code integration but often provides limited documentation and needs a lot of customized coding to build a complete end to end solution. This article will largely focus on this third camp since it is where I am personally most experienced.

Provisioning

Let’s start off talking about provisioning. While there are a variety of ways to provision a Windows box, I’m going to run through the process we use at CenturyLink cloud. We run a mixed environment of Linux and Windows servers. We needed a solution that could integrate with both operating systems. We decided to use Chef for our configuration management tooling and we have been early adopters of their machine resource product that is currently in beta – Chef Metal. Our primary virtualization platform is VMware vSphere. So let’s look at how all of these pieces come together to provision both Windows and Linux machines:

As pictured here, we have a provisioner node which holds a catalog (provided by the Chef server) of every server in a single data center and if it does not see a server provisioned where its catalog thinks one belongs, the provisioner uses Chef metal to provision the node. Chef metal provides a new “resource” to the Chef ecosystem, a machine resource. This resource is defined by attributes such as number of cores, memory, VM image template, etc.

machine 'web' do
   machine_options :memory_mb => 4096, :num_cpus => 2
   recipe 'active_directory'
end

Chef Metal on its own, knows what a machine is in Chef speak but it does not know about VMware. One can leverage Chef metal’s plugin model and create a driver that understands how to talk to the ruby vSphere SDK (rbvmomi) and can translate Chef metal’s high level abstractions to actual VMs, datastores, clusters, OS customization templates, etc.

Our driver code presents to Chef Metal a compute resource and Chef metal knows how to bootstrap this instance with a Chef client and then transforms it into the role my configuration has defined. Could be a web server, an active directory server, a file server or just about anything else.

Overall, this works well, but maybe you were hoping NOT to have to stand up several other servers and write your own ruby code to get a Windows server provisioned. Well there are several other light weight options and I’ll demonstrate a couple.

Windows Azure PowerShell Cmdlets

If you have an Azure account, just download the Azure PowerShell module and you can then automate everything you could do in the Azure web portal including the creation of an Azure IaaS virtual machine in one line:

$cred=Get-Credential AzureAdmin
New-AzureQuickVM –ServiceName ServiceTest1 -Windows -Name MyVM `
   -ImageName 3a50f22b388a4ff7ab41029918570fa6__Windows-Server-2012-Essentials-20131217-enus `
   -Password $cred.GetNetworkCredential().Password -AdminUsername $cred.UserName `
   -Location "West US" –WaitForBoot

The Hyper-V PowerShell Module

If you own a Windows 8 professional laptop, you can automate Windows provisioning with a hypervisor that ships with your machine. You can enable this if you have not done so already:

dism.exe /Online /Enable-Feature:Microsoft-Hyper-V /All
dism.exe /Online /Enable-Feature:Microsoft-Hyper-V-Management-PowerShell

And create your VM:

New-VM -Name "myVM" -MemoryStartupBytes 1GB -NewVHDPath "D:\VHDs\w81.vhdx" -NewVHDSizeBytes 60GB
Set-VMDvdDrive -VMName myVM -Path "C:\ISOs\EVAL_EN-US-IRM_CENA_X64FREE_EN-US_DV5.iso"
Start-VM "myVM"

No license required

Don’t have a spare Windows ISO lying around? That’s ok. You can download free evaluation copies of Windows from Microsoft’s TechNet or MSDN sites as an ISO or a VHD. The images expire in a few months and you should never use them in production but I use these for testing all the time.

A note about Windows Updates

Do yourself a favor and prebake Windows updates into your base image and save yourself hours of waiting for the updates to complete. You will want to have an automated process that can routinely update these images. I strongly recommend investigating a tool like packer.io. Packer known largely in the Linux world but getting some recent Windows attention is a tool specifically for building base VM images. You include a configuration that instructs packer as to how to build the image. It’s very much like configuration management but for the image instead of the machine. In fact packer can integrate with many popular configuration management tools like Chef so that you can leverage the DSL of your CM solution to build your images.

Molding your new Windows instance

So you have an empty Windows VM. Now what? As I have already pointed out above, we use Chef to build out a Windows box at CenturyLink Cloud. Technically, it is Ruby code but it’s largely just a DSL requiring little to no Ruby expertise. Chef exposes many of the common abstractions that comprise a server into building blocks called resources. You compose these together into larger building blocks called recipes and cookbooks in Chef speak.

Here’s a registry key resource:

# Disable the ServerManager.
registry_key 'HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\ServerManager' do
   values [{
     :name => 'DoNotOpenServerManagerAtLogon',
     :type => :dword,
     :data =>  0x1
     }]
end

This adds a user to a group resource:

group "administrators" do
   action :modify
   members node['platform_ftp']['fileshare_user']
   append true
end

BTW: The above will work in Windows or Linux. In fact most resources are platform agnostic and rely on an underlying provider model which delegates the implementation for a specific platform.

The ubiquity of resources is bigger than Chef

This resource abstraction is not unique to Chef. The same term is used in other configuration management tools like the popular Puppet and Microsoft’s DSC (desired state configuration) that ships with PowerShell 4 and above. The PowerShell team does have a lot of catching up to do with the Puppets, Chefs, CFEngines, etc., but they are hot on the path and coming out with new Windows ready resources you can download called resource wave packs. The latest to ship is wave 7.

There is a lot more than just resources that make up the sophistication of many configuration management tools. There is reporting, versioning, node bootstrapping, packaging etc. In fact tools like Chef have built an entire open source ecosystem around themselves that provide additional tools for testing, dependency management and all sorts of Lego-sized plugins that can fill the small gaps between your Windows server and the special needs of your business. Recognizing this gap, Microsoft is partnering with products like Chef and exposing its DSC resources from within Chef recipes. This means I can leverage some of the tricky Windows specific automation exposed by a DSC resources and also take advantage of Chef’s cross platform functionality, its reporting, enterprise server features as well as plug into the entirety of its open source community.

For more details on implementing DSC inside of Chef as well as testing this automation using PowerShell based testing tools, see this post for a step by step walkthrough on the topic.

Let’s get Chocolatey

If you don’t want to deal with the learning curve of a CM tool but just want to grab a few apps and be done with it, you might want to investigate what Windows has to offer in terms of package management.

For years, MSIs have been the de facto Windows package format but let’s be honest - it’s no apt-get or yum. My friend Rob Reynolds recognized the need for something simpler and http friendly a few years back and began Chocolatey. While I am always surprised when I bump into tech savvy Windows folk who have not heard of Chocolatey, it has garnered quite a bit of popularity among Windows power users and even the Microsoft PowerShell team have built a Chocolatey client into the latest version of PowerShell. That’s right, the next version of Windows will talk to Chocolatey right out of the box.

Observe these commands:

cinst googlechrome
cinst git
cinst ruby
cinst vagrant
cinst VisualStudio2013ExpressWeb

They install the listed software silently and with no GUI. No “Next”, “Next”, “Finish” here. Just like apt-get you can discover, download and upgrade your favorite Windows applications.

While the technology is solid and under very active development, the greatest weakness of Chocolatey is its ecosystem. Don’t get me wrong, as Windows OSS goes, Chocolatey has a rich community but unlike tools such as apt-get, Chocolatey packages are largely created and maintained by the community and not the owners of the packaged software with some exceptions. This means that sometimes the packages are not up to date or perhaps attempt to download software from a dead URL. For the most part this is not the case, but it is something that comes up frequently.

However, just as we are seeing DSC raise a technology like configuration management into the Windows mainstream, I’d bet we may see the same with package management. Once it comes with Windows and Windows users begin seeing samples consuming it in TechNet white papers, it may not be long before it becomes commonplace.

Chocolatey style machine builds using Boxstarter

Returning to the idea of building a Windows box with no heavy weight configuration management, let’s look quickly at a tool that leverages Chocolatey and addresses many of the typical machine bootstrapping woes when setting up a new Windows box. Full disclosure: I am the author of this tool.

Boxstarter adds reboot resiliency to Chocolatey packages and exposes several additional commands that can customize  and adds under the hood functionality preventing machine build failures when installing apps like SQL Server, Visual Studio and enabling Windows features and installing Windows updates all in one go.

Boxstarter takes a string of install commands identical to Chocolatey and it will detect pending reboots, rebooting and logging back on when necessary and then rerunning the package. One of Boxstarter’s most popular features is that you can do this without actually creating a package nor installing Chocolatey, Boxstarter or any other prerequisites. You can invoke everything from a URL. For example:

http://boxstarter.org/package/nr/url?https://gist.githubusercontent.com/mwrock/8518683/raw/43ab568ff32629b278cfa8ab3e7fb4c417c9b188/gistfile1.txt

This delivers Boxstarter via a Microsoft click once style app as a bootstrapper. Then it packages the contents of the gist URL appended to the Boxstarter URL. Optionally, you can install the Boxstarter PowerShell modules and use them to provision remote boxes via Chocolatey, again, gracefully handling reboots and allowing you to run any PowerShell you would normally run locally to setup a box.

You likely won’t use Boxstarter or Chocolatey on their own to setup and manage a running server, but these are great tools for the individual developer machine.

Where’s the SSH?

If you have worked much in the *Nix world, you are probably thinking that Windows has simply enabled an SSH server on the box. While not technically SSH, it is the same concept. Many have wondered why Microsoft did not use SSH from the get go. If you want to know Microsoft’s reasoning as to why they do not use SSH, listen to this podcast including an in depth discussion by Jeffrey Snover the creator of PowerShell.

To get SSH like functionality, Windows uses winrm (Windows Remote Management) which is a SOAP based web service that can send and receive messages via HTTP(s) and translate them to the local command line. Starting with PowerShell v 2.0 and progressively getting more advanced with each version (PowerShell is currently in beta v5), one can use “PowerShell Remoting” which sits on top of winrm and provides an interactive remote console almost no different from a an SSH session.

Here I am remoted into an Azure VM:

One may argue (including myself) that remote PowerShell is even more advanced than SSH exposing a higher fidelity of communication and manipulation between the remote and local shells.

My personal experience has been that the major disadvantage of remote PowerShell is that initially getting it to work is not nearly as seamless as SSH especially in older versions of Windows but as recent as Windows 2008R2. On a Linux box we take for granted that SSH is just there, while a Windows box needs to be properly configured. With Windows 2012R2 there may not be any configuration necessary but that is only if certain conditions apply like whether you are domain joined, in the same subnet or other group policy settings exist.

If you are trying to access Windows remotely from a non-Windows platform, remote PowerShell is not going to help you. You are limited to talking with the winrm web service directly. There are several cross platform APIs available. Ruby’s WinRM is a popular one and one that I have used quite a bit and is being actively maintained by Shawn Neal.

require 'winrm'
endpoint = 'http://mywinrmhost:5985/wsman'
krb5_realm = 'EXAMPLE.COM'
winrm = WinRM::WinRMWebService.new(endpoint, :kerberos, :realm => krb5_realm)
winrm.cmd('ipconfig /all') do |stdout, stderr|
   STDOUT.print stdout
   STDERR.print stderr
end

Can’t I just use Vagrant?

Short answer is YES!, If you are unfamiliar with Vagrant, it is a tool that abstracts virtualization and makes it simple to provision a personal box usually for developing/testing purposes that can be easily shared among team members. It’s hard to effectively communicate the utility and simplicity of Vagrant until you have used it. Many uninitiated will state, “I’m very comfortable with my hypervisor (VMware, virtual box, Hyper-V, etc.) why introduce an additional tool? Vagrant makes it easy to share a single ~1K file (usually in source control) that expresses via an easily readable DSL where to get the initial VM image, how to setup networking and how to add additional automation to the base image. You can work on the same team as others who use different virtualization technologies but the “vagrantfile” abstracts away all of those differences.

VAGRANTFILE_API_VERSION = "2"
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| 
   config.vm.box = "mwrock/Windows8.1-amd64"
   config.vm.box_url = "https://wrock.blob.core.Windows.net/vhds/win8.1-vbox-amd64.box"
   config.vm.guest = :Windows 
   config.winrm.username = "vagrant"
   config.winrm.password = "vagrant"
   config.winrm.port = 55985
end

This is a very simple vagrantfile example that sets up a Windows 8.1 vagrant box. As you might tell from the URL, the base image is served from my Windows azure storage account. Vagrant will port forward all requests on port 55985 to the “real” winrm port of 5985 of the virtual box VM.

Quite recently Vagrant added first class support for Windows. My personal experience is that working with Linux boxes provide less friction in Vagrant, but that is getting better with every release. To illustrate how easy it is to provision a Windows box via Vagrant, first download vagrant. Then:

vagrant init mwrock/Windows8.1-amd64
vagrant up

This will provision a Windows VM whether you have VirtualBox or Hyper-V (you will need at least one). If you do not have the base image, and you won’t the first time you call this, it will download it. This is actually one area where you begin to feel the friction of Windows. Your typical compressed Windows base image is about 3.5 GB. That is a very large file and often 30x larger than a Linux base box. However, often this is a one-time download and Vagrant cached it locally so you do not need to download it again.

Containerization

I simply cannot walk away without addressing containerization or what some think of as Docker. Docker can dramatically reduce the time it takes to provision a compute instance and promises to deeply simplify how we package applications.

Today, containers do not exist in Windows. For some, this very fact alone is reason enough to decide against Windows or begin to migrate away from it. At CenturyLink Cloud we do all of our initial server build testing using Docker for our Linux based infrastructure and anyone on my team can tell you that testing and tweaking Windows server automation is far more tedious than Linux by virtue of the fact that Docker can’t be used with Windows.

One company heavily investing to bring the features of containerization to Windows is spoon.net. They have actually been developing this concept for quite some time in the virtual desktop world, but they are quickly accelerating this on the server. You can create a spoon container that provides an isolated file system and registry and the command line interface is very Docker-like. There are still rough edges when it comes to some services and networking, but many of these issues may be resolved by the time this is published. My hope is that one day I can incorporate Windows containers into my Chef automation workflow.

Here are screen shots of containerized Chef client nodes than Kenji Obata, CEO of Spoon posted on Twitter recently.

Since the original writing of this post, the story of contrainerizing Windows has suddenly gotten even more interesting. Microsoft announced that it will be working with Docker to bring Windows containers to the Docker ecosystem. Its unclear when that will be made available and exactly what it will look like. However the fact that Microsoft is publicly committing to this effort is truly exciting. One way or another, it sounds like Windows containers lies in our future.

These are pioneering times

This is a very exciting time for Windows automation. When I recently left Microsoft to join CenturyLink and began my full immersion cross-platform journey, I felt like I had crested a summit to witness an established civilization of server automation. Well there are several ways to spin that image but I rather like having one leg in the Wild West. It may be rugged but right now I feel Windows automation is ripe for opportunity and innovation. I‘m looking forward to see where all this takes us.

About the Author

Matt Wrock has over fifteen years experience architecting scalable, distributed, high traffic web applications as well as environment and deployment automation. Until recently, Matt worked for Microsoft as a Sr. Software Engineer and now works for CenturyLink Cloud focusing on data center automation. Matt is also project founder of http://boxstarter.org and a committer to http://chocolatey.org. You can follow Matt on twitter at @mwrockx or check out his blog at hurryupandwait.io.

Rate this Article

Adoption
Style

BT