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

Terraform关联子网与NSG报错:for_each含待应用时确定的属性

Terraform子网与NSG关联报错解决方案

目标

使用模块将环境中的多个子网关联到对应的NSG(NSG和子网已通过单独模块创建)

现有代码结构

根模块

main.tf

resource "azurerm_subnet_network_security_group_association" "root_subnet_nsg_association" {
  subnet_id                 = var.subnet_id
  network_security_group_id = var.nsg_id
}

variables.tf

variable "subnet_id"{
    type=number
    description="ID of the subnet which is to be attached to NSG"
    #default=""
}

variable "nsg_id"{
    type=number
    description="ID of the NSG which is to be associated with a subnet"
    #default=""
}

项目文件夹中的模块调用

nsg_subnet_association.tf

module "nsg_subnet_asosciation_module"{
source="../../Modules/network/nsg_subnet_association"

#Variable names to be passed into the root module:
#Use for_each to loop the module:

#for_each accepts a set or map but not list as a value

for_each          = local.nsg_subnet_association

subnet_id=each.key
nsg_id=each.value
}

locals块(传递值到调用模块)

注:可使用括号()在映射中定义动态键

locals{ //Key in subnet name and NSG name for each element of the LIST
        //Implicit dependence on Subnet and NSG being created before attempt to associate

     #It is possible to have dynamic keys using parenthesis () as seen on left below   
     nsg_subnet_association={
        (module.subnet_module["MGT-Subnet-1"].subnet_id)= module.nsg_module["HUB-NSG"].nsg_id
        (module.subnet_module["MGT-Subnet-1"].subnet_id) = module.nsg_module["MGT-NSG"].nsg_id
        (module.subnet_module["SEC-Subnet-1"].subnet_id) = module.nsg_module["SEC-NSG"].nsg_id
    }

}

报错信息

"for_each 映射包含的键来自于只能在执行apply阶段才能确定的资源属性,因此Terraform无法提前确定该资源实例的完整键集合。
在for_each中处理未知值时,建议在配置中静态定义映射的键,仅将apply阶段才能得到的结果放在映射的值中。
或者,你可以使用-target规划选项,先仅应用for_each值依赖的资源,然后再执行第二次apply以完成收敛。"

解决方案

核心问题分析

报错的根源是for_each的键使用了子网ID这类apply阶段才能生成的动态值,Terraform在plan阶段无法提前知晓这些键的具体内容,无法确定要创建多少个关联资源实例。另外原locals里重复使用同一个子网ID作为键,会导致映射被覆盖,逻辑上也存在错误。

具体修复步骤

  1. 修改locals块,使用静态键
    用子网名称(静态可提前确定的标识)作为映射的键,值里存放子网ID和对应的NSGID,确保plan阶段能明确键的集合,同时修正原代码中子网重复关联NSG的错误:

    locals {
      nsg_subnet_association = {
        "MGT-Subnet-1" = {
          subnet_id = module.subnet_module["MGT-Subnet-1"].subnet_id
          nsg_id    = module.nsg_module["MGT-NSG"].nsg_id
        }
        "SEC-Subnet-1" = {
          subnet_id = module.subnet_module["SEC-Subnet-1"].subnet_id
          nsg_id    = module.nsg_module["SEC-NSG"].nsg_id
        }
      }
    }
    
  2. 调整模块调用的for_each和变量传递
    模块调用时,for_each使用上述静态键的映射,从each.value中取出子网ID和NSGID传递给模块:

    module "nsg_subnet_association_module" {
      source = "../../Modules/network/nsg_subnet_association"
    
      for_each = local.nsg_subnet_association
    
      subnet_id = each.value.subnet_id
      nsg_id    = each.value.nsg_id
    }
    
  3. 修正根模块变量类型错误
    子网ID和NSGID都是字符串类型,原variables.tf中错误定义为number类型,需要修正:

    variable "subnet_id" {
      type        = string
      description = "ID of the subnet which is to be attached to NSG"
    }
    
    variable "nsg_id" {
      type        = string
      description = "ID of the NSG which is to be associated with a subnet"
    }
    

其他可选方案(不推荐)

如果暂时不想调整代码结构,可以分两次执行apply:先创建子网和NSG资源,再创建关联关系:

terraform apply -target=module.subnet_module -target=module.nsg_module
terraform apply

该方案需要手动分阶段执行,长期维护性差,优先推荐前面的静态键方案。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 18:45:19