所需状态配置
什么是所需状态配置?
所需状态配置(或 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 或更高的详细级别运行 Ansible(-vvv
)时,返回值将包含基于指定的 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
注意
在 Ansible 2.8 之前的版本上,您应该在 Ansible 的任务定义中设置 no_log: true
,以确保使用的任何凭据都不会存储在任何日志文件或控制台输出中。
[PSCredential]
在 DSC 资源 MOF 定义中使用 EmbeddedInstance("MSFT_Credential")
定义。
CimInstance 类型
DSC 使用 [CimInstance]
对象来存储基于该资源定义的自定义类的字典对象。在 YAML 中定义一个接受 [CimInstance]
的值与在 YAML 中定义字典相同。例如,要在 Ansible 中定义 [CimInstance]
值
# [CimInstance]AuthenticationInfo == MSFT_xWebAuthenticationInformation
AuthenticationInfo:
Anonymous: false
Basic: true
Digest: false
Windows: true
在上面的示例中,CIM 实例是类 MSFT_xWebAuthenticationInformation 的表示。此类接受四个布尔变量: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 == MSFT_xWebBindingInformation
BindingInfo:
- Protocol: https
Port: 443
CertificateStoreName: My
CertificateThumbprint: C676A89018C4D5902353545343634F35E6B3A659
HostName: DSCTest
IPAddress: '*'
SSLFlags: 1
- Protocol: http
Port: 80
IPAddress: '*'
上面的示例是一个包含两个 MSFT_xWebBindingInformation 类值的数组。定义 [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'
上面的所有值都等于 UTC 日期时间 2019 年 2 月 22 日下午 1:57,其中包含 31 秒和 2311892 毫秒。
以其他用户身份运行
默认情况下,DSC 将每个资源作为 SYSTEM 帐户而不是 Ansible 用于运行模块的帐户运行。这意味着根据用户配置文件动态加载的资源(例如 HKEY_CURRENT_USER
注册表项)将在 SYSTEM
配置文件下加载。参数 PsDscRunAsCredential
是可以为每个 DSC 资源设置的参数,并强制 DSC 引擎在不同的帐户下运行。由于 PsDscRunAsCredential
的类型为 PSCredential
,因此使用 _username
和 _password
后缀定义。
以 Registry 资源类型为例,以下是如何定义一个任务来访问 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 剧本
剧本简介
- Ansible 技巧和窍门
剧本的技巧和诀窍
- Windows 模块列表
特定于 Windows 的模块列表,全部在 PowerShell 中实现
- 沟通
有疑问?需要帮助?想分享您的想法?请访问 Ansible 通信指南