Terraform创建多ALB CloudWatch仪表盘遇for循环重复键错误
问题
尝试为多个ALB(应用负载均衡器)和目标组创建CloudWatch仪表盘时,Terraform的for_each循环因传入重复键值"AWS/ApplicationELB"报错,需要解决重复键问题。
data.tf 配置
dashboards = [ { my-dashboard-name = "Cloudwatch-Dashboard-ALB-test3" aws-region = "us-east-1" targets = ["app/test3/e8586bb7d49cf35b"] target_groups = ["targetgroup/test-tg-2/f2e0260797ce83e8","targetgroup/test4/2dd3e8ae3bf2cb94"] metrics = ["RequestCountPerTarget", "NewConnectionCount", "TargetResponseTime", "HTTPCode_Target_2XX_Count","RuleEvaluations", "HTTPCode_ELB_4XX_Count", "HTTPCode_Target_3XX_Count", "HTTP_Redirect_Count", "ActiveConnectionCount", "ProcessedBytes", "HTTPCode_ELB_3XX_Count", "RequestCount", "HTTPCode_ELB_5XX_Count", "HTTPCode_ELB_504_Count", "ConsumedLCUs", "HTTPCode_ELB_503_Count", "HTTPCode_ELB_502_Count", "HTTP_Fixed_Response_Count", "HTTPCode_Target_4XX_Count", "UnHealthyHostCount", "HealthyHostCount"] aws-namespace = "AWS/ApplicationELB" dim = "LoadBalancer" service_names = "" stat = "Average" period = 300 }, { my-dashboard-name = "Cloudwatch-Dashboard-ALB-test" aws-region = "us-east-1" targets = ["app/test2/eb397187e673ccc3"] target_groups = ["targetgroup/test-tg/62fdb81766299e0e"] metrics = ["RequestCountPerTarget", "NewConnectionCount", "TargetResponseTime", "HTTPCode_Target_2XX_Count","RuleEvaluations", "HTTPCode_ELB_4XX_Count", "HTTPCode_Target_3XX_Count", "HTTP_Redirect_Count", "ActiveConnectionCount", "ProcessedBytes", "HTTPCode_ELB_3XX_Count", "RequestCount", "HTTPCode_ELB_5XX_Count", "HTTPCode_ELB_504_Count", "ConsumedLCUs", "HTTPCode_ELB_503_Count", "HTTPCode_ELB_502_Count", "HTTP_Fixed_Response_Count", "HTTPCode_Target_4XX_Count", "UnHealthyHostCount", "HealthyHostCount"] aws-namespace = "AWS/ApplicationELB" dim = "LoadBalancer" service_names = "" stat = "Average" period = 300 }, ] }
cloudwatch.tf 配置
module "create-dashboard" { source = "../" for_each = { for service in local.dashboards : service.aws-namespace => service} dashboard-name = each.value.my-dashboard-name aws-region = each.value.aws-region targets = each.value.targets metrics = each.value.metrics aws-namespace = each.value.aws-namespace dim = each.value.dim service_names = each.value.service_names target_groups = each.value.target_groups cluster_name = ["a-cluster"] stat = each.value.stat period = each.value.period }
错误信息
╷ │ Error: Duplicate object key │ │ on cloudwatch-v1.tf line 10, in module "create-dashboard": │ 10: for_each = { for idx, service in local.dashboards : service.aws-namespace => service} │ ├──────────────── │ │ service.aws-namespace is "AWS/ApplicationELB" │ │ Two different items produced the key "AWS/ApplicationELB" in this 'for' expression. If duplicates are expected, use the ellipsis (...) after the value │ expression to enable grouping by key
解决方案
报错核心原因是for_each要求映射的键必须唯一,你当前用service.aws-namespace作为键,两个仪表盘的命名空间完全相同,导致键重复。以下是两种可行的解决方法:
方法1:使用仪表盘名称作为唯一键(推荐)
每个仪表盘的名称本身就是唯一标识,直接用它作为for_each的键:
module "create-dashboard" { source = "../" for_each = { for service in local.dashboards : service.my-dashboard-name => service} dashboard-name = each.value.my-dashboard-name aws-region = each.value.aws-region targets = each.value.targets metrics = each.value.metrics aws-namespace = each.value.aws-namespace dim = each.value.dim service_names = each.value.service_names target_groups = each.value.target_groups cluster_name = ["a-cluster"] stat = each.value.stat period = each.value.period }
这种方式直观且符合业务逻辑,每个模块实例对应一个独立的仪表盘。
方法2:使用索引+命名空间组合键
如果不想用仪表盘名称,也可以结合列表索引和命名空间生成唯一键:
module "create-dashboard" { source = "../" for_each = { for idx, service in local.dashboards : "${service.aws-namespace}-${idx}" => service} dashboard-name = each.value.my-dashboard-name aws-region = each.value.aws-region targets = each.value.targets metrics = each.value.metrics aws-namespace = each.value.aws-namespace dim = each.value.dim service_names = each.value.service_names target_groups = each.value.target_groups cluster_name = ["a-cluster"] stat = each.value.stat period = each.value.period }
索引从0开始,生成的键类似AWS/ApplicationELB-0、AWS/ApplicationELB-1,确保每个键唯一。
注意事项
错误提示中提到的...语法是用来将重复键的多个值分组到同一个键下,比如{ for service in local.dashboards : service.aws-namespace => service... },但这会把两个仪表盘的配置合并到一个模块实例中,不符合你创建多个独立仪表盘的需求,因此不适用。
内容的提问来源于stack exchange,提问作者DineshS
相关产品推荐
相关产品推荐

