Terraform:含count的资源内dynamic block无法正常工作问题排查
Terraform CloudWatch告警模块dynamic块迭代器错误分析
问题背景
使用Terraform AWS Provider创建CloudWatch Metric Alarms,编写了一个接收实例ID列表的模块:
- 模块内
aws_cloudwatch_metric_alarm资源通过count功能,为每个实例ID生成一条告警 - 计划用
dynamic块实现多metric_query配置,让根模块按需定义查询数量 - 预期最终实现:配置3个metric_query块,其中两个为基础指标,第三个基于前两个的表达式,同时为每个实例生成对应告警
现有代码
模块资源定义
resource "aws_cloudwatch_metric_alarm" "alarm" { count = length(var.dimension_values) alarm_name = "${var.alarm_name}_${var.dimension_values[count.index]}" comparison_operator = var.comparison_operator evaluation_periods = var.evaluation_periods threshold = var.threshold actions_enabled = var.actions_enabled alarm_actions = var.alarm_actions dynamic "metric_query" { for_each = var.metric_queries content { id = metric_queries.value.id return_data = metric_queries.value.return_data expression = metric_queries.value.expression label = metric_queries.value.label metric { namespace = metric_queries.value.namespace metric_name = metric_queries.value.metric_name period = metric_queries.value.period stat = metric_queries.value.stat dimensions = { "${metric_queries.value.dimension_name}" = var.dimension_values[count.index] } } } } tags = merge( var.common_tags, { Name = "${var.alarm_name}_${var.dimension_values[count.index]}" } ) }
模块变量定义
variable "metric_queries" { type = list(object({ id = string return_data = bool expression = string label = string namespace = string metric_name = string period = number stat = string dimension_name = string })) description = "Metric query for the CloudWatch alarm" default = [] }
根模块调用代码
module "cpu_alarms" { source = "../../Modules/cloudwatch_metric_alarm/" common_tags = local.common_tags # Metrics alarm_name = "EC2_CPU_80_PERCENT" comparison_operator = "GreaterThanOrEqualToThreshold" evaluation_periods = 3 threshold = 80 actions_enabled = true alarm_actions = ["redacted"] dimension_values = local.all_ec2_instance_ids metric_queries = [ { id = "m1" return_data = true expression = null label = "CPU utilization" namespace = "AWS/EC2" metric_name = "CPUUtilization" period = 60 stat = "Average" dimension_name = "InstanceId" } ] }
错误现象
- 使用
each作为迭代器引用时,报错:
A reference to "each.value" has been used in a context in which it unavailable, such as when the configuration no longer contains the value in its "for_each" expression. Remove this reference to each.value in your configuration to work around this error.
- 使用
metric_queries作为迭代器引用时,报错:
A managed resource "metric_queries" "value" has not been declared in module.cpu_alarms.
根本原因
each引用错误:each仅在资源/模块级别的for_each参数中生效,dynamic块的默认迭代器名称是dynamic块的名称(即这里的metric_query),而非each,因此直接用each.value会被判定为无效引用。metric_queries引用错误:你误将变量名metric_queries当成了迭代器名称。dynamic块的迭代器默认是块名metric_query,如果未显式指定iterator参数,必须使用块名.value的格式访问迭代值,而非变量名。
修复方案
将dynamic块内的迭代值引用改为默认的metric_query.value,同时为表达式类型的query添加count控制,避免生成无效的metric块:
dynamic "metric_query" { for_each = var.metric_queries content { id = metric_query.value.id return_data = metric_query.value.return_data expression = metric_query.value.expression label = metric_query.value.label # 仅当expression为空时生成metric块,适配表达式类型的query metric { count = metric_query.value.expression == null ? 1 : 0 namespace = metric_query.value.namespace metric_name = metric_query.value.metric_name period = metric_query.value.period stat = metric_query.value.stat dimensions = { "${metric_query.value.dimension_name}" = var.dimension_values[count.index] } } } }
内容的提问来源于stack exchange,提问作者anmisnad
相关产品推荐
相关产品推荐

