Terraform vSphere克隆自定义重置WinRM配置及命令执行时序问题求助
针对你在特定环境下遇到的问题(vSphere 6、Windows Server 2016、Terraform 0.11.7、vSphere Provider 1.4.1),我整理了几个切实可行的解决思路:
思路1:在customization块中直接配置WinRM,替代模板预配置
既然customization块会覆盖模板的WinRM设置,不如直接在虚拟机定制阶段完成WinRM配置,彻底避免依赖模板的预配置。你可以利用vSphere Provider的customization块中的extra_customizations参数,添加Sysprep XML片段来定义WinRM规则,虚拟机完成定制后WinRM直接可用。
示例配置片段:
resource "vsphere_virtual_machine" "win_vm" { # 你的虚拟机基础配置(名称、资源池、模板等)... customization { # 现有定制项(如计算机名、域加入设置等)... # 追加WinRM的Sysprep配置 extra_customizations = <<EOF <settings> <component name="Microsoft-Windows-WebServicesForManagement" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <WinRM> <Enable>true</Enable> <AllowUnencrypted>true</AllowUnencrypted> <Basic>true</Basic> </WinRM> </component> </settings> EOF } }
这种方式让WinRM配置和虚拟机定制同步完成,不会出现被重置的问题,provisioner可以直接连接执行后续操作。
思路2:让Provisioner等待run_once_command_list执行完成
如果你坚持要用run_once_command_list来配置WinRM,可以通过“标记文件”的方式,让provisioner等待命令执行完毕后再启动。
步骤1:修改run_once_command_list,添加完成标记
resource "vsphere_virtual_machine" "win_vm" { # 虚拟机基础配置... customization { # 现有定制项... run_once_command_list = [ # 你的WinRM配置命令示例 "powershell.exe -Command \"Enable-PSRemoting -Force -SkipNetworkProfileCheck\"", "powershell.exe -Command \"Set-Item WSMan:\\localhost\\Client\\TrustedHosts -Value '*' -Force\"", # 添加标记文件,标识WinRM配置完成 "echo WinRM setup finished > C:\\winrm_ready.txt" ] } }
步骤2:在Provisioner中添加等待逻辑
在remote-exec provisioner的最前面,加入一段powershell脚本循环检查标记文件,确保WinRM配置完成后再执行后续操作:
resource "vsphere_virtual_machine" "win_vm" { # 前面的虚拟机配置... provisioner "remote-exec" { inline = [ # 等待标记文件出现,每5秒检查一次,超时10分钟 "powershell.exe -Command \"while (-not (Test-Path C:\\winrm_ready.txt)) { Start-Sleep -Seconds 5; if ((Get-Date) -gt (Get-Date).AddMinutes(10)) { throw 'Timeout waiting for WinRM setup' } }\"", # 你的后续provisioner命令(如软件安装、配置修改等)... ] connection { type = "winrm" user = "${var.admin_user}" password = "${var.admin_password}" timeout = "15m" # 延长连接超时时间,避免等待过程中断开 } } }
思路3:利用Terraform连接重试机制
Terraform 0.11版本的remote-exec provisioner支持在connection块中设置重试参数,让Terraform自动重试WinRM连接,直到服务正常可用,间接等待WinRM配置完成。
示例配置:
resource "vsphere_virtual_machine" "win_vm" { # 虚拟机基础配置... provisioner "remote-exec" { inline = [ # 你的provisioner命令... ] connection { type = "winrm" user = "${var.admin_user}" password = "${var.admin_password}" timeout = "20m" retry_max = 24 # 最多重试24次 retry_wait = "30s" # 每次重试间隔30秒 } } }
这种方式不需要额外的标记文件,靠Terraform的重试机制自动等待WinRM服务就绪,适合不想修改命令列表的场景。
内容的提问来源于stack exchange,提问作者Kevin Brooks

