WinRM 通信器
通信器(Communicators) 是 Packer 用来向创建的机器上上传文件、执行脚本等的机制。WinRM 通信器使用 Windows 远程管理协议(Windows Remote Management protocol)来执行此操作。
使用 WinRM 通信器的准备
WinRM 通信器不是默认的通信器,因此您始终必须明确设置 "communicator": "winrm",
模板选项。除此之外,您几乎总是必须提供一个预运行脚本,用于在来宾计算机上启用和配置 WinRM。这通常采用 PowerShell 脚本或批处理文件的形式。
如果您从全新且未配置的操作系统镜像构建,则需要将此预运行脚本作为 Autounattend.xml 文件的一部分提供,这是 Windows 自动安装操作系统所必需的。如果您在云上或从预装的镜像构建,您提供此预运行脚本的方法将因构建器而异。有关如何提供 winrm 配置脚本的更多信息,请参阅每个构建器的文档。
如果您不熟悉如何使用 autounattend 文件,请查看我们的快速指南;了解如何自动初始化操作系统对于成功使用 Packer 从 iso 构建至关重要。
WinRM 通信器选项
winrm_username
(string)- 用于连接到 WinRM 的用户名。winrm_password
(string)- 用于连接到 WinRM 的密码。winrm_host
(string)- WinRM 要连接的地址。 注意:如果使用 Amazon EBS 构建器,您可以指定 WinRM 通过ssh_interface
连接的接口winrm_no_proxy
(bool) - 将此设置为true
将远程host:port
添加到NO_PROXY
环境变量。这可以连接到远程主机时绕过所有配置的代理。默认为false
。winrm_port
(int) - 要连接的 WinRM 端口。当winrm_use_ssl
设置为true
时,普通未加密连接默认为5985
,SSL 默认为5986
。winrm_timeout
(duration string | ex:"1h5m2s"
) - 等待 WinRM 可用的时间量。默认为"30m"
,因为设置 Windows 机器通常需要很长时间。winrm_use_ssl
(bool) - 如果为true
,则对 WinRM 使用 HTTPS。winrm_insecure
(bool) - 如果为true
,则不检查服务器证书链和主机名。winrm_use_ntlm
(bool) - 如果为true
,WinRM 将启用 NTLMv2 身份验证(具有会话安全性),而不是默认值(基本身份验证),从而消除了在发起连接的目标来宾机器上启用基本身份验证的要求。可以在此处.aspx)找到有关远程连接身份验证的进一步阅读。
例子
WinRM 连接基础
请注意,WinRM 不是 Packer 特有的协议。 Microsoft 有大量关于 WinRM 的文档。如果您在阅读本指南后发现仍然无法通过 WinRM 进行连接,请查看 Microsoft 文档以确保没有遗漏任何内容。
为了使 Packer 能够通过 WinRM 进行连接,您通常需要执行一些步骤:
- 设置 Packer 连接用的用户名和密码。
- 对注册表进行必要的设置以启用远程执行(如果需要,还可以启用提权的远程执行)
- 启动 WinRM,对设置进行必要的修改以允许基本身份验证
- 根据您的连接方式打开端口
5985
和/或5986
- 启动 WinRM 并将其设置为在计算机重新启动时自动启动
- 如有必要,生成自签名证书或向 WinRM 侦听器提供真实证书。
在 VMWare 中配置 WinRM
如果您使用 Autounattend.xml 配置 WinRM,设置 WinRM 的最简单方法是像这样将配置命令直接放入 Autounattend 文件中。
您还可以将一个批处理文件添加到您的 autounattend,而不是单独输入每一行,其中包含用于配置 winrm 的命令。根据您的 winrm 设置,这可能是一个复杂的批处理文件,也可能是一个非常简单的批处理文件。
下面是我们如何从 Autounattend 文件中调用批处理文件的示例:
<FirstLogonCommands>
...
<SynchronousCommand wcm:action="add">
<CommandLine>cmd.exe /c a:\winrmConfig.bat</CommandLine>
<Description>Configure WinRM</Description>
<Order>3</Order>
<RequiresUserInput>true</RequiresUserInput>
</SynchronousCommand>
...
</FirstLogonCommands>
也可以用类似的方式调用 PowerShell 脚本。
上面引用的 winrmConfig.bat
可以很简单:
rem basic config for winrm
cmd.exe /c winrm quickconfig -q
rem allow unencrypted traffic, and configure auth to use basic username/password auth
cmd.exe /c winrm set winrm/config/service @{AllowUnencrypted="true"}
cmd.exe /c winrm set winrm/config/service/auth @{Basic="true"}
rem update firewall rules to open the right port and to allow remote administration
cmd.exe /c netsh advfirewall firewall set rule group="remote administration" new enable=yes
rem restart winrm
cmd.exe /c net stop winrm
cmd.exe /c net start winrm
请注意,上面的批处理文件是极度简化的,而且不安全,它只是提供了一个刚好能够运行的例子。下面,我们将提供一个更安全也更复杂的 WinRM 配置过程的示例。
此批处理文件仅适用于 HTTP 连接,不适用于 HTTPS,但可让您仅使用之前在 Autounattend 文件中创建的用户名和密码进行连接。下面的批处理文件将允许您使用非常简单的 Packer 配置进行连接:
"communicator": "winrm",
"winrm_username": "packeruser",
"winrm_password": "SecretPassword"
下面是一个更复杂的用于配置的 PowerShell 脚本示例:
# A Packer config that works with this example would be:
#
#
# "winrm_username": "Administrator",
# "winrm_password": "SuperS3cr3t!!!",
# "winrm_insecure": true,
# "winrm_use_ssl": true
#
#
# Create username and password
net user Administrator SuperS3cr3t!!!
wmic useraccount where "name='Administrator'" set PasswordExpires=FALSE
Set-ExecutionPolicy Unrestricted -Scope LocalMachine -Force -ErrorAction Ignore
# Don't set this before Set-ExecutionPolicy as it throws an error
$ErrorActionPreference = "stop"
# Remove HTTP listener
Remove-Item -Path WSMan:\Localhost\listener\listener* -Recurse
# Create a self-signed certificate to let ssl work
$Cert = New-SelfSignedCertificate -CertstoreLocation Cert:\LocalMachine\My -DnsName "packer"
New-Item -Path WSMan:\LocalHost\Listener -Transport HTTPS -Address * -CertificateThumbPrint $Cert.Thumbprint -Force
# WinRM
write-output "Setting up WinRM"
write-host "(host) setting up WinRM"
# Configure WinRM to allow unencrypted communication, and provide the
# self-signed cert to the WinRM listener.
cmd.exe /c winrm quickconfig -q
cmd.exe /c winrm set "winrm/config/service" '@{AllowUnencrypted="true"}'
cmd.exe /c winrm set "winrm/config/client" '@{AllowUnencrypted="true"}'
cmd.exe /c winrm set "winrm/config/service/auth" '@{Basic="true"}'
cmd.exe /c winrm set "winrm/config/client/auth" '@{Basic="true"}'
cmd.exe /c winrm set "winrm/config/service/auth" '@{CredSSP="true"}'
cmd.exe /c winrm set "winrm/config/listener?Address=*+Transport=HTTPS" "@{Port=`"5986`";Hostname=`"packer`";CertificateThumbprint=`"$($Cert.Thumbprint)`"}"
# Make sure appropriate firewall port openings exist
cmd.exe /c netsh advfirewall firewall set rule group="remote administration" new enable=yes
cmd.exe /c netsh firewall add portopening TCP 5986 "Port 5986"
# Restart WinRM, and set it so that it auto-launches on startup.
cmd.exe /c net stop winrm
cmd.exe /c sc config winrm start= auto
cmd.exe /c net start winrm
请注意,如果您将来不需要服务器接收 WinRM 连接,那么让 WinRM 保持自动启动可能不是正确的选择。自行清理并在最后的配置步骤关闭不必要的防火墙端口,以确保镜像安全。
在云端配置 WinRM
大多数云允许我们提供在实例启动时运行的配置脚本。在 AWS 上是 user_data_file
。在 Google Cloud 上,这是使用 windows-startup-script-cmd
元数据标签提供的功能(例子)。
本质上,这些文件是配置 winrm 的 powershell 或 cmd 脚本,无需包装在 Autounattend 中。以各家云厂商要求的格式提供脚本,并确保您手动配置云厂商不允许内部管理的防火墙规则。各家云厂商的更多具体细节可以在构建器部分找到。