期望状态配置
什么是期望状态配置?
期望状态配置(DSC)是 PowerShell 中内置的工具,可用于通过代码定义 Windows 主机的设置。DSC 的总体目的与 Ansible 相同,只是执行方式不同。自 Ansible 2.4 起,添加了 win_dsc
模块,可以在与 Windows 主机交互时利用现有的 DSC 资源。
有关 DSC 的更多详细信息,请参阅 DSC 概述。
主机要求
要使用 win_dsc
模块,Windows 主机必须安装 PowerShell v5.0 或更高版本。所有受支持的主机都可以升级到 PowerShell v5。
满足 PowerShell 要求后,使用 DSC 就像使用 win_dsc
模块创建任务一样简单。
为什么要使用 DSC?
DSC 和 Ansible 模块具有共同的目标,即定义并确保资源的状态。因此,可以使用 DSC 文件资源和 Ansible win_file
等资源来实现相同的结果。选择使用哪个取决于具体情况。
使用 Ansible 模块而不是 DSC 资源的原因
主机不支持 PowerShell v5.0,或者无法轻松升级
DSC 资源不提供 Ansible 模块中存在的功能。例如,win_regedit 可以管理
REG_NONE
属性类型,而 DSCRegistry
资源则不能DSC 资源对检查模式的支持有限,而某些 Ansible 模块具有更好的检查功能
DSC 资源不支持 diff 模式,而某些 Ansible 模块支持
自定义资源需要在主机上预先运行其他安装步骤,而 Ansible 模块内置于 Ansible 中
DSC 资源中存在错误,而 Ansible 模块可以正常工作
使用 DSC 资源而不是 Ansible 模块的原因
Ansible 模块不支持 DSC 资源中存在的功能
没有可用的 Ansible 模块
现有 Ansible 模块中存在错误
最后,使用 DSC 还是 Ansible 模块执行任务并不重要;重要的是任务执行正确且 playbook 仍然可读。如果您对 DSC 的经验比 Ansible 更丰富,并且它可以完成工作,那么就针对该任务使用 DSC。
如何使用 DSC?
win_dsc
模块接受自由格式的选项,以便根据它管理的资源进行更改。内置资源的列表可以在 resources 中找到。
以 Registry 资源为例,这是 Microsoft 文档中记录的 DSC 定义
Registry [string] #ResourceName
{
Key = [string]
ValueName = [string]
[ Ensure = [string] { Enable | Disable } ]
[ Force = [bool] ]
[ Hex = [bool] ]
[ DependsOn = [string[]] ]
[ ValueData = [string[]] ]
[ ValueType = [string] { Binary | Dword | ExpandString | MultiString | Qword | String } ]
}
定义任务时,必须将 resource_name
设置为正在使用的 DSC 资源 - 在这种情况下,resource_name
应设置为 Registry
。module_version
可以引用已安装的 DSC 资源的特定版本;如果留空,则默认为最新版本。其他选项是用于定义资源的参数,例如 Key
和 ValueName
。虽然任务中的选项不区分大小写,但建议保持原样,因为这样可以更容易地区分 DSC 资源选项和 Ansible 的 win_dsc
选项。
这是上述 DSC Registry 资源的 Ansible 任务版本
- name: Use win_dsc module with the Registry DSC resource
win_dsc:
resource_name: Registry
Ensure: Present
Key: HKEY_LOCAL_MACHINE\SOFTWARE\ExampleKey
ValueName: TestValue
ValueData: TestData
从 Ansible 2.8 开始,win_dsc
模块会自动使用 DSC 定义验证 Ansible 的输入选项。这意味着如果选项名称不正确、未设置强制选项或值不是有效选择,Ansible 将失败。当以 3 或更高的详细级别 (-vvv
) 运行 Ansible 时,返回值将包含基于指定的 resource_name
的可能调用选项。以下是上述 Registry
任务的调用输出示例
changed: [2016] => {
"changed": true,
"invocation": {
"module_args": {
"DependsOn": null,
"Ensure": "Present",
"Force": null,
"Hex": null,
"Key": "HKEY_LOCAL_MACHINE\\SOFTWARE\\ExampleKey",
"PsDscRunAsCredential_password": null,
"PsDscRunAsCredential_username": null,
"ValueData": [
"TestData"
],
"ValueName": "TestValue",
"ValueType": null,
"module_version": "latest",
"resource_name": "Registry"
}
},
"module_version": "1.1",
"reboot_required": false,
"verbose_set": [
"Perform operation 'Invoke CimMethod' with following parameters, ''methodName' = ResourceSet,'className' = MSFT_DSCLocalConfigurationManager,'namespaceName' = root/Microsoft/Windows/DesiredStateConfiguration'.",
"An LCM method call arrived from computer SERVER2016 with user sid S-1-5-21-3088887838-4058132883-1884671576-1105.",
"[SERVER2016]: LCM: [ Start Set ] [[Registry]DirectResourceAccess]",
"[SERVER2016]: [[Registry]DirectResourceAccess] (SET) Create registry key 'HKLM:\\SOFTWARE\\ExampleKey'",
"[SERVER2016]: [[Registry]DirectResourceAccess] (SET) Set registry key value 'HKLM:\\SOFTWARE\\ExampleKey\\TestValue' to 'TestData' of type 'String'",
"[SERVER2016]: LCM: [ End Set ] [[Registry]DirectResourceAccess] in 0.1930 seconds.",
"[SERVER2016]: LCM: [ End Set ] in 0.2720 seconds.",
"Operation 'Invoke CimMethod' complete.",
"Time taken for configuration job to complete is 0.402 seconds"
],
"verbose_test": [
"Perform operation 'Invoke CimMethod' with following parameters, ''methodName' = ResourceTest,'className' = MSFT_DSCLocalConfigurationManager,'namespaceName' = root/Microsoft/Windows/DesiredStateConfiguration'.",
"An LCM method call arrived from computer SERVER2016 with user sid S-1-5-21-3088887838-4058132883-1884671576-1105.",
"[SERVER2016]: LCM: [ Start Test ] [[Registry]DirectResourceAccess]",
"[SERVER2016]: [[Registry]DirectResourceAccess] Registry key 'HKLM:\\SOFTWARE\\ExampleKey' does not exist",
"[SERVER2016]: LCM: [ End Test ] [[Registry]DirectResourceAccess] False in 0.2510 seconds.",
"[SERVER2016]: LCM: [ End Set ] in 0.3310 seconds.",
"Operation 'Invoke CimMethod' complete.",
"Time taken for configuration job to complete is 0.475 seconds"
]
}
invocation.module_args
键显示了实际设置的值以及其他可能但未设置的值。遗憾的是,这不会显示 DSC 属性的默认值,只会显示从 Ansible 任务设置的值。出于安全原因,任何 *_password
选项都将在输出中被屏蔽;如果有任何其他敏感模块选项,请在任务上设置 no_log: True
以停止记录所有任务输出。
属性类型
每个 DSC 资源属性都有一个与其关联的类型。Ansible 将在执行期间尝试将定义的选项转换为正确的类型。对于 [string]
和 [bool]
等简单类型,这是一个简单的操作,但 [PSCredential]
或数组 (如 [string[]]
) 等复杂类型需要遵循某些规则。
PSCredential
[PSCredential]
对象用于以安全方式存储凭据,但 Ansible 无法通过 JSON 序列化它。要设置 DSC PSCredential 属性,该参数的定义应有两个条目,分别以 _username
和 _password
作为后缀,用于用户名和密码。例如
PsDscRunAsCredential_username: '{{ ansible_user }}'
PsDscRunAsCredential_password: '{{ ansible_password }}'
SourceCredential_username: AdminUser
SourceCredential_password: PasswordForAdminUser
注意
在早于 2.8 的 Ansible 版本中,应在 Ansible 的任务定义中设置 no_log: true
,以确保使用的任何凭据都不会存储在任何日志文件或控制台输出中。
[PSCredential]
在 DSC 资源 MOF 定义中以 EmbeddedInstance("MSFT_Credential")
定义。
CimInstance 类型
DSC 使用 [CimInstance]
对象来存储基于该资源定义的自定义类的字典对象。在 YAML 中定义接受 [CimInstance]
的值与在 YAML 中定义字典相同。例如,要在 Ansible 中定义 [CimInstance]
值
# [CimInstance]AuthenticationInfo == DSC_WebAuthenticationInformation
AuthenticationInfo:
Anonymous: false
Basic: true
Digest: false
Windows: true
在上面的示例中,CIM 实例是类 DSC_WebAuthenticationInformation 的表示形式。此类接受四个布尔变量:Anonymous
、Basic
、Digest
和 Windows
。[CimInstance]
中使用的键取决于它所代表的类。请仔细阅读资源文档,以确定可以使用的键以及每个键值的类型。类定义通常位于 <resource name>.schema.mof
中。
HashTable 类型
一个 [HashTable]
对象也是一个字典,但它没有可以/需要定义的严格的键集。像一个 [CimInstance]
一样,在 YAML 中将其定义为普通的字典值。[HashTable]
在 DSC 资源 MOF 定义中使用 EmbeddedInstance("MSFT_KeyValuePair")
定义。
数组
像 [string[]]
或 [UInt32[]]
这样的简单类型数组被定义为一个列表或一个逗号分隔的字符串,然后将其转换为它们的类型。建议使用列表,因为这些值在传递给 DSC 引擎之前不会被 win_dsc
模块手动解析。例如,要在 Ansible 中定义一个简单类型数组:
# [string[]]
ValueData: entry1, entry2, entry3
ValueData:
- entry1
- entry2
- entry3
# [UInt32[]]
ReturnCode: 0,3010
ReturnCode:
- 0
- 3010
像 [CimInstance[]]
(字典数组)这样的复杂类型数组可以像以下示例一样定义:
# [CimInstance[]]BindingInfo == DSC_WebBindingInformation
BindingInfo:
- Protocol: https
Port: 443
CertificateStoreName: My
CertificateThumbprint: C676A89018C4D5902353545343634F35E6B3A659
HostName: DSCTest
IPAddress: '*'
SSLFlags: 1
- Protocol: http
Port: 80
IPAddress: '*'
上面的示例是一个数组,其中包含类 DSC_WebBindingInformation 的两个值。定义 [CimInstance[]]
时,请务必阅读资源文档,以了解在定义中要使用哪些键。
DateTime
[DateTime]
对象是一个 DateTime 字符串,表示 ISO 8601 日期时间格式的日期和时间。 [DateTime]
字段的值应在 YAML 中用引号引起来,以确保该字符串被正确序列化到 Windows 主机。以下是如何在 Ansible 中定义 [DateTime]
值的示例:
# As UTC-0 (No timezone)
DateTime: '2019-02-22T13:57:31.2311892+00:00'
# As UTC+4
DateTime: '2019-02-22T17:57:31.2311892+04:00'
# As UTC-4
DateTime: '2019-02-22T09:57:31.2311892-04:00'
上面的所有值都等于 2019 年 2 月 22 日下午 1:57,精确到 31 秒和 2311892 毫秒的 UTC 日期时间。
以其他用户身份运行
默认情况下,DSC 以 SYSTEM 帐户而不是 Ansible 用于运行模块的帐户运行每个资源。这意味着基于用户配置文件动态加载的资源,如 HKEY_CURRENT_USER
注册表配置单元,将在 SYSTEM
配置文件下加载。参数 PsDscRunAsCredential
是一个可以为每个 DSC 资源设置的参数,强制 DSC 引擎以不同的帐户运行。由于 PsDscRunAsCredential
的类型为 PSCredential
,因此它使用 _username
和 _password
后缀定义。
以注册表资源类型为例,以下是如何定义一个任务以访问 Ansible 用户的 HKEY_CURRENT_USER
配置单元:
- name: Use win_dsc with PsDscRunAsCredential to run as a different user
win_dsc:
resource_name: Registry
Ensure: Present
Key: HKEY_CURRENT_USER\ExampleKey
ValueName: TestValue
ValueData: TestData
PsDscRunAsCredential_username: '{{ ansible_user }}'
PsDscRunAsCredential_password: '{{ ansible_password }}'
no_log: true
自定义 DSC 资源
DSC 资源不限于 Microsoft 的内置选项。可以安装自定义模块来管理通常不可用的其他资源。
查找自定义 DSC 资源
您可以使用 PSGallery 来查找自定义资源,以及有关如何在 Windows 主机上安装它们的文档。
Find-DscResource
cmdlet 也可用于查找自定义资源。例如:
# Find all DSC resources in the configured repositories
Find-DscResource
# Find all DSC resources that relate to SQL
Find-DscResource -ModuleName "*sql*"
注意
Microsoft 开发的以 x
开头的 DSC 资源意味着该资源是实验性的,不提供任何支持。
安装自定义资源
有三种方法可以在主机上安装 DSC 资源:
使用
Install-Module
cmdlet 手动安装使用
win_psmodule
Ansible 模块手动保存模块并将其复制到另一台主机
以下是使用 win_psmodule
安装 xWebAdministration
资源的示例:
- name: Install xWebAdministration DSC resource
win_psmodule:
name: xWebAdministration
state: present
安装后,win_dsc 模块将能够通过使用 resource_name
选项引用该资源来使用它。
上面的前两种方法仅在主机可以访问互联网时才有效。当主机无法访问互联网时,必须先使用上述方法在另一台可以访问互联网的主机上安装模块,然后再复制过来。要将模块保存到本地文件路径,可以运行以下 PowerShell cmdlet:
Save-Module -Name xWebAdministration -Path C:\temp
这将在 C:\temp
中创建一个名为 xWebAdministration
的文件夹,可以将其复制到任何主机。为了使 PowerShell 可以看到此脱机资源,必须将其复制到 PSModulePath
环境变量中设置的目录。在大多数情况下,路径 C:\Program Files\WindowsPowerShell\Module
通过此变量设置,但 win_path
模块可用于添加不同的路径。
示例
解压缩 zip 文件
- name: Extract a zip file
win_dsc:
resource_name: Archive
Destination: C:\temp\output
Path: C:\temp\zip.zip
Ensure: Present
创建目录
- name: Create file with some text
win_dsc:
resource_name: File
DestinationPath: C:\temp\file
Contents: |
Hello
World
Ensure: Present
Type: File
- name: Create directory that is hidden is set with the System attribute
win_dsc:
resource_name: File
DestinationPath: C:\temp\hidden-directory
Attributes: Hidden,System
Ensure: Present
Type: Directory
与 Azure 交互
- name: Install xAzure DSC resources
win_psmodule:
name: xAzure
state: present
- name: Create virtual machine in Azure
win_dsc:
resource_name: xAzureVM
ImageName: a699494373c04fc0bc8f2bb1389d6106__Windows-Server-2012-R2-201409.01-en.us-127GB.vhd
Name: DSCHOST01
ServiceName: ServiceName
StorageAccountName: StorageAccountName
InstanceSize: Medium
Windows: true
Ensure: Present
Credential_username: '{{ ansible_user }}'
Credential_password: '{{ ansible_password }}'
设置 IIS 网站
- name: Install xWebAdministration module
win_psmodule:
name: xWebAdministration
state: present
- name: Install IIS features that are required
win_dsc:
resource_name: WindowsFeature
Name: '{{ item }}'
Ensure: Present
loop:
- Web-Server
- Web-Asp-Net45
- name: Setup web content
win_dsc:
resource_name: File
DestinationPath: C:\inetpub\IISSite\index.html
Type: File
Contents: |
<html>
<head><title>IIS Site</title></head>
<body>This is the body</body>
</html>
Ensure: present
- name: Create new website
win_dsc:
resource_name: xWebsite
Name: NewIISSite
State: Started
PhysicalPath: C:\inetpub\IISSite\index.html
BindingInfo:
- Protocol: https
Port: 8443
CertificateStoreName: My
CertificateThumbprint: C676A89018C4D5902353545343634F35E6B3A659
HostName: DSCTest
IPAddress: '*'
SSLFlags: 1
- Protocol: http
Port: 8080
IPAddress: '*'
AuthenticationInfo:
Anonymous: false
Basic: true
Digest: false
Windows: true
另请参阅
- Ansible playbook
playbook 简介
- Ansible 技巧和诀窍
playbook 的技巧和窍门
- Windows 模块列表
特定于 Windows 的模块列表,全部以 PowerShell 实现
- 沟通
有疑问?需要帮助?想分享您的想法?请访问 Ansible 沟通指南