Terraform count.index索引local值报无效索引错误排查
问题根因
报错核心是集合类型转换逻辑错误,和变量定义为list(string)还是list(object)没有直接关系:
- 你写的
for x in var.xxx_list : x.name => x表达式,会把原本支持数字索引按顺序取值的列表(list),转换成仅支持字符串键取值的映射(map,即报错中提到的object类型集合) - 转换完成后的
local.alarm_names、local.metric_names实际结构如下,所有键都是配置的name字符串,不存在0、1、2、3这类数字键,自然无法用count.index的数字值做索引查询:
# 转换后的local.metric_names实际结构 { CPUUtilization = { name = "CPUUtilization" } DiskReadOps = { name = "DiskReadOps" } NetworkIn = { name = "NetworkIn" } NetworkOut = { name = "NetworkOut" } }
正确配置方案
以下两种方案均可直接落地,根据使用场景选择即可:
方案1:直接引用原始列表配合count(改动最小)
既然已经确认两个列表长度始终一致、同位置元素一一对应,完全不需要额外转map,直接引用原始变量列表按索引取值即可,变量也可以简化为list(string)类型减少冗余。
修改后的main.tf代码:
resource "aws_cloudwatch_metric_alarm" "ec2_cpu" { count = length(var.alarm_names_list) alarm_name = "${var.alarm_names_list[count.index]}-${var.name_instance_outout}" comparison_operator = "GreaterThanOrEqualToThreshold" evaluation_periods = "2" metric_name = var.metric_names_list[count.index] namespace = "AWS/EC2" period = "120" statistic = "Average" threshold = "80" alarm_description = "This metric monitors ec2 cpu utilization" insufficient_data_actions = [] dimensions = { InstanceId = var.ec2_id_output } }
对应简化后的variables.tf代码:
variable "metric_names_list" { type = list(string) default = ["CPUUtilization", "DiskReadOps", "NetworkIn", "NetworkOut"] } variable "alarm_names_list" { type = list(string) default = ["cpu-utilization-duk-test", "memory-utilization", "network-inbound", "network-outbound"] }
方案2:合并结构后用for_each(生产环境更稳妥)
如果担心后续调整列表顺序导致告警意外重建,可以先把两个列表按索引合并成统一的映射结构,用for_each创建资源,这种方式不受列表顺序变动影响。
修改后的main.tf代码:
locals { # 按索引合并两个列表,生成以告警名为键的固定映射 alarm_metric_map = { for idx, alarm_name in var.alarm_names_list : alarm_name => { alarm_name = alarm_name metric_name = var.metric_names_list[idx] } } } resource "aws_cloudwatch_metric_alarm" "ec2_cpu" { for_each = local.alarm_metric_map alarm_name = "${each.value.alarm_name}-${var.name_instance_outout}" comparison_operator = "GreaterThanOrEqualToThreshold" evaluation_periods = "2" metric_name = each.value.metric_name namespace = "AWS/EC2" period = "120" statistic = "Average" threshold = "80" alarm_description = "This metric monitors ec2 cpu utilization" insufficient_data_actions = [] dimensions = { InstanceId = var.ec2_id_output } }
变量定义和方案1保持一致即可。
注意:for_each方案下后续调整告警配置时,只会修改对应键匹配的资源,不会因为列表顺序变化批量重建告警,生产环境优先推荐该写法。
内容的提问来源于stack exchange,提问作者duuk
相关产品推荐
相关产品推荐

