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

Terraform使用For Each创建多目标组与监听器时的端口类型错误求助

Terraform ALB监听器端口类型错误解决思路

问题场景

尝试通过Terraform的for_each批量创建应用目标组、ALB监听器及路径转发规则,实现基于HTTP路径的流量路由。但执行时aws_lb_listener资源抛出类型错误:

Error: Incorrect attribute value type

on alb.tf line 38, in resource "aws_lb_listener" "app_listener_forward":
38: port = each.value.listeners
├────────────────
│ each.value.listeners is set of string with 5 elements

Inappropriate value for attribute "port": number required.

错误原因

aws_lb_listener的port属性要求单个数字值(每个监听器绑定一个唯一端口),但当前变量中listeners是一个包含多个端口的集合,直接将集合赋值给port会导致类型不匹配。此外,原代码按应用(app_one、app_two)遍历var.listeners,但每个应用对应多个端口,这种结构无法直接生成每个端口对应的独立监听器实例。

修复方案

通过局部值(locals)重构变量结构,生成每个端口+应用的唯一组合,让for_each遍历每个组合以创建独立的监听器及对应规则。

步骤1:定义局部值转换结构

添加局部值,将原变量中的应用-多端口结构拆分为每个端口对应的独立条目:

locals {
  listener_instances = merge([
    for app_name, app_config in var.listeners : {
      for port in app_config.listeners :
      "${app_name}-${port}" => {
        app_name = app_name
        port     = port
        paths    = app_config.paths
        app_port = app_config.app_port
      }
    }
  ]...)
}

该局部值会生成类似{"app_one-80": {...}, "app_one-443": {...}, ...}的结构,每个键对应一个唯一的监听器实例。

步骤2:修改监听器资源

调整aws_lb_listener的for_each指向局部值,port属性取单个端口值:

resource "aws_lb_listener" "app_listener_forward" {
  for_each          = local.listener_instances
  load_balancer_arn = aws_lb.app_alb.arn
  port              = each.value.port
  protocol          = "HTTPS"
  ssl_policy        = "ELBSecurityPolicy-TLS-1-2-Ext-2018-06"
  certificate_arn   = var.ssl_cert

  default_action {
    type             = "forward"
    target_group_arn = aws_lb_target_group.app_tg[each.value.app_name].arn
  }
}

步骤3:调整监听器规则资源

同步修改aws_lb_listener_rule的for_each,关联到对应的监听器和目标组:

resource "aws_lb_listener_rule" "app_https_listener_rule" {
  for_each     = local.listener_instances
  listener_arn = aws_lb_listener.app_listener_forward[each.key].arn

  action {
    type             = "forward"
    target_group_arn = aws_lb_target_group.app_tg[each.value.app_name].arn
  }

  condition {
    path_pattern {
      values = each.value.paths
    }
  }
}

步骤4:保留目标组资源

目标组仍按应用维度创建,无需修改:

resource "aws_lb_target_group" "app_tg" {
  for_each    = var.listeners
  name        = each.key
  port        = each.value.app_port
  protocol    = "HTTP"
  target_type = "ip"
  vpc_id      = aws_vpc.app_vpc.id

  health_check {
    interval            = 130
    timeout             = 120
    healthy_threshold   = 10
    unhealthy_threshold = 10
  }

  stickiness {
    type            = "lb_cookie"
    cookie_duration = 86400
  }
}

说明

修复后,每个端口都会创建独立的HTTPS监听器,默认转发到对应应用的目标组,同时添加路径规则匹配指定路径并转发到同一目标组。局部值的转换确保了for_each的键唯一,避免Terraform资源实例冲突。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 15:45:55