Terraform配置中NSG与Subnet关联错误排查求助
Terraform NSG与子网关联配置错误排查与修复
问题概述
配置NSG与子网关联时,执行terraform plan -var-file=dev.tfvars返回以下错误:
Error: Unsupported attribute │ │ on networking_nsgs.tf line 19, in resource "azurerm_subnet_network_security_group_association" "subnet_association": │ 19: subnet_id = data.azurerm_subnet.subnet_data.subnet.id │ │ This object has no argument, nested block, or exported attribute named "subnet". ╵ ╷ │ Error: Reference to undeclared resource │ │ on networking_nsgs.tf line 20, in resource "azurerm_subnet_network_security_group_association" "subnet_association": │ 20: network_security_group_id = azurerm_network_security_group.nsg.id │ │ A managed resource "azurerm_network_security_group" "nsg" has not been declared in the root module.
现有配置代码
app1-data.tf
data "azurerm_subnet" "subnet_data" { name = var.subnet_name virtual_network_name = var.net_name resource_group_name = var.resource_group_name }
app1-networking_nsgs.tf
module "nsg-app1" { source = "git@gitlab.com:*/*" nsg_name = var.nsg_name resource_group_name = var.resource_group_name location = var.location nsg_security_rules = var.nsg_security_rules } # Associate the NSG with the subnet resource "azurerm_subnet_network_security_group_association" "subnet_association" { # subnet_id = var.subnet_id subnet_id = data.azurerm_subnet.subnet_data.subnet.id network_security_group_id = data.azurerm_network_security_group.nsg_data.id # network_security_group_id = data.azurerm_network_security_group.nsg_data[0].id }
module-subnet-main.tf
# Create the Subnet resource "azurerm_subnet" "subnet" { name = var.subnet_names resource_group_name = var.resource_group_name virtual_network_name = var.vnet_name address_prefixes = var.subnet_cidr_list }
module-subnet-outputs.tf
output "subnet_name" { description = "Name of the created subnet" value = azurerm_subnet.subnet.name } output "subnet_id" { value = azurerm_subnet.subnet.id } output "subnet_cidr_list" { value = azurerm_subnet.subnet.address_prefixes }
module-subnet-variables.tf
variable "subnet_names" { type = string } variable "resource_group_name" { type = string description = "name of resource group" } variable "subnet_cidr_list" { type = list(any) description = "Address prefixes of Subnet" } variable "vnet_name" { type = string description = "Name of Virtual Network" }
module-nsg-main.tf
resource "azurerm_network_security_group" "nsg" { name = var.nsg_name resource_group_name = var.resource_group_name location = var.location # tags = var.tags dynamic "security_rule" { for_each = var.nsg_security_rules content { name = lookup(security_rule.value, "name", null) priority = lookup(security_rule.value, "priority", null) direction = lookup(security_rule.value, "direction", null) access = lookup(security_rule.value, "access", null) protocol = lookup(security_rule.value, "protocol", null) source_port_range = lookup(security_rule.value, "source_port_range", null) source_port_ranges = lookup(security_rule.value, "source_port_ranges", null) destination_port_range = lookup(security_rule.value, "destination_port_range", null) destination_port_ranges = lookup(security_rule.value, "destination_port_ranges", null) source_address_prefix = lookup(security_rule.value, "source_address_prefix", null) source_address_prefixes = lookup(security_rule.value, "source_address_prefixes", null) destination_address_prefix = lookup(security_rule.value, "destination_address_prefix", null) destination_address_prefixes = lookup(security_rule.value, "destination_address_prefixes", null) source_application_security_group_ids = lookup(security_rule.value, "source_application_security_group_ids ", null) destination_application_security_group_ids = lookup(security_rule.value, "destination_application_security_group_ids ", null) } } }
module-nsg-outputs.tf
output "nsg_id" { description = "The ID of the newly created Network Security Group" value = azurerm_network_security_group.nsg.id } output "nsg_name" { description = "The name of the new NSG" value = azurerm_network_security_group.nsg.name }
module-nsg-variables.tf
variable "resource_group_name" { description = "description" type = string } variable "location" { description = "description" type = string # default = "West Europe" } variable "nsg_name" { description = "description" type = string } variable "nsg_security_rules" { description = "A list of security rules to add to the security group. Each rule should be a map of values to add. See the Readme.md file for further details." type = list(object({ name = string priority = number direction = string access = string protocol = string source_port_range = string destination_port_range = string source_address_prefix = string destination_address_prefix = string })) }
错误原因与修复方案
错误1:Unsupported attribute - data.azurerm_subnet.subnet_data.subnet.id
azurerm_subnet数据源直接导出id属性,不需要额外的.subnet层级,正确引用方式:
subnet_id = data.azurerm_subnet.subnet_data.id
错误2:Reference to undeclared resource - azurerm_network_security_group.nsg.id
你已通过module "nsg-app1"调用NSG模块,需直接引用模块输出的nsg_id,而非根模块未声明的资源。同时配置中引用的data.azurerm_network_security_group.nsg_data未定义,直接使用模块输出即可:
network_security_group_id = module.nsg-app1.nsg_id
修复后的关联配置
修改app1-networking_nsgs.tf中的关联块:
resource "azurerm_subnet_network_security_group_association" "subnet_association" { subnet_id = data.azurerm_subnet.subnet_data.id network_security_group_id = module.nsg-app1.nsg_id }
额外建议
如果子网是通过module-subnet模块创建的,建议直接引用该模块的subnet_id输出,保证配置一致性:
# 假设已调用子网模块 module "subnet-app1" { source = "./path/to/subnet-module" # 传入所需变量 } # 关联时使用模块输出 resource "azurerm_subnet_network_security_group_association" "subnet_association" { subnet_id = module.subnet-app1.subnet_id network_security_group_id = module.nsg-app1.nsg_id }
内容的提问来源于stack exchange,提问作者Cyborganizer
相关产品推荐
相关产品推荐

