You need to enable JavaScript to run this app. Terraform使用for_each创建VM模块时如何传递模块输出NSG至外部安全规则
优惠活动
大模型
产品
解决方案
定价
更多

Terraform使用for_each创建VM模块时如何传递模块输出NSG至外部安全规则

问题根因

404报错和NSG是否正常创建无关,核心是两个引用错误:

  • 你把模块引用路径当成普通字符串硬编码在了配置里:network_security_group_name = "module.fico_app_vm.linux_vm_nsg"、source_address_prefixes = ["module.fico_web_vm.linux_vm_ips"]。只要内容套了双引号,Terraform就会把这串字符当成纯文本,直接传给Azure API当资源标识查询,Azure自然找不到名字为module.fico_app_vm.linux_vm_nsg的NSG。
  • 你对fico_app_vm模块使用了for_each循环,模块的所有输出都是和循环键一一对应的映射集合,不是单个标量值,不能直接引用module.fico_app_vm.linux_vm_nsg拿到具体的NSG名称。
修正步骤

1. 对齐模块内部的输出定义

你贴的模块内NSG资源定义名称是azurerm_network_security_group.network_security_group,但outputs.tf里引用的是azurerm_network_security_group.dwp_network_security_group,两者名称不匹配会导致模块输出为空,需要调整为和实际资源名一致的写法:

# linux_vm模块内的outputs.tf
output "linux_vm_ips" {
  value = azurerm_network_interface.dwp_network_interface.private_ip_address
}

output "linux_vm_nsg" {
  # 修正为实际存在的资源引用
  value = azurerm_network_security_group.network_security_group.name
}

2. 重构外部安全规则的配置逻辑

不要写单个静态的安全规则资源,直接复用模块的循环逻辑,保证每个生成的NSG都能匹配到对应规则,同时去掉硬编码的字符串引用,改成真实的输出值调用:

# 替换原来写死的单条安全规则资源
resource "azurerm_network_security_rule" "fico-app-sr-80" {
  # 直接复用app VM模块的循环键,和每个NSG一一绑定
  for_each = module.fico_app_vm

  # 规则名称带上每个VM的唯一标识,避免重名冲突
  name                        = "nsr-${var.environment}-${var.directorate}-${var.business_unit}-${var.vm_identifier}${var.instance_number}-${each.key}-http80"
  priority                    = 100
  direction                   = "Inbound"
  access                      = "Allow"
  protocol                    = "*"
  source_port_range           = "*"
  destination_port_range      = "80"
  # 遍历web模块的输出集合,拿到所有VM的私网IP,不要硬编码字符串
  source_address_prefixes     = values(module.fico_web_vm)[*].linux_vm_ips
  destination_address_prefix  = "VirtualNetwork"
  resource_group_name         = azurerm_resource_group.rg_fico_app.name
  # 直接引用每个循环对应的模块输出的NSG名称,不要写带模块路径的字符串
  network_security_group_name = each.value.linux_vm_nsg
}
关键注意事项
  • 所有模块输出的引用都要写在表达式上下文中,不能套双引号硬编码。只有不带引号的module.xxx.output_name写法,才会被Terraform解析成实际的输出值。
  • 对使用了for_each的模块,所有输出都是以循环传入的集合键为索引的map结构,必须通过each引用、values()、lookup()这类函数才能拿到具体的标量值,不能直接把整个输出属性当单个值使用。
  • 安全规则的for_each直接绑定对应的循环模块,能自动保证规则数量和NSG数量匹配,不会出现规则遗漏或者资源错位的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.11.08 22:24:05