InCycle Software's Application Modernization and DevOps Blog

Desired State Configuration 101 – An intro to DSC

Written by Daniel Mann | May 7, 2014 9:35:10 AM

Hello! I want to take a break from talking about Release Management today and tackle a slightly different topic: Desired State Configuration (DSC). Release Management is great for deploying software, but what if you have extremely complex server setups that require a lot of "moving parts" to all be set up and configured properly before you can install your software? That's where Desired State Configuration (DSC) comes in to play: DSC is a great tool for managing your server configurations.

What is Desired State Configuration (DSC)?

Desired State Configuration is a new management platform added in PowerShell 4.0 that lets you manage your servers' configurations more easily. Instead of writing a "setup" script that goes and checks for perquisites and installs them if they're missing, you create a script that expresses how the server should be configured. When you run the script, the DSC framework is responsible for enforcing that the server's configuration matches up with what you defined, only taking the minimum set of actions necessary to enforce that state.

DSC is built off of the Managed Object Format (MOF), which is the language used to model Windows Management Instrumentation (WMI) interactions. Don't worry about MOF too much for today, though!


What platforms does DSC work on?

DSC is part of PowerShell 4.0, available in-the-box on Windows Server 2012 and later. You can also install it on a Windows Server 2008 R2 machine by installing Windows Management Framework 4.0.

What can it do?

A lot of stuff! You can see all of the built-in functionality on TechNet, or you can write a custom resource to extend DSC to do pretty much whatever you want.

The built-in resources are:

  • Archive – Provides tools to unpack ZIP archives
  • Environment – Manages system environment variables
  • File – Manages files and folders
  • Group – Manages local groups
  • Log – Writes messages to the DSC event log
  • Package – Executes packages, such as MSIs or EXEs
  • WindowsProcess – Ensures that processes are running (or not running)
  • Registry – Manages registry keys and values
  • WindowsFeature – Manages Windows features and roles, such as Hyper-V, IIS, or MSMQ
  • Script – Provides the ability to execute arbitrary PowerShell scripts on the target machine
  • Service – Manages Windows services
  • User – Manages local users

Neat! What else can it do?

Well, you can configure a Local Configuration Manager. A Local Configuration Manager can either have configurations pushed to it from other servers, or pull its DSC configuration from another server. Using this mechanism, you can set up a central repository to host your DSC configurations and configure your target servers to periodically validate that their configuration matches the desired configuration.

What does a DSC script look like?

Let's say we want to have our server host some Microsoft Message Queue (MSMQ) queues. It's easy!

First, create a Configuration block and give it a nice, descriptive name:
[powershell]
Configuration InstallMSMQFeature
{
}
[/powershell]

Next, we define a Node, which represents the server that we want to run this configuration on.

[powershell]
Configuration InstallMSMQFeature
{
Node "localhost"
{
}
}
[/powershell]

On that node, we can execute some commands. I'm going to just have it make sure that the MSMQ Windows Feature is installed with the WindowsFeature resource. For starters, I'll just say that I want it to be Present on the server, and I'll choose the feature name to install.
[powershell]
Configuration InstallMSMQFeature
{
Node "localhost"
{
WindowsFeature MessageQueueFeature
{
Ensure = "Present"
Name = "MSMQ"
}
}
}
[/powershell]

Now, if I want to actually run this thing, I have two more steps:

First, execute the configuration (just like you would any PowerShell script). This "preps" the configuration and generates a .mof file, which contains the configuration.
Then you execute it by calling Start-DscConfiguration".

Here's my complete script:
[powershell]
Configuration InstallMSMQFeature
{
Node "localhost"
{
WindowsFeature MessageQueueFeature
{
Ensure = "Present"
Name = "MSMQ"
}
}
}

InstallMSMQFeature
Start-DscConfiguration -Wait -Verbose -Path .\InstallMSMQFeature

[/powershell]

When I save the script as "InstallMSMQFeature.ps1" and run it, here's what the output looks like:

PS C:\Users\daniel.mann\Desktop> C:\Users\daniel.mann\Desktop\InstallMSMQFeature.ps1
Directory: C:\Users\daniel.mann\Desktop\InstallMSMQFeature
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a--- 5/5/2014 4:06 PM 1216 localhost.mof

VERBOSE: Perform operation 'Invoke CimMethod' with following parameters, ''methodName' = SendConfigurationApply,'className' = MSFT_DSC
LocalConfigurationManager,'namespaceName' = root/Microsoft/Windows/DesiredStateConfiguration'.
VERBOSE: An LCM method call arrived from computer DSCLAB with user sid S-1-5-21-2976432802-2705183534-60419669-500.
VERBOSE: [DSCLAB]: LCM: [ Start Set ]
VERBOSE: [DSCLAB]: LCM: [ Start Resource ] [[WindowsFeature]MessageQueueFeature]
VERBOSE: [DSCLAB]: LCM: [ Start Test ] [[WindowsFeature]MessageQueueFeature]
VERBOSE: [DSCLAB]: [[WindowsFeature]MessageQueueFeature] The operation 'Get-WindowsFeature' started: MSMQ
VERBOSE: [DSCLAB]: [[WindowsFeature]MessageQueueFeature] The operation 'Get-WindowsFeature' succeeded: MSMQ
VERBOSE: [DSCLAB]: LCM: [ End Test ] [[WindowsFeature]MessageQueueFeature] in 0.6590 seconds.
VERBOSE: [DSCLAB]: LCM: [ Start Set ] [[WindowsFeature]MessageQueueFeature]
VERBOSE: [DSCLAB]: [[WindowsFeature]MessageQueueFeature] Installation started...
VERBOSE: [DSCLAB]: [[WindowsFeature]MessageQueueFeature] Prerequisite processing started...
VERBOSE: [DSCLAB]: [[WindowsFeature]MessageQueueFeature] Prerequisite processing succeeded.
VERBOSE: [DSCLAB]: [[WindowsFeature]MessageQueueFeature] Installation succeeded.
VERBOSE: [DSCLAB]: [[WindowsFeature]MessageQueueFeature] successfully installed the feature MSMQ
VERBOSE: [DSCLAB]: LCM: [ End Set ] [[WindowsFeature]MessageQueueFeature] in 43.4700 seconds.
VERBOSE: [DSCLAB]: LCM: [ End Resource ] [[WindowsFeature]MessageQueueFeature]
VERBOSE: [DSCLAB]: LCM: [ End Set ]
VERBOSE: [DSCLAB]: LCM: [ End Set ] in 44.1910 seconds.
VERBOSE: Operation 'Invoke CimMethod' complete.
VERBOSE: Time taken for configuration job to complete is 44.333 seconds

And if I run it again,

PS C:\Users\daniel.mann\Desktop> C:\Users\daniel.mann\Desktop\InstallMSMQFeature.ps1
Directory: C:\Users\daniel.mann\Desktop\InstallMSMQFeature
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a--- 5/5/2014 4:09 PM 1216 localhost.mof

VERBOSE: Perform operation 'Invoke CimMethod' with following parameters, ''methodName' = SendConfigurationApply,'className' = MSFT_DSC
LocalConfigurationManager,'namespaceName' = root/Microsoft/Windows/DesiredStateConfiguration'.
VERBOSE: An LCM method call arrived from computer DSCLAB with user sid S-1-5-21-2976432802-2705183534-60419669-500.
VERBOSE: [DSCLAB]: LCM: [ Start Set ]
VERBOSE: [DSCLAB]: LCM: [ Start Resource ] [[WindowsFeature]MessageQueueFeature]
VERBOSE: [DSCLAB]: LCM: [ Start Test ] [[WindowsFeature]MessageQueueFeature]
VERBOSE: [DSCLAB]: [[WindowsFeature]MessageQueueFeature] The operation 'Get-WindowsFeature' started: MSMQ
VERBOSE: [DSCLAB]: [[WindowsFeature]MessageQueueFeature] The operation 'Get-WindowsFeature' succeeded: MSMQ
VERBOSE: [DSCLAB]: LCM: [ End Test ] [[WindowsFeature]MessageQueueFeature] in 1.6720 seconds.
VERBOSE: [DSCLAB]: LCM: [ Skip Set ] [[WindowsFeature]MessageQueueFeature]
VERBOSE: [DSCLAB]: LCM: [ End Resource ] [[WindowsFeature]MessageQueueFeature]
VERBOSE: [DSCLAB]: LCM: [ End Set ]
VERBOSE: [DSCLAB]: LCM: [ End Set ] in 2.5810 seconds.
VERBOSE: Operation 'Invoke CimMethod' complete.
VERBOSE: Time taken for configuration job to complete is 2.995 seconds

The second time, it only took 3 seconds to run because I already had the feature installed! Nifty!

Now, what if I wanted to run the same configuration on multiple servers? I don't want to copy and paste my node a bunch of times! Luckily you can pass parameters to your DSC configurations. If we modify the script so it has a param block, we can run the same configuration on multiple nodes like so:

[powershell]
Configuration InstallMSMQFeature
{
param($Servers="localhost")
Node $Servers
{
WindowsFeature MessageQueueFeature
{
Ensure = "Present"
Name = "MSMQ"
}
}
}

InstallMSMQFeature -Servers "dsclab", "foo"
Start-DscConfiguration -Wait -Verbose -Path .\InstallMSMQFeature

[/powershell]

That's all for today! In future blog posts, I'll cover some more complex topics, such as creating custom DSC resources, integrating DSC with Release Management, and more complex workflows.