Configuration Management Week: DSC

Today’s guest post is by Jon Carl. View the full Configuration Management Week schedule here.

About Jon

Jon Carl enjoys the outdoors, running, and anything tech, specifically software engineering. In his spare time, Jon is building a new social network, Segment. At the time of this article he is employed by Frontline Technologies where he works as a Junior Software Engineer. Follow him on Twitter @grounded042.

Intro to DSC

Overview

Get-Help DSC

PowerShell Desired State Configuration, hereafter referred to as DSC, is a configuration data deployment and management feature in Windows PowerShell. DSC allows one to declare a wide range of configuration options and variables through PowerShell syntax, and apply those configurations to one or many machines with the push of a button. Configurations are made to be re-runable, and can thus be used as a configuration integrity tool by re-applying the configurations as needed. To put it simply, DSC allows the desired state of a configuration to be declared and applied.

DSC was announced in 2013 as a part of PowerShell version 4 in Windows Server 2012 R2. The goal of DSC is to help “administrators write a declarative ‘script’ that describes what a computer should look like.”

DSC was also espoused to be a core part of the Windows OS which was a big step in the direction of making Windows easier to configure and manage using just a command line interface. While one might think Microsoft was trying to take on configuration management and deployment giants like Puppet or Chef, such was not the case. DSC has been built to compliment what Puppet and Chef have to offer – to provide a consistent and reliable interface on which Puppet, Chef, or any other configuration management tool may build on. A configuration script can be written by hand for DSC, or an external tool can generate that script – cross-compiling so-to-speak.

In general, DSC has been well received by the Windows community. Microsoft MVP Don Jones, founder of powershell.org, has written widely on the topic along with other authors on PowerShell.org and PowerShellMagazine.com. For those not already using a configuration management tool, DSC has helped break the ice for them. Gone are the days of manually building out new Windows servers.

Getting Started with DSC

Setting up a development environment for DSC is simple and easy. If you have a computer with PowerShell 4 or later installed, you’re halfway there. A handy tool for developing the DSC scripts in is the PowerShell ISE (integrated scripting environment). If you don’t already have the PowerShell ISE installed, most modern systems will come with it. If you don’t have it, simply run the PowerShell command Import-Module ServerManager Add-WindowsFeature PowerShell-ISE to get it.

DSC has local configuration files called resources. A resource takes in configuration parameters and configures the system using those parameters. For instance, the File resource takes in configuration parameters that can make sure a folder or file does or does not exist, a folder or file matches a target folder or file, etc. By default, PowerShell 4 comes with stable, production-worthy resources. Unstable or experimental resources can be downloaded and installed from GitHub.

Here’s a simple DSC configuration for IIS with a custom site instead of the default one:

Configuration Custom_Website
{
    param([string[]]$computerName='localhost')

    Node $computerName
    {
        WindowsFeature IIS
        {
            Ensure = 'Present'
            Name = 'Web-Server'
        }

        Script RemoveDefaultIISSite
        {
            SetScript = {
                Import-Module WebAdministration -Verbose:$false
                Remove-Website -Name 'Default Web Site'
            }  
        
            GetScript = {
                return @{'Action' = 'Removes the default IIS site'}
            }
        
            TestScript = {
                Import-Module WebAdministration -Verbose:$false
                if (!(Test-Path 'IIS:\Sites\Default Web Site')) {
                   return $true
                }
                return $false
            }
            DependsOn = '[WindowsFeature]IIS'
        }
    
        File Website_Directory
        {
            Ensure = 'Present'
            Type = 'Directory'
            DestinationPath = 'C:\Custom_Website'
        }
    
        Script Custom_WebsiteIIS
        {
            SetScript = {
                Import-Module WebAdministration -Verbose:$false

                 Remove-Website -Name 'Default Web Site'
                 New-Website -Name 'Custom_Website' -Port 80 -PhysicalPath 'C:\Custom_Website'
            }
        
            GetScript = {
                return @{'Action' = 'Removes the default IIS site'}
            }
        
            TestScript = {
                Import-Module WebAdministration -Verbose:$false

                if (Test-Path 'IIS:\Sites\Custom_Website') {
                    return $true
                }

                return $false
            }
            DependsOn = '[WindowsFeature]IIS', '[Script]RemoveDefaultIISSite', '[File]Website_Directory'
        }
    }
}

Let’s break this down and talk about the different parts:

Configuration Custom_Website
{
    param(
        [string[]]$computerName='localhost'
    )
}

This piece is defining the configuration. Think of it like a function that can be called with the string variable computerName. When you call it, a build configuration will be generated. Notice that we are taking in an array of strings for computerName, so we could pass in multiple computer names here and it would generate the configuration for each machine. By default the variable will be localhost.

Node $computerName
{

}

This block is declaring the configuration for a node. You can have any number of node blocks inside of a configuration. With DSC, a configuration is not limited to a single server like this configuration. A configuration could be written for an application that needs different types of servers, and a node block could be defined for each type of server.

Inside of the node block you will see 3 separate blocks. Each block uses a resource and defines the configuration of that resource. This is where extra, albeit sometimes unstable, resources from GitHub or other places can be used (you could even write your own). Below we won’t go over every resource node, but will instead just go over the types used.

WindowsFeature IIS
{
    Ensure = 'Present'
    Name = 'Web-Server'
}

As with all the resources, this one declares the resource to be used, in this case WindowsFeature, and then a name for it, in this case IIS. Inside of each resource block are the configuration parameters related to the specific resource. For this resource, we are ensuring that the Windows feature ‘Web-Server’ is present – the exact same thing as running Install-WindowsFeature Web-Server via the command line. The Ensure variable could also be set to ‘Absent’ if the configuration needed to make sure that a windows feature was not installed. Microsoft is good about making sure their resources have good documentation, and more info about the WindowsFeature resource can be found here.

Script RemoveDefaultIISSite
{
    SetScript = {
        Import-Module WebAdministration -Verbose:$false
        Remove-Website -Name 'Default Web Site'
    }

    GetScript = {
        return @{'Action' = 'Removes the default IIS site'}
    }

    TestScript = {
        Import-Module WebAdministration -Verbose:$false

        if (!(Test-Path 'IIS:\Sites\Default Web Site')) {
            return $true
        }
        return $false
    }
    DependsOn = '[WindowsFeature]IIS'
}

The script resource allows the execution of powershell defined in the block instead of in the resource itself. Notice the configuration variables SetScript, GetScript, and TestScript. SetScript is used to actually setup the configuration for the current resource. In this case, it’s removing the default IIS website. TestScript is used by DSC to test and see if the SetScript block needs to run. If TestScript returns False, meaning that the test failed, SetScript is run. If TestScript returns True, the SetScript block will not be run. The GetScript block is used for getting information about the configuration from a machine. You can do fancy stuff with the GetScript block, but you don’t have to. The last thing in the configuration variables is DependsOn. This block specifies that before this resource configuration is run, another resource configuration needs to run. To specify what needs to be run, you simply need to use the syntax [ResourceType]ResourceName. In this case, RemoveDefaultIISSite needs the WindowsFeature resource configuration named IIS to run before it runs. DependsOn is a nifty variable, and it even accepts multiple resource configurations to depend on.

File Website_Directory
{
    Ensure = 'Present'
    Type = 'Directory'
    DestinationPath = 'C:\Custom_Website'
}

This last resource type, File, allows the configuration of files and folders. Through the variables defined, the configuration will make sure that the directory C:\Custom_Website is present. If the directory does not exist, it will be created. This is a simple resource configuration compared to some of the other things it can do. The File resource can go as far as making sure a certain file has specific content.

Now that the main resource types have been covered, we can move on to how to apply this configuration. The first step is to generate the configuration for a machine from the configuration function. Execute the configuration block in powershell just like you would execute a new function, and it will then be available to generate configurations. Just like a function, the configuration is called to generate a specific configuration. To do that for this, just run the command Custom_Website -computerName testMachine where testMachine is the name of the machine for the configuration. Note that you could also run the command Custom_Website -computerName testmachine, testmachine1 and it would generate one configuration for each machine. The configuration files that get spit out will go to a folder at your current location with the name of the configuration. In this case, they will sit in a folder named Custom_Website.

The next step is to actually apply the configuration to the machines. To do this, simply run Start-DscConfiguration -Path .\Custom_Website -Wait -Verbose. This applies all the configurations from the Custom_Website folder to their respective machines. With the -Wait flag, you specify that you want to wait until the configuration process is finished. The -Verbose flag specifies that you want all the output for the configuration application. Verbose is handy to help troubleshoot issues. If there are any issues, they will appear on the PowerShell console just like any other error will.

The above is just a scratch on the surface of what DSC can actually do. You can do anything from a simple web server configuration all the way to an entire micro-services ecosystem configuration.

Also of note is that the example above is just pushing a configuration manually, but you can also do a pull setup.

Coolest Features

One of the biggest benefits of DSC is that it’s automatically included with Windows since Server 2012 R2. You don’t need to download anything special on the target machine – just build a configuration and apply it. Also, if you live in a Windows environment, and already write PowerShell, this is going to be easy and simple. The learning curve coming from a PowerShell background is minimal, and if you already have custom built scripts in PowerShell, you can potentially reuse them in your DSC. Also, while I haven’t tried it out yet, DSC can also be applied to a Linux server.

Biggest Drawback

PowerShell DSC is a solid configuration management option for Windows. However, it lacks scalability. If you want visibility into the configuration of a large farm of servers , this is not the product for you. It’s great for a couple of servers here and there, but not hundreds and hundreds. However, like I noted before, DSC is meant to complement tools like Puppet and Chef – so maybe, you could write your configurations in DSC, but apply them with Puppet or Chef.

Further Reading

The online community has some great resources for PowerShell DSC. Check out http://blogs.technet.com/b/privatecloud/archive/2013/08/30/introducing-powershell-desired-state-configuration-dsc.aspx or http://www.powershellmagazine.com/tag/dsc/ to get started.

Configuration Management Week: DSC

One thought on “Configuration Management Week: DSC

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s