You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

通过Azure DevOps Pipeline+Terraform创建VM并部署Java失败求助

解决方案:Terraform Azure Windows VM WinRM连接超时问题

核心问题拆解

你的问题根源集中在三点:

  • Windows VM默认未启用WinRM远程管理及防火墙入站规则
  • 用私有IP作为WinRM连接地址,若Azure DevOps Pipeline Agent不在同VNet则无法访问
  • 动态公网IP字段未正确填充,导致无法用公网IP建立连接

分步解决

1. 预配置WinRM(关键)

不要依赖手动配置,在Terraform中通过虚拟机扩展自动初始化WinRM,确保VM启动后立即可用:

resource "azurerm_virtual_machine_extension" "winrm_config" {
  name                 = "WinRM-Config"
  virtual_machine_id   = azurerm_windows_virtual_machine.vm.id
  publisher            = "Microsoft.Compute"
  type                 = "CustomScriptExtension"
  type_handler_version = "1.10"

  settings = jsonencode({
    commandToExecute = "powershell.exe -ExecutionPolicy Bypass -Command \"& { winrm quickconfig -q; winrm set winrm/config/service '@{AllowUnencrypted=\"true\"}'; winrm set winrm/config/service/auth '@{Basic=\"true\"}'; netsh advfirewall firewall set rule group=\"Windows Remote Management\" new enable=yes }\""
  })

  depends_on = [azurerm_windows_virtual_machine.vm]
}

这段脚本会完成:

  • 一键配置WinRM服务
  • 允许非加密连接(测试场景用,生产建议改用HTTPS 5986端口)
  • 启用Basic认证(匹配Terraform的WinRM连接配置)
  • 开启防火墙WinRM入站规则组

2. 修正WinRM连接地址

放弃私有IP,改用公网IP连接(除非Pipeline Agent部署在同VNet内)。针对公网IP字段未填充的问题,确保资源关联和依赖正确:

# 创建动态公网IP
resource "azurerm_public_ip" "vm_pip" {
  name                = "vm-pip"
  location            = azurerm_resource_group.rg.location
  resource_group_name = azurerm_resource_group.rg.name
  allocation_method   = "Dynamic"
}

# 网卡配置关联公网IP
resource "azurerm_network_interface" "nic" {
  name                = "vm-nic"
  location            = azurerm_resource_group.rg.location
  resource_group_name = azurerm_resource_group.rg.name

  ip_configuration {
    name                          = "internal"
    subnet_id                     = azurerm_subnet.subnet.id
    private_ip_address_allocation = "Dynamic"
    public_ip_address_id          = azurerm_public_ip.vm_pip.id
  }
}

# VM关联网卡,添加依赖确保公网IP就绪
resource "azurerm_windows_virtual_machine" "vm" {
  name                = "windows-vm"
  resource_group_name = azurerm_resource_group.rg.name
  location            = azurerm_resource_group.rg.location
  size                = "Standard_D2s_v3"
  admin_username      = var.admin_username
  admin_password      = var.admin_password
  network_interface_ids = [azurerm_network_interface.nic.id]

  depends_on = [azurerm_public_ip.vm_pip]
}

3. 修正Terraform Provisioner配置

用公网IP作为WinRM连接地址,添加超时设置,并依赖WinRM扩展执行完成:

resource "azurerm_windows_virtual_machine" "vm" {
  # ... 保留上述VM基础配置 ...

  # 上传Java安装脚本
  provisioner "file" {
    source      = "java.ps1"
    destination = "C:\\temp\\java.ps1"

    connection {
      type     = "winrm"
      user     = var.admin_username
      password = var.admin_password
      host     = azurerm_public_ip.vm_pip.ip_address
      port     = 5985
      timeout  = "10m"
      https    = false
      insecure = true
    }

    depends_on = [azurerm_virtual_machine_extension.winrm_config]
  }

  # 执行Java安装脚本
  provisioner "remote-exec" {
    inline = [
      "powershell.exe -ExecutionPolicy Bypass -File C:\\temp\\java.ps1"
    ]

    connection {
      type     = "winrm"
      user     = var.admin_username
      password = var.admin_password
      host     = azurerm_public_ip.vm_pip.ip_address
      port     = 5985
      timeout  = "10m"
      https    = false
      insecure = true
    }

    depends_on = [azurerm_virtual_machine_extension.winrm_config]
  }
}

4. 验证NSG规则

确保网络安全组开放5985端口:

resource "azurerm_network_security_group" "nsg" {
  name                = "vm-nsg"
  location            = azurerm_resource_group.rg.location
  resource_group_name = azurerm_resource_group.rg.name

  security_rule {
    name                       = "WinRM-HTTP"
    priority                   = 1001
    direction                  = "Inbound"
    access                     = "Allow"
    protocol                   = "Tcp"
    source_port_range          = "*"
    destination_port_range     = "5985"
    source_address_prefix      = "*" # 生产环境建议限制为Pipeline Agent的IP段
    destination_address_prefix = "*"
  }
}

关键注意事项

  • 生产环境禁止使用Basic认证和非加密连接,建议配置WinRM HTTPS(5986端口)并导入SSL证书
  • 若Pipeline Agent部署在Azure同VNet内,可继续使用私有IP,但需确保Agent能访问VM的私有网络
  • 公网IP的ip_address字段需等资源完全创建后才会填充,depends_on能强制Terraform等待资源就绪

内容的提问来源于stack exchange,提问作者lcs

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 13:10:05