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

Terraform部署Azure Windows VMSS遇问题:脚本未执行+公网IP无法访问

问题排查:Terraform部署Windows VMSS+公网LB无法访问且IIS脚本未执行

以下是导致问题的核心原因及修正方案:

核心问题分析

1. 负载均衡器规则未关联后端池与健康探针

原负载均衡器规则azurerm_lb_rule.lb_rule未绑定后端地址池和健康探针,导致:

  • LB无法将公网流量转发到VMSS实例
  • LB无法检测实例健康状态,会直接标记实例为不健康,拒绝转发流量

2. CustomScriptExtension配置错误

  • 使用protected_settings存储非敏感的脚本执行命令,可能引发权限或解析问题
  • 冗余的base64编码处理增加复杂度,易出现转义错误
  • 旧版template_file数据源在Terraform 0.12+已被templatefile函数替代

3. 冗余资源干扰

azurerm_network_interface.nic是冗余资源,VMSS会自动为每个实例创建网卡,该资源无实际作用且可能引发资源冲突

4. 变量定义不完整

admin_username和admin_password变量仅标记为敏感但无类型与描述定义,部署时若未传入值会直接失败


修正后的完整代码

main.tf

terraform {
  required_version = ">= 0.13"
}

provider "azurerm" {
  features {}
}

variable "admin_username" {
  type        = string
  sensitive   = true
  description = "VMSS管理员用户名"
}

variable "admin_password" {
  type        = string
  sensitive   = true
  description = "VMSS管理员密码"
}

resource "azurerm_resource_group" "rg1" {
  name     = "rg2"
  location = "uksouth"
}

resource "azurerm_virtual_network" "vn" {
  name                = "vn-vmss"
  address_space       = ["10.0.0.0/16"]
  location            = azurerm_resource_group.rg1.location
  resource_group_name = azurerm_resource_group.rg1.name
}

resource "azurerm_subnet" "subnet1" {
  name                 = "subnet-vmss"
  resource_group_name  = azurerm_resource_group.rg1.name
  virtual_network_name = azurerm_virtual_network.vn.name
  address_prefixes     = ["10.0.1.0/24"]
}

resource "azurerm_public_ip" "vmss-pip" {
  name                = "vmss-pip"
  location            = azurerm_resource_group.rg1.location
  resource_group_name = azurerm_resource_group.rg1.name
  allocation_method   = "Static"
  sku                 = "Standard"
  domain_name_label   = "vmss10101"

  tags = {
    "app" = "scale-set"
    "env" = "dev"
  }
}

resource "azurerm_network_security_group" "nsg1" {
  name                = "nsg1"
  resource_group_name = azurerm_resource_group.rg1.name
  location            = azurerm_resource_group.rg1.location

  security_rule {
    name                       = "allow-rdp"
    description                = "允许RDP访问"
    priority                   = 100
    direction                  = "Inbound"
    access                     = "Allow"
    protocol                   = "Tcp"
    source_port_range          = "*"
    destination_port_range     = "3389"
    source_address_prefix      = "Internet"
    destination_address_prefix = "*"
  }

  security_rule {
    name                       = "allow-http"
    description                = "允许HTTP访问"
    priority                   = 110
    direction                  = "Inbound"
    access                     = "Allow"
    protocol                   = "Tcp"
    source_port_range          = "*"
    destination_port_range     = "80"
    source_address_prefix      = "Internet"
    destination_address_prefix = "*"
  }
}

resource "azurerm_subnet_network_security_group_association" "nsg-assoc" {
  subnet_id                 = azurerm_subnet.subnet1.id
  network_security_group_id = azurerm_network_security_group.nsg1.id
}

resource "azurerm_lb" "vmss_lb" {
  name                = "vmss_lb"
  location            = azurerm_resource_group.rg1.location
  resource_group_name = azurerm_resource_group.rg1.name
  sku                 = "Standard"

  frontend_ip_configuration {
    name                 = "PublicIP"
    public_ip_address_id = azurerm_public_ip.vmss-pip.id
  }
}

resource "azurerm_lb_backend_address_pool" "backend" {
  name                = "backend"
  loadbalancer_id     = azurerm_lb.vmss_lb.id
}

resource "azurerm_lb_probe" "http_probe" {
  name                = "http_probe"
  protocol            = "Http"
  port                = 80
  request_path        = "/"
  loadbalancer_id     = azurerm_lb.vmss_lb.id
}

resource "azurerm_lb_rule" "lb_rule" {
  name                           = "lb_rule"
  loadbalancer_id                = azurerm_lb.vmss_lb.id
  protocol                       = "Tcp"
  frontend_port                  = 80
  backend_port                   = 80
  frontend_ip_configuration_name = "PublicIP"
  backend_address_pool_ids       = [azurerm_lb_backend_address_pool.backend.id]
  probe_id                       = azurerm_lb_probe.http_probe.id
}

resource "azurerm_windows_virtual_machine_scale_set" "vmss" {
  name                = "vmss"
  resource_group_name = azurerm_resource_group.rg1.name
  location            = azurerm_resource_group.rg1.location
  sku                 = "Standard_F2"
  instances           = 2
  admin_password      = var.admin_password
  admin_username      = var.admin_username

  source_image_reference {
    publisher = "MicrosoftWindowsServer"
    offer     = "WindowsServer"
    sku       = "2016-Datacenter"
    version   = "latest"
  }

  os_disk {
    storage_account_type = "Standard_LRS"
    caching              = "ReadWrite"
  }

  network_interface {
    name    = "example"
    primary = true

    ip_configuration {
      name      = "internal"
      primary   = true
      subnet_id = azurerm_subnet.subnet1.id
      load_balancer_backend_address_pool_ids = [azurerm_lb_backend_address_pool.backend.id]
    }
  }
}

resource "azurerm_virtual_machine_scale_set_extension" "iis_vmss_extension" {
  name                         = "iis_vmss_ext"
  virtual_machine_scale_set_id = azurerm_windows_virtual_machine_scale_set.vmss.id
  publisher                    = "Microsoft.Compute"
  type                         = "CustomScriptExtension"
  type_handler_version         = "1.9"

  settings = <<SETTINGS
  {
    "commandToExecute": "powershell -ExecutionPolicy Unrestricted -Command \"${templatefile("iis.ps1", {})}\""
  }
SETTINGS
}

iis.ps1

Install-WindowsFeature -Name Web-Server -IncludeManagementTools
# 确保文件存在并覆盖原有内容,避免重复追加
Set-Content -Path "C:\inetpub\wwwroot\Default.htm" -Value $env:computername

部署说明

  1. 创建terraform.tfvars文件,填入管理员账号信息:
admin_username = "your-admin-user"
admin_password = "your-strong-password"
  1. 执行部署命令:
terraform init
terraform plan
terraform apply

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 19:54:28