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

Terraform嵌套循环创建ALB目标组及附件报错的解决方案咨询

解决Terraform「Invalid for_each argument」错误:创建ALB目标组及实例附件

问题原因

你遇到的错误是因为local.c的键依赖于aws_lb_target_group.tg的ARN属性——这个属性只有在资源apply阶段才能生成,而Terraform要求for_each的键集合必须在规划阶段就能完全确定。你的原配置用动态生成的ARN来构建键,导致Terraform无法提前预知所有资源实例的标识。

解决方案

核心思路是:用静态、规划阶段可确定的值(比如EC2实例ID和目标端口的组合)作为for_each的键,仅将动态生成的目标组ARN放在映射的值中。

修改后的完整配置

main.tf

resource "aws_lb_target_group" "tg" {
  for_each = toset(var.target-port)
  name     = "${var.targetgroup-name}-${each.value}"
  port     = each.value
  protocol = "HTTP"
  vpc_id   = "vpc-571f3830"
}

# 直接基于已知变量构建目标组附件的映射,键为静态的"实例ID-端口"
locals {
  target_attachments = {
    for combo in setproduct(var.target, var.target-port) :
    "${combo[0]}-${combo[1]}" => {
      target_id        = combo[0]
      port             = combo[1]
      target_group_arn = aws_lb_target_group.tg[combo[1]].arn
    }
  }
}

resource "aws_lb_target_group_attachment" "tg-attach" { 
  for_each         = local.target_attachments
  target_group_arn = each.value.target_group_arn
  target_id        = each.value.target_id
  port             = each.value.port
}

variables.tf(无需修改,若要优化类型可调整)

variable "target-port" {
    type = set(string)
    default = [ "81" , "82" , "83" , "84" , "85" ]
}

variable "listenerport" {
    type = set(string)
    default = [ "81" , "82" , "83" , "84" , "85" ]
}

variable "target" {
      type = set(string)
      default = ["i-08990bdd2df0" , "i-0d3b9802d7ac"]
}

variable "targetgroup-name" {
    default = "terraform-alb-tg"
}

关键改动说明

  1. 简化映射逻辑:去掉了冗余的local.a/local.b/local.c,直接用setproduct(var.target, var.target-port)生成所有需要的实例-端口组合,这些值都是变量中定义的静态内容,规划阶段即可确定。
  2. 静态键设计:用"${combo[0]}-${combo[1]}"(实例ID+端口)作为每个附件资源的唯一键,确保Terraform在规划时就能知道所有需要创建的资源实例。
  3. 动态值引用:仅将目标组ARN(动态生成的属性)放在映射的值中,Terraform允许for_each的值包含未知内容,只要键是确定的。
  4. 移除冗余依赖:无需手动添加depends_on,因为aws_lb_target_group.tg[combo[1]].arn已经隐式建立了依赖关系,Terraform会自动处理创建顺序。

可选优化:调整变量类型

如果你的端口都是数字,可以把var.target-port的类型改为set(number),更符合实际类型:

variable "target-port" {
    type = set(number)
    default = [81, 82, 83, 84, 85]
}

对应的目标组配置中port = each.value依然可以正常工作,因为Terraform会自动转换类型。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 01:35:35