DevOps with Windows Server 2016
上QQ阅读APP看书,第一时间看更新

Desired State Configuration

Desired State Configuration is a new configuration management platform from Microsoft built as an extension to PowerShell. DSC was originally launched as part of WMF 4.0. It is available as part of WMF 4.0 and 5.0 for all Windows Server operating systems above Windows 2008 R2. WMF 5.0 is available out-of-the-box on Windows Server 2016 and Windows 10. It uses the core infrastructure of Web Services for Management (WSMan) and Windows Remote Management (WinRM) for its working. It is an extension to PowerShell and adds language constructs, features, and cmdlets for easy authoring and execution of configuration across heterogeneous environments.

DSC is a declarative language enabling Infrastructure as Code by representing and describing the entire infrastructure and its configuration through code. DSC configuration files are simple .ps1 script files that can be stored in source control repositories for version control.

DSC represents the target state and configuration for environments through code. It represents what the environment state and configuration should look like. The how part is not required because it is taken care of by DSC internally.

DSC will be used in the release pipeline to configure multiple environments and application configuration.

DSC Push architecture

Figure 15 depicts a DSC Push architecture.

Figure 15: Desired State Configuration Push architecture

A simple DSC is shown here:

Configuration EnableWebServer 
{ 
    Import-DscResource -ModuleName 'PSDesiredStateConfiguration' 
    Node WebServer01 
    { 
        WindowsFeature IIS 
        { 
            Name = "Web-Server" 
            Ensure = "Present" 
        } 
    } 
} 
EnableWebServer -OutputPath "C:\DSC-WebServer" -Verbose 
Start-DscConfiguration -Path "C:\DSC-WebServer" -Wait -Force -Verbose  

The code declares EnableWebServer configuration. This configuration is responsible for ensuring the presence of the Web-Server (IIS) Windows feature on a WebServer01 computer. The node name should be changed reflecting an actual computer name in your network. Notice that the configuration does not use any scripting or programming to provision a web server. The configuration is merely providing the intent and its configuration values, the rest is taken care of by DSC resources internally. The node section comprises of names of computers that this configuration is applicable to. WindowsFeature mentioned in Configuration is a DSC resource that actually provides the logic for provisioning of Windows features on a target computer. The how part is taken care of by these DSC resources.

Executing the above configuration as shown in the code, generates the configuration Management Object Format (MOF) file for each node name in configuration at the folder location provided to the path parameter. If the path parameter is omitted, the MOF files will be generated in the current working folder. These MOF files are pushed to target nodes by DSC using the Start-DscConfiguration cmdlet. This cmdlet takes the path parameter as input representing the folder containing MOF files, loads all MOF files, and sends them to their respective computer nodes using the MOF file names.

Alternatively, you can also provide the ComputerName parameter to Start-DSCConfiguration cmdlet which will load a MOF file matching the ComputerName and push it to that node only. This is shown here:

Start-DscConfiguration -Path "C:\DSC-WebServer" -ComputerName WebServer01 -Wait -Force -Verbose  

Installing WMF 4.0 or 5.0 on client nodes ensures the installation of DSC Local Configuration Manager (LCM). It is the responsibility of LCM on these client nodes to accept the configuration sent to it and execute them on the local machine. LCM treats the received configuration as Golden configuration. LCM is configured to run periodically, checking the current state of configuration with a Golden desired state of configuration. If it finds any deviation, it brings back the configuration and environment back to a desired state. This ensures that target servers and their configuration can be auto-remediated in case there are changes applied to them.

DSC resources must be available at the client nodes for LCM to periodically check and auto-remediate the configuration. They help LCM in validating the current resource configuration with desired configuration, bringing back the current configuration to a desired configuration. Earlier we witnessed a single DSC resource in configuration. There are more than 300 DSC resources available to be used within configurations. While DSC comes with few out-of-the-box DSC resources, it is possible to author custom DSC resources. DSC provided resources are:

  • WindowsProcess
  • WindowsFeature
  • Service
  • Environment
  • File
  • Archive
  • User
  • Group
  • Package
  • Log
  • Script

DSC Pull architecture

We've seen one of the DSC architecture implementations called the Push mode. DSC comes in two architectural implementation modes:

  • DSC Push mode
  • DSC Pull mode

In Pull mode, the configurations are not pushed to client nodes. Instead, LCM on client nodes are configured with appropriate endpoint information through which it is able to connect and download configuration from DSC Pull servers and execute them on a local server. It is needless to say that DSC Pull servers need to be created and available with appropriate published configuration files before they are fetched by LCM.

DSC Pull mode is a decentralized and a scalable way of enabling configuration management. Hundreds and thousands of client nodes can simultaneously pull configurations automatically without any manual intervention. DSC resources can also be downloaded along with configuration files eliminating the need to preinstall resources on client nodes before executing the configuration. It is much more manageable and flexible compared to DSC Push mode. We will be using DSC Pull server and configuration to create our base container images.

The DSC Pull architecture is shown in Figure 16:

Figure 16: Desired State Configuration Pull architecture

Initially, DSC configuration is authored as PowerShell scripts. Then DSC MOF file is generated based on authored PowerShell scripts, and eventually the MOF files are published to a Pull server. The LCM of the client node then downloads the configuration and reconfigures the node according to the configuration.

Figure 17 shows the DSC Pull mode request flow between client node and Pull server.

Figure 17: Desired State Configuration Pull flow sequence

The following sequence of operations happens during Pull mode

  1. The configuration developer creates the configuration, generates MOF files and other artifacts, and copies them to a pre-defined folder location on the DSC Pull server. This is simply a copy-paste operation.
  2. The DSC administrator configures the LCM of every client node with information about Pull server endpoint, configuration details, and frequency to pull configuration.
  3. The client node sends requests to the Pull server for fetching configuration.
  4. The Pull server on receiving the request, responds by sending configuration information.
  5. Steps 2 to 4 are repeated based on configured frequency.
  6. For every request received, a response is sent with configuration information to the client nodes.

Pull configuration example

This chapter assumes that you already have a working Pull server in your network. In case, you do not have a Pull server available, complete steps for creating a Pull server is provided in appendix 1 in this book which would create a Pull server with endpoint URL https://10.4.0.4:9100/PSDSCPullServer.svc/ on port 9100:

The following configuration will to explain how to set up DSC Pull configuration:

Configuration EnableWebServer 
{ 
    Import-DscResource -ModuleName 'PSDesiredStateConfiguration' 
    Node EnableWebServer 
    { 
        WindowsFeature IIS 
        { 
            Name = "Web-Server" 
            Ensure = "Present" 
        } 
    } 
} 

You will notice that the name of Node is no longer a computer node name. This is because any node can pull this configuration from the Pull server. The node name is of high significance in DSC. The Node name decides the name of the generated MOF file. With pull architecture, even the name of configuration has impact on the way these configurations are downloaded by the target node. The name used reflects the intent of the configuration.

You will also notice that start-DscConfiguration cmdlet is not used for this configuration. Start-DscConfiguration is used to push configuration to target nodes. For Pull server configurations, there are two additional requirements:

  • Instead of pushing, configurations are deployed to a well-known folder path known to Pull server. Pull server can be an IIS website or a Server Message Block (SMB) share. In this book, IIS websites will be configured as a Pull server. The Pull server is configured with this folder path in its web.config file. When a request for configuration arrives at the Pull server, the website accesses this folder path, loads and sends back the configuration. By default, this folder location is $env:ProgramFiles\WindowsPowershell\DSCService\Configuration. We generate MOF files as we did in the Push scenario by executing the configuration with output path as $env:ProgramFiles\WindowsPowershell\DSCService\Configuration. This would generate the MOF file within the output path folder. This is shown here:
        EnableWebServer -OutputPath "$env:ProgramFiles\
        WindowsPowershell\DSCService\
        Configuration" -Verbose 
  • A checksum/hash should be generated for each MOF file. This hash is saved in a .mof.checksum file along with the original MOF file. Each .mof file should have a corresponding .mof.checksum file with same name. This checksum is important for LCM to validate and decide if it needs to download the configuration from the Pull server. Every time a LCM on a node pulls a configuration, it sends the hash it already has to the Pull server. If the hash is different on the Pull server, the configuration is downloaded otherwise it would mean the configuration on the node is the same as that on Pull server. To generate the checksum and write it to a file, DSC provides a cmdlet New-DscChecksum. Its usage is shown here. It takes configuratioPath as the path to the configuration MOF file and Outpath as the folder location to generate the corresponding checksum file:
        New-DSCCheckSum -ConfigurationPath 
        "$env:ProgramFiles\WindowsPowershell\DSCService\
        Configuration\    
        EnableWebServer.mof"  -OutPath 
        "$env:ProgramFiles\WindowsPowershell\DSCService\
        Configuration" -Force 
  • It is to be noted that if the ConfiguationPath parameter refers to a folder rather an MOF file, the checksum file will be generated for all MOF files at location referred to by the ConfiguationPath parameter. This is shown here:
        New-DscCheckSum -ConfigurationPath "$env:ProgramFiles\
        WindowsPowershell\DSCService\Configuration"     
        -OutPath "$env:ProgramFiles\WindowsPowershell\DSCService\
        Configuration" -Force 

The configuration can now be pulled by any authorized and configured computer node. After storing configurations on the Pull server, the LCM of computer nodes should be configured so that they can pull configurations from the Pull server.

To configure LCM on a target node, DSC configuration should be created containing resources specific to LCM. The MOF file should be generated, pushed to target nodes, and executed locally on target nodes. The approach to push LCM configuration to the target node is the same as that of any other configuration using Start-DscConfiguration cmdlet. However, there are differences in the way the configurations are authored. This is explained next.

DscLocalConfigurationManager() attribute

LCM configuration has the DscLocalConfigurationManager() attribute at a configuration level. This attribute ensures and enforces that only configuration related to LCM are allowed within the configuration. There are three resources used in this example:

  • Settings
  • ConfigurationRepositoryWeb
  • PartialConfiguration

The Settings resource configures the LCM with multiple properties. If you want to view LCM properties, use Get-DscLocalConfigurationManager cmdlet to list all properties along with their values. The properties  used in this example are explained here:

ConfigurationRepositoryWeb

ConfigurationRepositoryWeb defines details about web-based Pull server. The three properties of this resource used in this example provide enough information to connect to the Pull server. CertificateID and AllowUnsecureConnection are other available properties but not used in this example. CertificateID refers to the certificate thumbprint for authenticating to Pull server and AllowUnsecureConnection accepts a Boolean value determining whether unauthenticated access to Pull server is allowed.

Partial Configurations

The PartialConfiguration section defines the Configuration source that should be used to deploy the configuration on a computer node. PartialConfiguration help in downloading multiple configurations from different Pull servers and apply all of them together on a local node. In this example, we have used a single configuration in ConfigurationRepositoryWeb and a single PartialConfiguration section, but more configurations can be added to the ConfigurationNames property of ConfigurationRepositoryWeb and multiple partial configuration sections can be defined corresponding to those configurations. It is important to note that the name of partial configuration must available in ConfigurationNames property of ConfigurationRepositoryWeb. Moreover, the name must also match to the name of the original configuration based on which MOF file is generated. We mentioned at the beginning of this section that ConfigurationNames are quite important in Pull scenarios.

In short, the PartialConfiguration names should match the name of the original configuration, the name of MOF file, and the name should also be available as part of ConfigurationNames property of ConfigurationRepositoryWeb. If these names do not match, LCM on computer nodes will not be able to pull configuration information from Pull servers. The RefreshMode property defined in settings section can be overridden in this section with a different value.

Pushing LCM Configuration

Finally, the configuration is pushed to the localhost computer node (in this case the configuration is authored on local computer) and executed to effect changes to LCM configuration using Set-DSCLocalConfigurationManager cmdlet. This cmdlet is responsible for pushing and updating only Local Configuration Manager configuration. It cannot be used for pushing other types of configuration.

The configuration assumes that the LCM configuration is authored on the node that would act as a client to Pull server. This is the reason the node name is localhost in code shown next. However, if you want the following configuration to be authored on any other server, it is possible to do so. In that case, the node name in code should change to the actual name of the node and start-DscConfiguration should either, not use the computer name altogether, or should provide the actual node name to ComputerName parameter as argument.

Pull server information like RegistrationKey, endpoint URL, and ConfigurationNames should be gathered before the following script is executed. The RegistrationKey is available from the RegistrationKeys.txt file available in the $env:ProgramFiles\WindowsPowerShell\DscService folder on Pull server. The endpoint URL of Pull server can be obtained from IIS.

 [DscLocalConfigurationManager()] 
configuration PartialConfigurationDemo 
{ 
    Node localhost 
    { 
        Settings 
        { 
            ConfigurationModeFrequencyMins = 30 
            RefreshMode = 'Pull' 
            RefreshFrequencyMins = 30  
            ConfigurationMode = "ApplyandAutoCorrect" 
            RebootNodeIfNeeded = $true 
        } 
 
        ConfigurationRepositoryWeb IISConfig 
        { 
            ServerURL = "https://10.4.0.4:9100/PSDSCPullServer.svc/" 
            RegistrationKey = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" 
            ConfigurationNames = @("EnableWebServer") 
        } 
        PartialConfiguration EnableWebServer 
        { 
            Description = 'Configuration for installing Web server' 
            ConfigurationSource = '[ConfigurationRepositoryWeb]IISConfig' 
            RefreshMode = 'Pull' 
        } 
    } 
} 
PartialConfigurationDemo -OutputPath "C:\LCMConfiguration" -Verbose 
Set-DscLocalConfigurationManager -path "C:\LCMConfiguration" -force -verbose 
Update-DscConfiguration -Wait -Verbose 
Start-DscConfiguration -UseExisting -Wait -Force -Verbose 

After the LCM settings are configured, it's time to connect to Pull server, download, and execute the configuration on the target node. The configuration is pulled using Update-DscConfiguration cmdlet. It does not accept any parameters and runs as a job by default. To execute this cmdlet in synchronous mode, the -wait switch can be used as shown before. Verbose switch provides additional execution steps when this cmdlet is executed.

After pulling configuration the configuration is executed and applied using Start-DscConfiguration cmdlet. It is asked to use existing configuration through UseExisting switch, wait switch runs the cmdlet in synchronous mode, force switch pushes configuration to target nodes even when the LCM on target node is configured with pull configuration and verbose switch provides additional information about the execution.

If there are no errors while executing the code shown here, IIS will be installed, available and configured on target node. This can be verified by accessing http://localhost/ using browser in your local machine. You should see IISStart screen.