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

Terraform配置Azure VWAN VPN网关连接时vpn_link参数报错求助

问题:Azure VWAN VPN站点链路连接创建失败

场景概述

通过Terraform定义映射结构管理VWAN站点及链路,已成功创建站点和链路,但创建azurerm_vpn_gateway_connection时提示缺少vpn_site_link_id参数,尽管状态文件中已存在链路ID。

变量定义

virtual_wan_vpn_sites = {
  vwan_site_dc = {
    name = "site-shr-infra-dc"
    location_map_key   = "primary"
    resource_group_key = "rg_vwan"
    vwan_key = "vwan"
    device_vendor = "Fortigate"
    device_model = "FGT60F"
    links = {
      link_1 = {
        name = "link-shr-infra-dc-1"
        bgp_asn = "64512"
        public_ip_address = "1.1.1.1"
        bgp_peering_ip = "10.10.100.1"
      }
      link_2 = {
        name = "link-shr-infra-dc-2"
        bgp_asn = "64513"
        public_ip_address = "2.2.2.2"
        bgp_peering_ip = "10.10.100.100"
      }
    }
  }
}

模块调用及资源代码

# 创建VPN站点
module "virtualWanVpnSites" {
  source = "../../modules/networking/virtual_wan_vpn_site"
  for_each = var.virtual_wan_vpn_sites

  name                    = each.value.name
  location                = var.location_map[each.value.location_map_key]
  resource_group_name     = azurerm_resource_group.resource_group[each.value.resource_group_key].name
  virtual_wan_id          = module.virtualWan[each.value.vwan_key].virtual_wan_id
  vwan_key                = each.value.vwan_key
  vwan_sites              = each.value.links
  device_vendor           = each.value.device_vendor
  device_model            = each.value.device_model
  vpn_gateways            = values(module.virtualHubVpn)[*].virtual_hub_vpn_gateway_id
  tags                    = merge(lookup(each.value, "tags", {}), local.tags)
}

# 模块内的VPN站点资源
resource "azurerm_vpn_site" "vwan_vpn_site" {
  name                = var.name
  location            = var.location
  resource_group_name = var.resource_group_name
  virtual_wan_id      = var.virtual_wan_id
  device_vendor       = var.device_vendor
  device_model        = var.device_model
  tags                = local.tags

  dynamic "link" {
    for_each = try(var.vwan_sites, {})
    content {
      name          = link.value.name
      ip_address    = link.value.public_ip_address
      bgp {
        asn               = link.value.bgp_asn
        peering_address   = link.value.bgp_peering_ip
      }
    }
  }
}

# 模块内的VPN网关连接资源
resource "azurerm_vpn_gateway_connection" "vhub_vpn_gateway_connection" {
  for_each = toset(var.vpn_gateways)

  name               = "example"
  vpn_gateway_id     = each.key
  remote_vpn_site_id = azurerm_vpn_site.vwan_vpn_site.id

  dynamic "vpn_link" {
    for_each = try(azurerm_vpn_site.vwan_vpn_site.link, [])
    content {
      name              = vpn_link.value.name
      vpn_site_link_id  = vpn_link.value.id
      bgp_enabled       = true
    }
  }
}

报错信息

Error: Missing required argument
│ 
│   with module.virtualWanVpnSites["vwan_site_dc"].azurerm_vpn_gateway_connection.vhub_vpn_gateway_connection["/subscriptions/xxx/resourceGroups/xxx/providers/Microsoft.Network/vpnGateways/vpn-shr-infra-usce"],
│   on ../../modules/networking/virtual_wan_vpn_site/module.tf line 25, in resource "azurerm_vpn_gateway_connection" "vhub_vpn_gateway_connection":
│   25: resource "azurerm_vpn_gateway_connection" "vhub_vpn_gateway_connection" {
│ 
│ The argument "vpn_link.1.vpn_site_link_id" is required, but no definition
│ was found.
╵
╷
│ Error: Missing required argument
│ 
│   with module.virtualWanVpnSites["vwan_site_dc"].azurerm_vpn_gateway_connection.vhub_vpn_gateway_connection["/subscriptions/xxx/resourceGroups/xxx/providers/Microsoft.Network/vpnGateways/vpn-shr-infra-use2"],
│   on ../../modules/networking/virtual_wan_vpn_site/module.tf line 25, in resource "azurerm_vpn_gateway_connection" "vhub_vpn_gateway_connection":
│   25: resource "azurerm_vpn_gateway_connection" "vhub_vpn_gateway_connection" {
│ 
│ The argument "vpn_link.1.vpn_site_link_id" is required, but no definition
│ was found.

状态文件验证(链路ID已存在)

{
  "module": "module.virtualWanVpnSites[\"vwan_site_dc\"]",
  "mode": "managed",
  "type": "azurerm_vpn_site",
  "name": "vwan_vpn_site",
  "provider": "provider[\"registry.terraform.io/hashicorp/azurerm\"]",
  "instances": [
    {
      "schema_version": 0,
      "attributes": {
        "address_cidrs": [],
        "device_model": "FGT60F",
        "device_vendor": "Fortigate",
        "id": "/subscriptions/xxx/resourceGroups/xxx/providers/Microsoft.Network/vpnSites/site-shr-infra-dc",
        "link": [
          {
            "bgp": [
              {
                "asn": 64512,
                "peering_address": "10.10.100.1"
              }
            ],
            "fqdn": "",
            "id": "/subscriptions/xxx/resourceGroups/xxx/providers/Microsoft.Network/vpnSites/site-shr-infra-dc/vpnSiteLinks/link-shr-infra-dc-1",
            "ip_address": "1.1.1.1",
            "name": "link-shr-infra-dc-1",
            "provider_name": "",
            "speed_in_mbps": 0
          },
          {
            "bgp": [
              {
                "asn": 64513,
                "peering_address": "10.10.100.100"
              }
            ],
            "fqdn": "",
            "id": "/subscriptions/xxx/resourceGroups/xxx/providers/Microsoft.Network/vpnSites/site-shr-infra-dc/vpnSiteLinks/link-shr-infra-dc-2",
            "ip_address": "2.2.2.2",
            "name": "link-shr-infra-dc-2",
            "provider_name": "",
            "speed_in_mbps": 0
          }
        ]
      }
    }
  ]
}

解决思路及修正代码

问题根源

直接遍历azurerm_vpn_site.vwan_vpn_site.link列表时,Terraform可能无法正确解析列表元素的id属性传递到动态块中,导致部分vpn_link块缺失vpn_site_link_id参数。

修正方案

改用输入的var.vwan_sites(链路映射)作为动态块遍历源,通过链路名称从站点资源的link列表中匹配对应的ID,确保每个vpn_link块都能正确获取到必填参数。

修正后的azurerm_vpn_gateway_connection资源代码:

resource "azurerm_vpn_gateway_connection" "vhub_vpn_gateway_connection" {
  for_each = toset(var.vpn_gateways)

  # 生成唯一连接名称,避免重复
  name               = "${var.name}-conn-${regex("[^/]+$", each.key)}"
  vpn_gateway_id     = each.key
  remote_vpn_site_id = azurerm_vpn_site.vwan_vpn_site.id

  dynamic "vpn_link" {
    # 遍历输入的链路映射,确保每个链路都被处理
    for_each = var.vwan_sites
    content {
      name              = vpn_link.value.name
      # 通过链路名称匹配站点资源中的链路ID
      vpn_site_link_id  = one([for l in azurerm_vpn_site.vwan_vpn_site.link : l.id if l.name == vpn_link.value.name])
      bgp_enabled       = true
    }
  }
}

说明

  1. 使用var.vwan_sites(明确的链路映射)遍历,避免依赖资源列表的不确定性;
  2. 通过列表推导式[for l in ...]结合one()函数,精准匹配对应链路的ID,确保返回单个有效值;
  3. 优化连接名称生成逻辑,避免固定名称导致的冲突问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 03:25:23