This month, my team of fellow IT Pro Technical Evangelists are publishing a series of articles on Why Windows Server 2012 R2? that highlights the key enhancements and new capabilities that we're seeing driving particular interest in this latest release of our Windows Server operating system in the field.  After reading this article, be sure to catch the full series at:

Windows Server 2012 R2 includes a new version of the PowerShell scripting language, PowerShell 4.0. One of the most interesting new features in PowerShell 4.0 is Desired State Configuration (DSC).  DSC is a declarative management system inside Windows PowerShell 4.0 that enables servers to self-provision themselves during initial deployment and also self-remediate their configuration if it should fall out of compliance with their assigned “desired state”.

As our IT world moves towards increasingly more rapid deployments of servers and applications, DSC provides a standard framework for defining and managing configuration changes.  This provides a solution that can be leveraged to easily maintain system stability while on our march towards improved agility in the cloud. Gears

In this article, I’ll provide an overview of how DSC works, along with specific PowerShell code snippets that you can leverage and customize for use in your own environment.  While DSC can be used for managing the configuration of many different server roles, my examples in this article will show how DSC can be leveraged to provision and manage the standard configuration elements of Hyper-V virtualization hosts within a datacenter.

Which Servers Can I Manage with DSC?

DSC can manage the configured state of Windows Servers running as physical hosts, virtual machines in your on-premises datacenter, as well as virtual machines running on a public cloud platform, such as Windows Azure.  Although DSC is included as part of the built-in PowerShell 4.0 support in Windows Server 2012 R2, DSC is also available as a free download for Windows Server 2008 R2 and Windows Server 2012 via the Windows Management Framework 4.0 kit.  This allows you to leverage DSC for managing the configured state of Windows Server 2008 R2 and later.

However, DSC can be leveraged to work with server platforms beyond the typical “Microsoft stuff” … DSC is built upon Desktop Management Task Force (DMTF) standards, such as the Managed Object Format (MOF) and the WS-Management web services protocol.  Thus, DSC also lends itself to integration with third-party management tools, such as Puppet, Chef and other configuration management tools that have been commonly used in the Linux world. 

What is a Declarative Management System?

Rather than building a set of complex, process-oriented PowerShell scripts … With DSC, you instead express, or “declare”, the desired configuration end-state of a set of servers.  When this desired state is assigned to servers, each server will automatically compare their current state to the desired state, and then implement any configuration changes necessary to conform to the desired state – all without needing to write lines-and-lines of conditional checks and blocks of script code.  As a result, in just a few lines of declarative code, you can easily define some rather detailed configuration states.

In PowerShell 4.0, DSC adds a new keyword, the Configuration keyword, that is used to define configured states.  The structure of the Configuration keyword looks very similar to a PowerShell function, so it’s pretty easy to quickly understand and follow the syntax.  Here’s an example of a very basic configuration for a Hyper-V host that requires two Windows Server features: Hyper-V and Failover Clustering …

Configuration HyperVHost # Define the configuration name
{

    param ( $NodeName ) # Accept server names as parameters

    Node $NodeName # Begin block of configuration settings for each assigned server
    {

        #Install the Hyper-V Role
        WindowsFeature HyperV
        {
            Ensure = "Present" # Can be "Present" or "Absent"
            Name   = "Hyper-V"
        }

        #Install the Clustering Feature
        WindowsFeature Clustering
        {
            Ensure = "Present" # Can be "Present" or "Absent"
            Name   = "Failover-Clustering"
        }

    }
}

The above example is a simple configuration state that ensures that two Windows Server features, namely Hyper-V and Failover-Clustering, are both installed on assigned servers. Of course, DSC configurations can also be much more comprehensive.  DSC can include resources for supporting the following configuration components:

  • Enabling or disabling server roles and features
  • Managing registry settings
  • Managing files and folders
  • Starting, stopping and managing processes and services
  • Managing local user and group accounts
  • Deploying new software packages
  • Managing environment variables
  • Running Windows PowerShell scripts

I’ve included a more detailed DSC configuration example towards the end of this article, but you can also learn more about defining DSC configurations that include these additional resources in the article that follows.

How Do I Assign a Desired Configuration to Servers?

Once you’ve defined a DSC configuration using the Configuration keyword, there’s two steps that need to be performed to assign this configuration to servers:

  1. Compile the defined configuration into a set of MOF files for each server.  You do this by running the defined configuration, much like you’d run a PowerShell function.
     
    # Compile MOF files for each assigned server
    HyperVHost -NodeName "SERVER1","SERVER2"

     
  2. Use the Start-DSCConfiguration cmdlet to copy the MOF files to each assigned server and invoke the desired configurations.
     
    # Make it happen! Copy MOF file to node(s) and invoke the configuration
    Start-DSCConfiguration -Path .\HyperVHost -Wait -Verbose -Force

When the Start-DSCConfiguration cmdlet runs, the appropriate MOF files will be copied locally to each server and the Local Configuration Manager (LCM) engine on each server will process the MOF files.  As part of this processing, the LCM on each server will make the necessary configuration changes to conform to the assigned configuration.

What about Automated Remediation?

The steps above provide a simple example of the initial deployment of a desired configuration state to a set of assigned servers.  But, DSC can also periodically check the current configuration state of each assigned server and, if needed, remediate any configuration settings that may have fallen out of compliance.  This is great for organizations with large IT teams, as it means that the same configuration used for initial provisioning can also be used for self-correcting the configuration of servers post-deployment. If someone on the IT team should attempt to manually uninstall or reconfigure required configuration elements, the LCM on that server can remediate itself to return the server into configuration compliance ... automatically!

To use DSC for ongoing automated remediation, we need to add a new LocalConfigurationManager block of declarative code inside the Node{} block in the configuration above.  This new block contains the settings that the LCM on each assigned server will use to periodically recheck its configuration.  Here’s an example of this new block:

Configuration HyperVHost
{

    Node $Nodename
    {

    …

        # Set LCM Settings for each Node
        LocalConfigurationManager
        {
            RebootNodeIfNeeded = $True
            ConfigurationMode = "ApplyAndAutoCorrect" # Apply and Remediate configuration
            ConfigurationModeFrequencyMins = 15 # How frequently to recheck configuration
        }

    …

    }

}

Once this LocalConfigurationManager code block is added inside the defined configuration, you can use the following commands to recompile the MOF files for each server, deploy the LCM settings to each server, and then reapply the desired state configuration on each assigned server:

# Re-compile MOF files for each server using desired configuration data
HyperVHost -NodeName "SERVER1","SERVER2"

# Configure LCM Settings on each Node
Set-DscLocalConfigurationManager -Path .\HyperVHost -Verbose

# Make it happen! Copy MOF file to node(s) and invoke the configuration
Start-DSCConfiguration -Path .\HyperVHost -Wait -Verbose –Force

Now, with this updated configuration assigned to each server, our servers will make sure they have the Hyper-V role and Failover-Clustering feature installed.  If someone tries to uninstall these components manually, the servers will self-correct themselves within a few minutes!

Cool! How About A More Detailed Example?

Of course, production servers often include many more configuration settings than just a couple of Windows Server roles or features! Below, I’ve included an expanded example of the configuration started above. This expanded definition also includes support for MPIO, iSCSI, management tools, and the definition of a standard Hyper-V Virtual Switch.  This example shows how the Service and PowerShell Script configuration resources can be easily leveraged as part of a standard configuration.

Configuration HyperVHost # Define the configuration name
{

    param ( $NodeName ) # Accept server names as parameters

    Node $NodeName # Begin block of configuration settings for each assigned server
    {
        # Set DCM Settings for each Node
        LocalConfigurationManager
        {
            RebootNodeIfNeeded = $True
            ConfigurationMode = "ApplyAndAutoCorrect"
            ConfigurationModeFrequencyMins = 15
        }
       
        #Install the Hyper-V Role
        WindowsFeature HyperV
        {
            Ensure = "Present" # Can be "Present" or "Absent"
            Name   = "Hyper-V"
        }

        #Install the Storage Services Role
        WindowsFeature StorageServices
        {
            Ensure = "Present"
            Name   = "Storage-Services"
        }
       
        #Install the Clustering Feature
        WindowsFeature Clustering
        {
            Ensure = "Present"
            Name   = "Failover-Clustering"
        }

        #Install the MPIO Feature
        WindowsFeature MPIO
        {
            Ensure = "Present"
            Name   = "Multipath-IO"
        }

        #Install PowerShell Modules for HyperV and Cluster Management
        WindowsFeature RSAT-Clustering
        {
            Ensure = "Present"
            Name = "RSAT-Clustering"
        }
        WindowsFeature RSAT-HyperV
        {
            Ensure = "Present"
            Name = "RSAT-Hyper-V-Tools"
        }

        # Configure iSCSI Service
        Service iSCSIService
        {
            Name = "MSiSCSI"
            StartupType = "Automatic"
        }

        # Configure Hyper-V vSwitch
        Script vSwitch
        {
            TestScript = { (Get-VMSwitch -Name "vSwitch").Name -eq "vSwitch" }
            GetScript = { @{ Result = (Get-VMSwitch -Name "vSwitch").Name } }
            SetScript = { New-VMSwitch -Name "vSwitch" -NetAdapterName "NIC1" -AllowManagementOS:$true }
        }
    }
}

After defining this new configuration, use the same three command lines from the prior section of this article to compile and apply the configuration to the assigned servers.

Your Turn! Share Your DSC Examples …

Get started with DSC in your own lab environment by downloading the Windows Server 2012 R2 evaluation kit and exploring the DSC chapter in the Microsoft TechNet Library using the links below.

The configurations shown in this article provide a starting point for jumpstarting the use of DSC in your own environment. Feel free to augment these examples with additional configuration resources to further standardize your desired server configurations.

As you continue to explore DSC, be sure to share your examples in the Comments area below for how you’re leveraging DSC in your shop.

See you in the Clouds!

- Keith