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

如何将外部变量转为Map传入Terraform AWS ALB模块?

Terraform动态生成AWS ALB模块target_groups映射的问题

我正尝试将外部变量的数据转换为Map,传入Terraform的AWS ALB模块。原模块定义如下:

module "alb" {
    source = "github_url"
    name   = var.name
    listeners = {
       listener = {
         port = 443
         protocol = "HTTPS"
         certificate_arns = [""]
         target_group_name ="test_tg"  
       }
    }

    target_groups = {
       test_tg = {
          port   = var.port
          target_type = "ip"
       }
    }
  }

我不想硬编码target_groups,计划通过外部变量动态生成,但尝试用Dynamic Block构建时遇到了问题。

第一次尝试:数组类型的外部变量

外部变量定义:

clusters = [{"name":"cluster1", "ip_address":"10.10.10.10","port":"8080"},{"name":"cluster2", "ip_address":"10.10.10.11","port":"8080"}]

修改后的Terraform代码:

module "alb" {
        source = "github_url"
        name   = var.name
        listeners = {
           listener = {
             port = 443
             protocol = "HTTPS"
             certificate_arns = [""]
             target_group_name =var.clusters[0].name  
           }
        }
    
        dynamic "target_groups" {
           for_each = { for cluster in var.clusters: cluster.name => cluster}
           content {
               each.value.name = {
                   port        = each.value.port
                   target_type = each.value.ip_address
               }
           }
        }
      }

此时报错:Argument or Block definition is required,错误出现在each.value.name = {}行。

第二次尝试:Map类型的外部变量

将外部变量改为Map类型:

clusters = {"cluster1":{"ip_address":"10.10.10.10","port":"8080"},"cluster2":{"ip_address":"10.10.10.11","port":"8080"}}

修改代码:

module "alb" {
            source = "github_url"
            name   = var.name
            listeners = {
               listener = {
                 port = 443
                 protocol = "HTTPS"
                 certificate_arns = [""]
                 target_group_name =var.clusters[0].name  
               }
            }
        
            dynamic "target_groups" {
               for_each = var.clusters
               content {
                   each.key = each.value
               }
            }
          }

仍然报错,提示不能使用each.key作为键,必须硬编码。

解决方案

问题核心是误用了Dynamic Block:target_groups是模块的输入变量(类型为map(object(...))),而非Terraform资源内部的嵌套块(比如aws_lb中的listener块),因此不需要用dynamic来生成,直接通过for表达式构造符合要求的Map传入即可。

针对数组类型的clusters变量

先在locals中构造目标Map:

locals {
  target_groups = {
    for cluster in var.clusters : cluster.name => {
      port        = cluster.port
      target_type = "ip"  # 注意:原模块中target_type是固定值"ip",不要误传ip_address
    }
  }
}

然后在模块中直接传入:

module "alb" {
  source = "github_url"
  name   = var.name
  listeners = {
    listener = {
      port              = 443
      protocol          = "HTTPS"
      certificate_arns  = [""]
      target_group_name = var.clusters[0].name
    }
  }

  target_groups = local.target_groups
}

针对Map类型的clusters变量

同样在locals中转换结构:

locals {
  target_groups = {
    for tg_name, cluster in var.clusters : tg_name => {
      port        = cluster.port
      target_type = "ip"
    }
  }
}

然后传入模块:

module "alb" {
  source = "github_url"
  name   = var.name
  listeners = {
    listener = {
      port              = 443
      protocol          = "HTTPS"
      certificate_arns  = [""]
      target_group_name = keys(var.clusters)[0]  # 获取第一个目标组名称
    }
  }

  target_groups = local.target_groups
}

补充说明

  • Dynamic Block仅适用于Terraform资源/数据源内部的嵌套块(比如aws_security_group的ingress/egress块),模块的输入变量是参数赋值,直接传递Map即可。
  • 原模块中target_groups的结构是{ 目标组名称 = { port = ..., target_type = ... } },所以需要保证构造的Map完全匹配这个结构。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 16:03:27