适用于 PowerShell 5.1 及以上版本(Windows),DSC 需要 Windows 管理框架
Desired State Configuration(DSC)是 PowerShell 的声明式配置管理框架——你定义系统”应该是什么状态”,DSC 负责将系统调整到目标状态。与命令式脚本(”执行这些步骤”)不同,DSC 声明期望结果(”安装这些角色、创建这些文件、启动这些服务”),引擎自动判断需要做什么。这使得配置管理具有幂等性和可审计性。
本文将讲解 DSC 的核心概念、配置编写,以及实用的服务器配置场景。
DSC 配置基础
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 48 49 50 51 52 53 54
| Configuration WebServerSetup { param([string[]]$MachineName = "localhost")
Node $MachineName { WindowsFeature IIS { Ensure = "Present" Name = "Web-Server" IncludeAllSubFeature = $true }
WindowsFeature WebMgmtTools { Ensure = "Present" Name = "Web-Mgmt-Tools" DependsOn = "[WindowsFeature]IIS" }
File WebsiteRoot { Ensure = "Present" DestinationPath = "C:\inetpub\MyApp" Type = "Directory" }
File DefaultPage { Ensure = "Present" DestinationPath = "C:\inetpub\MyApp\default.htm" Contents = @" <!DOCTYPE html> <html> <head><title>MyApp</title></head> <body><h1>MyApp Running</h1><p>DSC Configured</p></body> </html> "@ DependsOn = "[File]WebsiteRoot" }
Service W3SVC { Name = "W3SVC" State = "Running" StartupType = "Automatic" DependsOn = "[WindowsFeature]IIS" } } }
WebServerSetup -OutputPath "C:\DSC\WebServer"
Write-Host "配置已编译,MOF 文件位于 C:\DSC\WebServer" -ForegroundColor Green
|
执行结果示例:
1 2 3 4 5 6
|
---- ------------- ------ ---- ----- --.
|
应用与测试配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| Start-DscConfiguration -Path "C:\DSC\WebServer" -Wait -Verbose -Force
Test-DscConfiguration -Path "C:\DSC\WebServer"
Get-DscConfigurationStatus | Select-Object Status, StartDate, Type, Mode | Format-List
Get-DscConfiguration | Select-Object ConfigurationName, ResourceInstanceName, ResourceModuleName | Format-Table -AutoSize
|
执行结果示例:
1 2 3 4 5 6 7 8 9 10 11
| PSComputerName ResourceName InDesiredState localhost WindowsFeature True localhost WindowsFeature True localhost File True localhost File True localhost Service True
Status : Success StartDate : 2025-07-24 08:30:15 Type : Initial Mode : Push
|
完整服务器配置
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 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
| Configuration ProductionWebServer { param( [string[]]$NodeName = "localhost", [string]$WebsitePath = "C:\inetpub\MyApp", [string]$LogPath = "C:\Logs\MyApp" )
Import-DscResource -ModuleName PSDesiredStateConfiguration Import-DscResource -ModuleName NetworkingDsc Import-DscResource -ModuleName xWebAdministration
Node $NodeName { WindowsFeature WebServer { Ensure = "Present" Name = "Web-Server" }
WindowsFeature NetFramework { Ensure = "Present" Name = "NET-Framework-45-Core" }
File WebsiteDir { Ensure = "Present" DestinationPath = $WebsitePath Type = "Directory" }
File LogDir { Ensure = "Present" DestinationPath = $LogPath Type = "Directory" }
Registry MaxUrlLength { Ensure = "Present" Key = "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\HTTP\Parameters" ValueName = "UrlSegmentMaxLength" ValueData = "0" ValueType = "Dword" }
Script FirewallRuleHTTP { GetScript = { @{ Result = (Get-NetFirewallRule -DisplayName "HTTP" -ErrorAction SilentlyContinue).DisplayName } } SetScript = { New-NetFirewallRule -DisplayName "HTTP" -Direction Inbound -Protocol TCP -LocalPort 80 -Action Allow } TestScript = { (Get-NetFirewallRule -DisplayName "HTTP" -ErrorAction SilentlyContinue) -ne $null } }
Service W3SVC { Name = "W3SVC" State = "Running" StartupType = "Automatic" }
Service WAS { Name = "WAS" State = "Running" StartupType = "Automatic" }
LocalConfigurationManager { ConfigurationMode = "ApplyAndAutoCorrect" ConfigurationModeFrequencyMins = 30 RefreshMode = "Push" RebootNodeIfNeeded = $true } } }
ProductionWebServer -OutputPath "C:\DSC\ProductionWeb" -NodeName "SRV-WEB-01"
Start-DscConfiguration -Path "C:\DSC\ProductionWeb" -Wait -Force
Write-Host "生产服务器配置已应用" -ForegroundColor Green
|
执行结果示例:
配置漂移检测
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
| function Test-DscDrift { param([string]$ComputerName = "localhost")
$result = Test-DscConfiguration -ComputerName $ComputerName -Detailed
$inDesired = ($result.ResourcesInDesiredState | Measure-Object).Count $notInDesired = ($result.ResourcesNotInDesiredState | Measure-Object).Count
$report = [PSCustomObject]@{ Computer = $ComputerName Timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss" InDesired = $inDesired NotInDesired = $notInDesired Compliant = $notInDesired -eq 0 }
if ($notInDesired -gt 0) { Write-Host "[$($report.Timestamp)] $ComputerName : 漂移!$notInDesired 项不符合" -ForegroundColor Red $result.ResourcesNotInDesiredState | ForEach-Object { Write-Host " - $($_.ResourceId)" -ForegroundColor Yellow } } else { Write-Host "[$($report.Timestamp)] $ComputerName : 合规($inDesired 项)" -ForegroundColor Green }
return $report }
$servers = @("SRV-WEB-01", "SRV-WEB-02", "SRV-WEB-03") $reports = foreach ($server in $servers) { Test-DscDrift -ComputerName $server }
$reports | Format-Table Computer, InDesired, NotInDesired, Compliant -AutoSize
|
执行结果示例:
1 2 3 4 5 6 7 8 9 10 11
| [2025-07-24 09:00:00] SRV-WEB-01 : 合规(8 项) [2025-07-24 09:00:02] SRV-WEB-02 : 漂移!2 项不符合 - [Service]W3SVC - [File]DefaultPage [2025-07-24 09:00:04] SRV-WEB-03 : 合规(8 项)
Computer InDesired NotInDesired Compliant -------- --------- ------------ --------- SRV-WEB-01 8 0 True SRV-WEB-02 6 2 False SRV-WEB-03 8 0 True
|
注意事项
- 推送 vs 拉取:推送模式(Push)适合小规模环境,拉取模式(Pull)适合大规模环境
- 幂等性:DSC 配置应该可以重复执行而不产生副作用,使用
Test 脚本检测当前状态
- MOF 文件:MOF 文件可能包含敏感信息(密码),注意安全存储和传输
- 依赖关系:使用
DependsOn 控制资源配置顺序,避免依赖循环
- 自定义资源:内置资源不满足需求时,可以创建自定义 DSC 资源模块
- AutoCorrect 模式:
ApplyAndAutoCorrect 模式会自动修复漂移,ApplyOnly 模式只检测不修复