如何将外部变量转为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
相关产品推荐
相关产品推荐

