Building infrastructures means building and connecting machines which are hosting services that support the business by making its jobs easier. From the early days on, infrastructure creates the baseline by hosting specific machines to do specific tasks. The infrastructure team installs and configures the OS and hands the machine over to the application developers who in their turn install and configure the application for the business.
So how to build and maintain the OS in a structured manner? There are enough methods to deploy an OS in a structured way, maintaining the configuration of the OS is somewhat more difficult. And checking if the installation and configuration isn’t drifting away from its intended state is difficult. Desired State Configuration (DSC) can maintain a configuration and detect a drift from the intented configuration.
DSC is Microsoft’s answer to maintain and keep configurations of OSes and applications. Microsoft states that DSC is gradually going to be the only means to manage windows servers and applications. DSC works with Microsoft Framework and Powershell.
Simplified DSC says: “Hey server you are going to be a web server, take configuration “WEB_Main_v4″ and apply that configuration. Have fun!”
Configuration files have a basic markup: it starts with defining the configuration name, the node name and actual configuration. The configuration acts as a template, from which a specific configuration for a specific server will be build, which we can deploy to that specific server.
|
PS >configuration ServerConfig >> { >> param ([string[]] $NodeName) >> node $NodeName >> { >> File Folder_C_Temp >> { >> Ensure = "Present" >> Type = "Directory" >> DestinationPath = "C:Temp" >> } >> } >> } PS > |
In this template the configuration is named “ServerConfig”. The configuration is for a server named Servername (which will be stored in the variable $NodeName). File is the configuration item which is being defined with parameters. Save the config as “aserver.ps1”
The configuration looks similar as a PowerShell function and in a way it is!
Knowledge of PowerShell is necessary when working with DSC
|
PS> ServerConfig -OutputPath "." -NodeName "A" Directory: C:UsersMyDocumentsScriptsServerConfig Mode LastWriteTime Length Name ---- ------------- ------ ---- -a--- 1/27/2015 3:35 PM 1162 A.mof -a--- 1/27/2015 3:35 PM 932 A.meta.mof PS > Start-DscConfiguration -Wait -Force -Path .ServerConfig -ServerName "A" |
Run aserver.ps1 in Powershell. Once the configuration is loaded, the configuration is available as a command with the name of the config (like a function). Run “ServerConfig -OutputPath “.” -NodeName “A”” to create the .mof file. Use the command Start-DscConfiguration -Wait -Force -Path .ServerConfig -ServerName “A” to actually deploy the configuration to server “A”.
The Managed Object Format (MOF) was defined by the Distributed Management Task Force (DMTF). The purpose of the DMTF is to supervise standards that help enable cross-platform management. In other words, MOF is a cross-platform standard with public available specifications. You don’t need PowerShell to create a .mof file, PowerShell is just a tool to create such file. You could even create a .mof file on a Unix server to manage Windows Server of vice versa!
What DSC does is creating a .mof file based on the configuration. The content of the .mof file
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
|
/* @TargetNode='A' @GeneratedBy=Me @GenerationDate=03/01/2015 11:00:53 @GenerationHost=Pullserver */ instance of MSFT_FileDirectoryConfiguration as $MSFT_FileDirectoryConfiguration1ref { ResourceID = "[File]Folder_C_Temp"; Type = "Directory"; Ensure = "Present"; SourceInfo = "::6::10::File"; DestinationPath = "C:Temp"; ModuleName = "PSDesiredStateConfiguration"; ModuleVersion = "1.0"; }; instance of OMI_ConfigurationDocument { Version="1.0.0"; Author="Me"; GenerationDate="03/01/2015 11:00:53"; GenerationHost="Pullserver"; } |
Deploy the configuration to the server:
|
PS > Start-DscConfiguration -Wait -Force -Path .ServerConfig -ServerName "A" |
The above steps are simple. First create a configuration file, converted it to a .mof file and push it to a server.
In a development environment the manual way of working is fine, but in production it certainly is not. There are two methods of deploying configuration to servers, push (as above) and pull.
For the pull method, a pull server is needed. In this configuration a server asks a pull server for its configuration and reports back the result. The Pull server can be manual installed, but why not use DSC to deploy the Pull server. To do this, download the xPSDesiredStateConfiguration Module from Technet and install it. The Pull server can be published using SMB or http(s). Https is the most versatile option, change it when needed. I used the following configuration to deploy the pull server. For simplicity this configuration does not use SSL, so I do not have to create the certificate and trust chain.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
|
configuration Pull_DscWebService { param ( [string]$NodeName = 'localhost' # Replace text with certificate thumbprint [string]$certificateThumbPrint = "AllowUnencryptedTraffic" ) Import-DSCResource -ModuleName "PSDesiredStateConfiguration" Node $NodeName { WindowsFeature DSCServiceFeature { Ensure = "Present" Name = "DSC-Service" } xDscWebService PSDSCPullServer { Ensure = "Present" EndpointName = "PSDSCPullServer" Port = 8080 PhysicalPath = "C:inetpubwwwrootPSDSCPullServer" CertificateThumbPrint = "AllowUnencryptedTraffic" ModulePath = "$env:PROGRAMFILESWindowsPowerShellDscServiceModules" ConfigurationPath = "$env:PROGRAMFILESWindowsPowerShellDscServiceConfiguration" State = "Started" DependsOn = "[WindowsFeature]DSCServiceFeature" } xDscWebService PSDSCComplianceServer { Ensure = "Present" EndpointName = "PSDSCComplianceServer" Port = 9080 PhysicalPath = "C:inetpubwwwrootPSDSCComplianceServer" CertificateThumbPrint = "AllowUnencryptedTraffic" State = "Started" IsComplianceServer = $true DependsOn = @("[WindowsFeature]DSCServiceFeature","[xDSCWebService]PSDSCPullServer") } } } Pull_DscWebService -output "." |
Activate the configuration with Start-DscConfiguration .Pull_DscWebService use -verbose to view progress of each individual action.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
|
PS > Start-DscConfiguration .Pull_DscWebService -Wait -Verbose VERBOSE: Perform operation 'Invoke CimMethod' with following parameters, ''methodName' = SendConfigurationApply,'className' = MSFT_DSCLocalConfigurationManager,'namespaceName' = root/Microsoft/Windows/DesiredStateConfiguration'. VERBOSE: An LCM method call arrived from computer . with user sid S-1-5-21-xxxxxxxxxxx. VERBOSE: [.]: LCM: [ Start Set ] VERBOSE: [.]: LCM: [ Start Resource ] [[WindowsFeature]DSCServiceFeature] VERBOSE: [.]: LCM: [ Start Test ] [[WindowsFeature]DSCServiceFeature] VERBOSE: [.]: [[WindowsFeature]DSCServiceFeature] The operation 'Get-WindowsFeature' started: DSC-Service VERBOSE: [.]: [[WindowsFeature]DSCServiceFeature] The operation 'Get-WindowsFeature' succeeded: DSC-Service VERBOSE: [.]: LCM: [ End Test ] [[WindowsFeature]DSCServiceFeature] in 0.6880 seconds. VERBOSE: [.]: LCM: [ Skip Set ] [[WindowsFeature]DSCServiceFeature] VERBOSE: [.]: LCM: [ End Resource ] [[WindowsFeature]DSCServiceFeature] VERBOSE: [.]: LCM: [ Start Resource ] [[xDSCWebService]PSDSCPullServer] VERBOSE: [.]: LCM: [ Start Test ] [[xDSCWebService]PSDSCPullServer] VERBOSE: [.]: [[xDSCWebService]PSDSCPullServer] Check Ensure VERBOSE: [.]: [[xDSCWebService]PSDSCPullServer] Check Port VERBOSE: [.]: [[xDSCWebService]PSDSCPullServer] Check Physical Path property VERBOSE: [.]: [[xDSCWebService]PSDSCPullServer] Check State VERBOSE: [.]: [[xDSCWebService]PSDSCPullServer] Get Full Path for Web.config file VERBOSE: [.]: [[xDSCWebService]PSDSCPullServer] Check ModulePath VERBOSE: [.]: [[xDSCWebService]PSDSCPullServer] Check ConfigurationPath VERBOSE: [.]: LCM: [ End Test ] [[xDSCWebService]PSDSCPullServer] in 0.0470 seconds. VERBOSE: [.]: LCM: [ Skip Set ] [[xDSCWebService]PSDSCPullServer] VERBOSE: [.]: LCM: [ End Resource ] [[xDSCWebService]PSDSCPullServer] VERBOSE: [.]: LCM: [ Start Resource ] [[xDSCWebService]PSDSCComplianceServer] VERBOSE: [.]: LCM: [ Start Test ] [[xDSCWebService]PSDSCComplianceServer] VERBOSE: [.]: [[xDSCWebService]PSDSCComplianceServer] Check Ensure VERBOSE: [.]: [[xDSCWebService]PSDSCComplianceServer] Check Port VERBOSE: [.]: [[xDSCWebService]PSDSCComplianceServer] Check Physical Path property VERBOSE: [.]: [[xDSCWebService]PSDSCComplianceServer] Check State VERBOSE: [.]: [[xDSCWebService]PSDSCComplianceServer] Get Full Path for Web.config file VERBOSE: [.]: LCM: [ End Test ] [[xDSCWebService]PSDSCComplianceServer] in 0.0150 seconds. VERBOSE: [.]: LCM: [ Skip Set ] [[xDSCWebService]PSDSCComplianceServer] VERBOSE: [.]: LCM: [ End Resource ] [[xDSCWebService]PSDSCComplianceServer] VERBOSE: [.]: LCM: [ End Set ] VERBOSE: [.]: LCM: [ End Set ] in 1.0160 seconds. VERBOSE: Operation 'Invoke CimMethod' complete. VERBOSE: Time taken for configuration job to complete is 1.084 seconds |
Test the server by browsing to to configured website http://servername:8080/PSDSCPullServer.svc. If you get a response, the pull server is working.
Now lets add some configuration to deploy in part 2.