设置 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

有关更多详细信息,请参阅“Out of memory” error on a computer that has a customized MaxMemoryPerShellMB quota set and has WMF 3.0 installed文章。

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 监听器

  • 使用winrm quickconfig(用于 HTTP)或winrm quickconfig -transport:https(用于 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 - 指定通道绑定令牌是否未验证(无)、验证但不要求(宽松)或验证并要求(严格)。CBT 仅在使用 NT LAN Manager (NTLM) 或 Kerberos 通过 HTTPS 连接时使用。

  • 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 命令执行连接测试以排除此问题。

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

  • 如果通过 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 侦听器。

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

连接被拒绝错误

当您与主机上的 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。Windows 10 1809 版本及更高版本可安装 OpenSSH 客户端。Windows Server 2019 及更高版本可安装 OpenSSH 服务器。

有关详细信息,请参阅 Windows OpenSSH 入门

安装 Win32-OpenSSH

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

  • 按照 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
  • 在您的剧本中使用该角色

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

注意

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

配置 Win32-OpenSSH shell

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

  • 要配置其他 shell,请使用 Ansible 剧本,其中包含一个任务来定义注册表设置

- 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 身份验证

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

对于基于密钥的身份验证

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

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

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

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

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

为 Windows 上的 SSH 配置 Ansible

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

  • 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 剧本

剧本简介

Ansible 提示和技巧

剧本的技巧和窍门

Windows 模块列表

Windows 特定模块列表,全部在 PowerShell 中实现

用户邮件列表

有问题吗?访问 Google 群组!

实时聊天

如何加入 Ansible 聊天频道