Devops Practices: Infrastructure as Code

This post is provided by PowerShell MVP Richard Siddaway

One of the biggest issues in IT is the apparent split between development teams and operations teams. I deliberately say apparent because as with many things in IT the hype doesn’t always match reality. DevOps is the new IT ‘wunderkind’ that will cure all your IT woes at the wave of a wand.  OK cynical view put aside for a while – the DevOps movement does bring benefits and in many organizations there is a dichotomy between development, operations and purchasing. The last one isn’t talked about much but how many times have operations between the last to find out that a new application has been purchased. Oh, and it has to be installed by the end of the week!

One of the biggest stumbling blocks in IT is the movement of applications into production. The development team have an environment where everything works and when the application is passed over the fence to operations everything falls apart. There a number of reasons for this including:

·         Development infrastructure doesn’t match production

·         Development machine configurations don’t match production

·         Load in production greater than development

·         Permissions different in development and production

·         Application configurations aren’t documented

Infrastructure as Code (IaC) is all about applying software development techniques, processes and tools to manage the deployment and configuration of your servers and applications.

Why do you need to do this? And what exactly is IaC?

Let’s start by viewing what it’s not. Since PowerShell’s introduction 9 years ago many people have written code to configure their servers. You might use Desired State Configuration:

Configuration ODataSetup


  param (





  Node $node


    WindowsFeature IISbasic


       Ensure = ‘Present’

       Name = ‘Web-Server’



    WindowsFeature HTTPtracing


       Ensure = ‘Present’

       Name = ‘Web-Http-Tracing’

       DependsOn = “[WindowsFeature]IISbasic”



    WindowsFeature BasicAuth


       Ensure = ‘Present’

       Name = ‘Web-Basic-Auth’

       DependsOn = “[WindowsFeature]HTTPtracing”



    WindowsFeature WinAuth


       Ensure = ‘Present’

       Name = ‘Web-Windows-Auth’

       DependsOn = “[WindowsFeature]BasicAuth”



    WindowsFeature ManCon


       Ensure = ‘Present’

       Name = ‘Web-Mgmt-Console’

       DependsOn = “[WindowsFeature]WinAuth”



    WindowsFeature Modata


       Ensure = ‘Present’

       Name = ‘ManagementOdata’

       DependsOn = “[WindowsFeature]ManCon”



    WindowsFeature Desk


       Ensure = ‘Present’

       Name = ‘Desktop-Experience’

       DependsOn = “[WindowsFeature]Modata”





       RebootNodeIfNeeded = ‘True’






This is a configuration I used to create a demo machine for a talk on Odata that I presented at the PowerShell Summit NA 2015.  Its purpose is to ensure that a number of Windows features are installed on the machine including the web server (IIS), Odata management extensions and the desktop experience. The configuration handles the reboot.

The configuration is run:

$node = “W12R2OD01”

$path = ‘C:\Scripts\Mof’


$params = @{

 Node = $node

 OutputPath = $path


ODataSetup @params 


This creates a MOF file which is pushed to the remote machine to install the configuration:

$cs = New-CimSession -ComputerName $node

Start-DscConfiguration -CimSession $cs -Path $path -Verbose -Wait -Force


Other configuration tools such as Puppet, Chef, Ansible or Salt may be used instead of, or in conjunction with, DSC.  You might just use a script to configure parts of your new server:

Get-NetAdapter -Name Ethernet | Rename-NetAdapter -NewName ‘LAN’


## set network adapter and IP address

$index = Get-NetAdapter -Name LAN | select -ExpandProperty ifIndex



$ipv4address = ‘’

New-NetIPAddress -InterfaceIndex $index -AddressFamily IPv4 -IPAddress $ipv4address -PrefixLength 24


Set-DnsClientServerAddress -InterfaceIndex $index -ServerAddresses “”

Set-DnsClient -InterfaceIndex $index -ConnectionSpecificSuffix “”



##  join domain


$newname = ‘NewServer’

$cred = Get-Credential -Credential

Add-Computer -Credential $cred -DomainName manticore  -NewName $newname  -Force -Restart


Or you might use a combination of scripts and configuration.

So, you’ve automated your build process to a greater, or lesser, extent. You have a reproducible process but it’s still not IaC – you’re using software to manage your infrastructure but you need to take a few more steps into the development world.

So what do we need to do?

At the minimum you need to:

·         Apply source control to your infrastructure code

·         Put together a process that takes a new application build, creates the required infrastructure and deploys the application

·         Build tests into your infrastructure code – and keep those tests up to date as you make changes

·         Make sure that infrastructure used for development, test and production is created using the same code

Source control at its simplest is a matter of tracking the changes that are made to your code, who made them and most importantly gives you an easy way to roll back changes. Think of the scenario where you have a number of web farms each supporting an important web application. You need the server configuration in each web farm to be identical across the farm. Assume that your configuration code is changed by an overzealous junior administrator. No one will know until you need to deploy a new server into the farm to cope with the Christmas rush. Oops. The deployment works the difference in configuration brings the application to its knees.

Source control means that you can restrict who can change the code. It means you know that a particular version will work and that you know where it is. One piece of grit removed from the machine and ultimately less work firefighting.

Creating a build process that will create infrastructure and deploy the application is one endpoint of IaC. Your developers commit their changes, and the build process spins up a new server and deploys the application. This means that testing is always performed on a clean machine with a known configuration. It’s possible with a source control product such as Team Foundation Server (TFS) to create a number of builds – development, test and production for instance – and chose which one is targeted.

Don’t forget the change control! Deployments into development, and possibly test, should be standard changes – moving a new version into production and your organisation needs to make a call on how much risk it can accept. There are organisations that roll out several new versions of an application per day – this includes building new infrastructure for the application each time.

Testing is critical to any build process. You need to develop a set of tests that can be run, preferably, automatically, when your build process is changed. If you’re using PowerShell for your code you can use the Pester module (ships in Windows 10 and Server 2016 or can be downloaded from the PowerShell gallery). A simple example of creating tests with Pester:

function divisiontest {

    param (




    return $a / $b




Describe -Tags ‘BasicTests’ ‘divisiontest’{

    It ‘divides positive numbers’{

        divisiontest 6 3 | Should Be 2




    It ‘divides negative numbers’ {

        divisiontest -6 -3 | Should Be 2



    It ‘throws error for divide by zero’ {

        {divisiontest 6 0} | Should Throw




The function divides the first parameter by the second. The tests are wrapped in the Describe block and in this case test for correct division of positive and negative numbers. The third test is to determine if the function correctly throws an error when attempting to divide by zero. The results look like this:

Describing divisiontest

 [+] divides positive numbers 70ms

 [+] divides negative numbers 25ms

 [+] throws error for divide by zero 45ms


When testing you IaC routines you’ll need to look at testing things like installed windows features and roles, network configuration (IP addresses and subnet masks) or the existence of particular folders (use Test-Path).

The last point about making sure you use the same code to create the infrastructure for development, test and production is important as it ensures that you have consistency across the environments. This prevents any assumptions made in development or testing causing problems in production. Also, you know now know the configuration you need, its creation has been tested and you’ll have a smooth roll out into production (hopefully).

Put all of the above into play and you’ve taken the most important steps into the brave new world of DevOps – you’ve started.  Implementing IaC is a great first step but it will all fall apart on you if you don’t have good change control. I’ve seen many organisations that claim to be using change control but in reality they’ve created a bureaucratic overhead that doesn’t achieve its goals because:

·         It doesn’t have the authority to stop dangerous changes

·         Its viewed as an overhead rather than a protection

·         It purpose isn’t understood – its viewed as a rubber stamp for change

Make sure your change control process is robust and works. It’s quite telling that in the Phoenix Project ( the first thing that is implemented is a change control process that works. If you’ve not read the Phoenix Project its highly recommended as an introduction to DevOps. The book spends a bit too long on the scene setting and problem description as opposed to the solutions but it’s well worth a read.

Finally, should you use Infrastructure as Code for all applications? Ideally yes but (strange how there’s always a but) you will derive most benefit from using IaC with applications that change frequently, or are being developed and rolled out in a phased manner. The one-off deployment of a COTS application isn’t going to be the best place to start though ultimately your IaC processes should support that as well.



The post Devops Practices – Infrastructure as Code appeared first on Blogg(Ed).