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

Terraform for_each创建aws_lb_target_group_attachment问题求解

问题描述
  • 需通过for_each批量创建AWS负载均衡目标组附件,减少重复编码。aws_lb_target_group_attachment资源仅支持传入单个字符串格式的target_id(对应EC2实例ID),要求实现1个目标组绑定多个实例的效果,例如此场景中1个目标组对应2条附件资源。
  • 初始写法直接将target_ids列表传入target_id参数,执行时抛出类型不匹配错误:
╷
│ Error: Incorrect attribute value type
│ 
│   on dev-alb.tf line 288, in resource "aws_lb_target_group_attachment" "dev_lb_tg":
│  288:   target_id        = each.value.target_ids
│     ├────────────────
│     │ each.value.target_ids is list of string with 2 elements
│ 
│ Inappropriate value for attribute "target_id": string required.
╵
  • 临时方案为每个实例单独编写重复的附件资源块,冗余度高,需优化为简洁规范的实现。
实现方案

Terraform不支持for_each直接嵌套遍历,核心解决思路是先将嵌套的「服务-实例列表」结构打平为单层map,再将该map作为for_each的遍历源,这是Terraform官方推荐的多层资源关联处理方式。

具体修改逻辑

  • 新增本地值,遍历所有服务配置,将每个服务下的target_ids列表展开,生成复合唯一键(格式为服务名-实例ID,避免不同服务下相同实例ID引发键冲突),每个键对应的值存储服务名、目标组端口、实例ID三个核心参数。
  • 原有目标组资源逻辑无需改动。
  • 目标组附件资源直接遍历打平后的单层map,无需嵌套遍历。

完整可用代码

locals {
  dev_alb_defaults = {
    vpc_id                          = local.dev_alb_vpc_id
    health_check_enabled            = true
    health_check_interval           = 30
    health_check_timeout            = 5
    health_check_healthy_threshold  = 2
    health_check_unhealthy_threshold = 2
    health_check_matcher            = 200
  }

  dev_alb_targets = {
    i-am-service = {
      tg_port    = 443
      target_ids = ["i-0123456789ab", "i-0123456789bc"]
    }
  }

  # 打平嵌套结构,生成目标组附件专用遍历map
  dev_alb_tg_attachments = merge([
    for service_name, service_conf in local.dev_alb_targets : {
      for target_id in service_conf.target_ids :
      "${service_name}-${target_id}" => {
        service_name = service_name
        tg_port      = service_conf.tg_port
        target_id    = target_id
      }
    }
  ]...)
}

resource "aws_lb_target_group" "dev_lb_tg" {
  for_each = local.dev_alb_targets

  name     = "${var.customer}-${var.dev_prefix}-${try(each.value.name, each.key)}-tg"
  port     = try(each.value.tg_port, null)
  protocol = try(each.value.tg_protocol, null)
  vpc_id   = try(each.value.vpc_id, local.dev_alb_defaults.vpc_id, null)

  health_check {
    enabled             = try(each.value.health_check_enabled, local.dev_alb_defaults.health_check_enabled, false)
    path                = try(each.value.health_check_path, local.dev_alb_defaults.health_check_path, null)
    port                = try(each.value.health_check_port, each.value.tg_port, null)
    protocol            = try(each.value.health_check_protocol, local.dev_alb_defaults.health_check_protocol, null)
    interval            = try(each.value.health_check_interval, local.dev_alb_defaults.health_check_interval, null)
    timeout             = try(each.value.health_check_timeout, local.dev_alb_defaults.health_check_timeout, null)
    healthy_threshold   = try(each.value.health_check_healthy_threshold, local.dev_alb_defaults.health_check_healthy_threshold, null)
    unhealthy_threshold = try(each.value.health_check_unhealthy_threshold, local.dev_alb_defaults.health_check_unhealthy_threshold, null)
    matcher             = try(each.value.health_check_matcher, local.dev_alb_defaults.health_check_matcher, null)
  }
}

resource "aws_lb_target_group_attachment" "dev_lb_tg" {
  for_each = local.dev_alb_tg_attachments

  target_group_arn = aws_lb_target_group.dev_lb_tg[each.value.service_name].arn
  port             = each.value.tg_port
  target_id        = each.value.target_id
}
方案特性
  • 打平后的map键采用复合格式保证全局唯一,后续新增、删除实例或服务时,Terraform只会精准增删对应的附件资源,不会影响其他已存在资源。
  • 无需重复编写多个附件资源块,后续扩展时仅需在对应服务的target_ids列表中追加实例ID即可,无需修改资源层逻辑。
  • 完全符合Terraform参数类型校验要求,执行terraform plan时可看到预期的1个目标组、2条附件资源的创建计划。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.03 07:54:32