设置 Windows 主机

本文档讨论了 Ansible 与 Microsoft Windows 主机通信之前所需的设置。

主机要求

为了让 Ansible 与 Windows 主机通信并使用 Windows 模块,Windows 主机必须满足以下基本连接要求

  • 使用 Ansible,您通常可以管理 Microsoft 当前和扩展支持下的 Windows 版本。您还可以管理桌面操作系统,包括 Windows 10 和 11,以及服务器操作系统,包括 Windows Server 2016、2019 和 2022。

  • 您需要在 Windows 主机上安装 PowerShell 5.1 或更高版本,以及至少 .NET 4.0。

  • 您需要创建并激活 WinRM 监听器。更多详细信息,请参阅 WinRM 监听器

注意

某些 Ansible 模块有额外的要求,例如较新的操作系统或 PowerShell 版本。请查阅模块文档页面以确定主机是否满足这些要求。

升级 PowerShell 和 .NET Framework

Ansible 需要 PowerShell 版本 5.1 和 .NET Framework 4.6 或更高版本才能正常工作。较旧的不受支持的操作系统基础映像不满足这些要求。您可以使用 Upgrade-PowerShell.ps1 脚本来更新这些。

这是如何从 PowerShell 运行此脚本的示例

[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
$url = "https://raw.githubusercontent.com/jborean93/ansible-windows/master/scripts/Upgrade-PowerShell.ps1"
$file = "$env:temp\Upgrade-PowerShell.ps1"
$username = "Administrator"
$password = "Password"

(New-Object -TypeName System.Net.WebClient).DownloadFile($url, $file)
Set-ExecutionPolicy -ExecutionPolicy Unrestricted -Force

&$file -Version 5.1 -Username $username -Password $password -Verbose

在脚本中,file 值可以是 PowerShell 版本 3.0、4.0 或 5.1。

完成后,您需要运行以下 PowerShell 命令

  1. 作为可选但良好的安全实践,您可以将执行策略设置回默认值。

Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Force

对 Windows 服务器使用 RemoteSigned 值,或对 Windows 客户端使用 Restricted

  1. 删除自动登录。

$reg_winlogon_path = "HKLM:\Software\Microsoft\Windows NT\CurrentVersion\Winlogon"
Set-ItemProperty -Path $reg_winlogon_path -Name AutoAdminLogon -Value 0
Remove-ItemProperty -Path $reg_winlogon_path -Name DefaultUserName -ErrorAction SilentlyContinue
Remove-ItemProperty -Path $reg_winlogon_path -Name DefaultPassword -ErrorAction SilentlyContinue

该脚本确定您需要安装哪些程序(例如 .NET Framework 4.5.2)以及需要存在哪个 PowerShell 版本。如果需要重新启动并且设置了 usernamepassword 参数,则该脚本将自动重新启动计算机然后登录。如果未设置 usernamepassword 参数,则该脚本将提示用户在需要时手动重新启动并登录。当用户下次登录时,该脚本将从上次停止的地方继续,并且该过程将继续,直到不再需要任何操作为止。

注意

如果您在 Server 2008 上运行该脚本,则需要安装 SP2。对于 Server 2008 R2 或 Windows 7,您需要 SP1。

在 Windows Server 2008 上,您只能安装 PowerShell 3.0。较新版本会导致脚本失败。

usernamepassword 参数以纯文本形式存储在注册表中。脚本完成后,运行清理命令以确保主机上没有存储凭据。

WinRM 内存热修复

在 PowerShell v3.0 上,存在一个限制 WinRM 服务可用内存量的错误。使用 Install-WMF3Hotfix.ps1 脚本在受影响的主机上安装热修复程序,作为系统引导或映像过程的一部分。如果没有此热修复程序,Ansible 将无法在 Windows 主机上执行某些命令。

要安装热修复程序

[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
$url = "https://raw.githubusercontent.com/jborean93/ansible-windows/master/scripts/Install-WMF3Hotfix.ps1"
$file = "$env:temp\Install-WMF3Hotfix.ps1"

(New-Object -TypeName System.Net.WebClient).DownloadFile($url, $file)
powershell.exe -ExecutionPolicy ByPass -File $file -Verbose

有关更多详细信息,请参阅 “内存不足”错误,在已设置自定义 MaxMemoryPerShellMB 配额并安装了 WMF 3.0 的计算机上 文章。

WinRM 设置

您需要配置 WinRM 服务,以便 Ansible 可以连接到它。WinRM 服务有两个主要组件控制 Ansible 如何与 Windows 主机交互:listenerservice 配置设置。

注意

用于设置此服务的脚本 可在 GitHub 上下载。原因是使用它可能会给用户带来一些问题。将来很有可能会完全删除它。

WinRM 监听器

WinRM 服务在 一个或多个端口上侦听请求。每个端口都必须创建和配置一个监听器。

要查看在 WinRM 服务上运行的当前监听器

winrm enumerate winrm/config/Listener

这将输出类似以下内容

Listener
    Address = *
    Transport = HTTP
    Port = 5985
    Hostname
    Enabled = true
    URLPrefix = wsman
    CertificateThumbprint
    ListeningOn = 10.0.2.15, 127.0.0.1, 192.168.56.155, ::1, fe80::5efe:10.0.2.15%6, fe80::5efe:192.168.56.155%8, fe80::
ffff:ffff:fffe%2, fe80::203d:7d97:c2ed:ec78%3, fe80::e8ea:d765:2c69:7756%7

Listener
    Address = *
    Transport = HTTPS
    Port = 5986
    Hostname = SERVER2016
    Enabled = true
    URLPrefix = wsman
    CertificateThumbprint = E6CDAA82EEAF2ECE8546E05DB7F3E01AA47D76CE
    ListeningOn = 10.0.2.15, 127.0.0.1, 192.168.56.155, ::1, fe80::5efe:10.0.2.15%6, fe80::5efe:192.168.56.155%8, fe80::
ffff:ffff:fffe%2, fe80::203d:7d97:c2ed:ec78%3, fe80::e8ea:d765:2c69:7756%7

在上面的示例中,激活了两个监听器。一个在 HTTP 上侦听端口 5985,另一个在 HTTPS 上侦听端口 5986。一些有用的关键选项是

  • Transport:监听器是通过 HTTP 还是 HTTPS 运行。我们建议您使用 HTTPS 上的监听器,因为数据在不需要任何进一步更改的情况下进行了加密。

  • Port:监听器运行的端口。默认情况下,HTTP 为 5985,HTTPS 为 5986。此端口可以根据需要更改,并与主机变量 ansible_port 相对应。

  • URLPrefix:要侦听的 URL 前缀。默认情况下,它是 wsman。如果更改此选项,则需要将主机变量 ansible_winrm_path 设置为相同的值。

  • CertificateThumbprint:如果您使用 HTTPS 监听器,这是 Windows 证书存储中用于连接的证书的指纹。要获取证书本身的详细信息,请在 PowerShell 中使用相关的证书指纹运行此命令

$thumbprint = "E6CDAA82EEAF2ECE8546E05DB7F3E01AA47D76CE"
Get-ChildItem -Path cert:\LocalMachine\My -Recurse | Where-Object { $_.Thumbprint -eq $thumbprint } | Select-Object *

设置 WinRM 监听器

有三种方法可以设置 WinRM 监听器

  • 对 HTTP 使用 winrm quickconfig,或对 HTTPS 使用 winrm quickconfig -transport:https。当在域环境之外运行时,需要简单的监听器时,这是最容易使用的选项。与其他选项不同,此过程还具有为所需端口打开防火墙并启动 WinRM 服务的额外好处。

  • 使用组策略对象 (GPO)。当主机是域的成员时,这是创建监听器的最佳方法,因为配置会自动完成,而无需任何用户输入。有关组策略对象的更多信息,请参阅 组策略对象文档

  • 使用 PowerShell 创建具有特定配置的监听器。这可以通过运行以下 PowerShell 命令来完成

    $selector_set = @{
        Address = "*"
        Transport = "HTTPS"
    }
    $value_set = @{
        CertificateThumbprint = "E6CDAA82EEAF2ECE8546E05DB7F3E01AA47D76CE"
    }
    
    New-WSManInstance -ResourceURI "winrm/config/Listener" -SelectorSet $selector_set -ValueSet $value_set
    

    要查看此 PowerShell 命令的其他选项,请参阅 New-WSManInstance 文档。

注意

创建 HTTPS 监听器时,必须在 LocalMachine\My 证书存储区中创建并存储证书。

删除 WinRM 监听器

  • 要删除所有 WinRM 监听器

Remove-Item -Path WSMan:\localhost\Listener\* -Recurse -Force
  • 要仅删除通过 HTTPS 运行的那些监听器

Get-ChildItem -Path WSMan:\localhost\Listener | Where-Object { $_.Keys -contains "Transport=HTTPS" } | Remove-Item -Recurse -Force

注意

Keys 对象是一个字符串数组,因此可以包含不同的值。默认情况下,它包含 Transport=Address= 的键,它们对应于 winrm enumerate winrm/config/Listeners 命令中的值。

WinRM 服务选项

您可以控制 WinRM 服务组件的行为,包括身份验证选项和内存设置。

要获取当前服务配置选项的输出,请运行以下命令

winrm get winrm/config/Service
winrm get winrm/config/Winrs

这将输出类似以下内容

Service
    RootSDDL = O:NSG:BAD:P(A;;GA;;;BA)(A;;GR;;;IU)S:P(AU;FA;GA;;;WD)(AU;SA;GXGW;;;WD)
    MaxConcurrentOperations = 4294967295
    MaxConcurrentOperationsPerUser = 1500
    EnumerationTimeoutms = 240000
    MaxConnections = 300
    MaxPacketRetrievalTimeSeconds = 120
    AllowUnencrypted = false
    Auth
        Basic = true
        Kerberos = true
        Negotiate = true
        Certificate = true
        CredSSP = true
        CbtHardeningLevel = Relaxed
    DefaultPorts
        HTTP = 5985
        HTTPS = 5986
    IPv4Filter = *
    IPv6Filter = *
    EnableCompatibilityHttpListener = false
    EnableCompatibilityHttpsListener = false
    CertificateThumbprint
    AllowRemoteAccess = true

Winrs
    AllowRemoteShellAccess = true
    IdleTimeout = 7200000
    MaxConcurrentUsers = 2147483647
    MaxShellRunTime = 2147483647
    MaxProcessesPerShell = 2147483647
    MaxMemoryPerShellMB = 2147483647
    MaxShellsPerUser = 2147483647

您无需更改这些选项中的大多数。但是,需要了解一些重要的选项是

  • Service\AllowUnencrypted - 指定 WinRM 是否允许不进行消息加密的 HTTP 流量。只有当 ansible_winrm_transport 变量为 ntlmkerberoscredssp 时,消息级加密才有可能。默认情况下,此值为 false,您只应在调试 WinRM 消息时将其设置为 true

  • Service\Auth\* - 定义您可以与 WinRM 服务一起使用的身份验证选项。默认情况下,启用 Negotiate (NTLM)Kerberos

  • Service\Auth\CbtHardeningLevel - 指定是否不验证通道绑定令牌(None),验证但不要求(Relaxed),或验证且要求(Strict)。只有在使用 NT LAN Manager (NTLM) 或 Kerberos 通过 HTTPS 连接时才使用 CBT。

  • Service\CertificateThumbprint - 用于加密 CredSSP 身份验证的 TLS 通道的证书指纹。默认情况下,此值为空。当 WinRM 服务启动时,会生成自签名证书,并在 TLS 进程中使用。

  • Winrs\MaxShellRunTime - 允许远程命令执行的最大时间(以毫秒为单位)。

  • Winrs\MaxMemoryPerShellMB - 每个 shell(包括其子进程)分配的最大内存量。

要在 PowerShell 中修改 Service 键下的设置,您需要在 winrm/config/Service 之后提供选项的路径

Set-Item -Path WSMan:\localhost\Service\{path} -Value {some_value}

例如,要更改 Service\Auth\CbtHardeningLevel

Set-Item -Path WSMan:\localhost\Service\Auth\CbtHardeningLevel -Value Strict

要在 PowerShell 中修改 Winrs 键下的设置,您需要在 winrm/config/Winrs 之后提供选项的路径

Set-Item -Path WSMan:\localhost\Shell\{path} -Value {some_value}

例如,要更改 Winrs\MaxShellRunTime

Set-Item -Path WSMan:\localhost\Shell\MaxShellRunTime -Value 2147483647

注意

如果在域环境中运行命令,则其中一些选项由 GPO 设置,并且无法在主机本身上更改。当您使用 GPO 配置键时,它会在值旁边包含文本 [Source="GPO"]

常见的 WinRM 问题

WinRM 有大量的配置选项,这使得其配置变得复杂。因此,Ansible 显示的错误实际上可能是主机设置的问题。

要识别主机问题,请从另一台 Windows 主机运行以下命令以连接到目标 Windows 主机。

  • 要测试 HTTP

winrs -r:http://server:5985/wsman -u:Username -p:Password ipconfig
  • 要测试 HTTPS

winrs -r:https://server:5986/wsman -u:Username -p:Password -ssl ipconfig

如果证书不可验证,则该命令将失败。

  • 要测试 HTTPS,忽略证书验证

$username = "Username"
$password = ConvertTo-SecureString -String "Password" -AsPlainText -Force
$cred = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $username, $password

$session_option = New-PSSessionOption -SkipCACheck -SkipCNCheck -SkipRevocationCheck
Invoke-Command -ComputerName server -UseSSL -ScriptBlock { ipconfig } -Credential $cred -SessionOption $session_option

如果上述任何命令失败,则问题可能与 WinRM 设置有关。

HTTP 401/凭据被拒绝

HTTP 401 错误表示初始连接期间身份验证过程失败。您可以检查以下内容以进行故障排除

  • 凭据正确,并在清单中使用 ansible_useransible_password 变量正确设置。

  • 该用户是本地 Administrators 组的成员,或者已被明确授予访问权限。您可以使用 winrs 命令执行连接测试以排除此问题。

  • Service\Auth\* 下启用了 ansible_winrm_transport 变量设置的身份验证选项。

  • 如果在 HTTP 而不是 HTTPS 上运行,请使用 ntlmkerberoscredssp 以及 ansible_winrm_message_encryption: auto 自定义清单变量以启用消息加密。如果您使用其他身份验证选项,或者无法升级已安装的 pywinrm 包,则可以将 Service\AllowUnencrypted 设置为 true。仅建议用于故障排除。

  • 下游包 pywinrmrequests-ntlmrequests-kerberos 和/或 requests-credssp 使用 pip 更新。

  • 对于 Kerberos 身份验证,请确保 Service\Auth\CbtHardeningLevel 未设置为 Strict

  • 对于基本或证书身份验证,请确保该用户是本地帐户。域帐户不适用于基本和证书身份验证。

HTTP 500 错误

HTTP 500 错误表示 WinRM 服务存在问题。您可以检查以下内容以进行故障排除

  • 您当前打开的 shell 数没有超过 WinRsMaxShellsPerUser。或者,您没有超出任何其他 Winrs 配额。

超时错误

有时 Ansible 无法访问主机。这些实例通常表示网络连接存在问题。您可以检查以下内容以进行故障排除

  • 防火墙未设置为阻止配置的 WinRM 监听器端口。

  • 在主机变量设置的端口和路径上启用了 WinRM 监听器。

  • winrm 服务正在 Windows 主机上运行,并配置为自动启动。

连接被拒绝错误

当您与主机上的 WinRM 服务通信时,您可能会遇到一些问题。检查以下内容以帮助进行故障排除

  • WinRM 服务在主机上启动并运行。使用 (Get-Service -Name winrm).Status 命令获取服务状态。

  • 主机防火墙允许通过 WinRM 端口传输流量。默认情况下,HTTP 为 5985,HTTPS 为 5986

有时,安装程序可能会重新启动 WinRM 或 HTTP 服务,并导致此错误。解决此问题的最佳方法是使用另一台 Windows 主机的 win_psexec 模块。

加载内置模块失败

有时,PowerShell 会失败并显示类似于以下内容的错误消息

The 'Out-String' command was found in the module 'Microsoft.PowerShell.Utility', but the module could not be loaded.

在这种情况下,尝试访问 PSModulePath 环境变量指定的所有路径时可能会出现问题。

此问题的一个常见原因是 PSModulePath 包含指向文件共享的通用命名约定 (UNC) 路径。此外,双跳/凭据委派问题会导致 Ansible 进程无法访问这些文件夹。要解决此问题,请执行以下任一操作

  • PSModulePath 中删除 UNC 路径。

  • 使用支持凭据委派的身份验证选项,如 credsspkerberos。您需要启用凭据委派。

有关此问题的更多信息,请参阅 KB4076842

Windows SSH 设置

Ansible 2.8 为 Windows 管理的节点添加了实验性的 SSH 连接。

警告

使用此功能,风险自负!将 SSH 与 Windows 结合使用是实验性的。此实现可能会在未来的版本中进行向后不兼容的更改。服务器端组件的可靠性可能会因您安装的版本而异。

使用 Windows 设置安装 OpenSSH

您可以使用 OpenSSH 将 Windows 10 客户端连接到 Windows Server 2019。OpenSSH 客户端可在 Windows 10 版本 1809 及更高版本上安装。OpenSSH 服务器可在 Windows Server 2019 及更高版本上安装。

有关更多信息,请参阅开始使用 Windows 版 OpenSSH

安装 Win32-OpenSSH

要安装用于 Ansible 的 Win32-OpenSSH 服务,请选择以下安装选项之一

  • 按照 Microsoft 提供的安装说明,手动安装 Win32-OpenSSH

  • 使用 Chocolatey

choco install --package-parameters=/SSHServerFeature openssh
  • 使用 win_chocolatey Ansible 模块

- name: install the Win32-OpenSSH service
  win_chocolatey:
    name: openssh
    package_params: /SSHServerFeature
    state: present
ansible-galaxy install jborean93.win_openssh
  • 在您的 playbook 中使用该角色

- name: install Win32-OpenSSH service
  hosts: windows
  gather_facts: false
  roles:
  - role: jborean93.win_openssh
    opt_openssh_setup_service: True

注意

Win32-OpenSSH 仍处于 Beta 测试阶段,并且不断更新以包含新功能和错误修复。如果您使用 SSH 作为 Windows 的连接选项,我们强烈建议您安装最新版本。

配置 Win32-OpenSSH shell

默认情况下,Win32-OpenSSH 使用 cmd.exe 作为 shell。

  • 要配置不同的 shell,请使用 Ansible playbook,其中包含一个用于定义注册表设置的任务

- name: set the default shell to PowerShell
  win_regedit:
    path: HKLM:\SOFTWARE\OpenSSH
    name: DefaultShell
    data: C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe
    type: string
    state: present
  • 要将设置恢复为默认 shell

- name: set the default shell to cmd
  win_regedit:
    path: HKLM:\SOFTWARE\OpenSSH
    name: DefaultShell
    state: absent

Win32-OpenSSH 身份验证

Windows 的 Win32-OpenSSH 身份验证类似于 Unix/Linux 主机上的 SSH 身份验证。您可以使用纯文本密码或 SSH 公钥身份验证。

对于基于密钥的身份验证

  • 将您的公钥添加到用户配置文件目录的 .ssh 文件夹中的 authorized_key 文件中。

  • 使用 sshd_config 文件配置 SSH 服务。

当使用 Ansible 的 SSH 密钥身份验证时,远程会话将无法访问用户凭据,并且在尝试访问网络资源时会失败。这也称为双跳或凭据委托问题。要解决此问题

  • 通过设置 ansible_password 变量来使用纯文本密码身份验证。

  • 在需要访问远程资源的用户凭据的任务上使用 become 指令。

配置 Ansible 以在 Windows 上使用 SSH

要配置 Ansible 以将 SSH 用于 Windows 主机,您必须设置两个连接变量

  • ansible_connection 设置为 ssh

  • ansible_shell_type 设置为 cmdpowershell

ansible_shell_type 变量应反映 Windows 主机上配置的 DefaultShell。对于默认 shell,请将 ansible_shell_type 设置为 cmd。或者,如果您将 DefaultShell 更改为 PowerShell,则将 ansible_shell_type 设置为 powershell

Windows 上使用 SSH 的已知问题

在 Windows 上使用 SSH 尚处于试验阶段。目前,存在的问题是

  • powershell 是 shell 类型时,旧于 v7.9.0.0p1-Beta 的 Win32-OpenSSH 版本无法工作。

  • 虽然安全复制协议 (SCP) 应该可以工作,但 SSH 文件传输协议 (SFTP) 是复制或获取文件时推荐使用的机制。

另请参阅

Ansible playbook

Playbook 简介

Ansible 提示和技巧

Playbook 的技巧和诀窍

Windows 模块列表

Windows 特定模块列表,全部使用 PowerShell 实现

交流

有疑问?需要帮助?想分享你的想法?请访问 Ansible 交流指南