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

如何正确实现Terraform嵌套for循环以创建AWS路由?

Terraform 路由资源遍历配置问题修复

问题场景

需遍历private和public两种路由类型,同时为每种路由下的每个cidr_block创建路由资源,但原代码运行报错。

原代码

locals {
  routes = {
    private = {
      route_table_ids  = module.vpc.private_route_table_ids
      cidr_blocks      = ["10.1.0.0/16", "10.2.0.0/16", "10.5.0.0/16"]
    }
    public = {
      route_table_ids  = module.vpc.public_route_table_ids
      cidr_blocks      = ["10.1.0.0/16", "10.2.0.0/16", "10.5.0.0/16"]
    }
  }
}

resource "aws_route" "vpc_route" {
  for_each = {
    for route in local.routes :
      for cidr in route.cidr_blocks : "${route}-${cidr}" => {
        route_table_id         = route.route_table_ids
        destination_cidr_block = cidr
      }
  }

  route_table_id         = each.value.route_table_id
  destination_cidr_block = each.value.destination_cidr_block
  gateway_id             = module.vpc.vgw_id
}

报错信息

╷
│ Error: Invalid 'for' expression
│ 
│   on routes.tf line 17, in resource "aws_route" "vpc_meta_route":
│   15:   for_each = {
│   16:     for route in local.routes :
│   17:       for cidr in route.cidr_blocks : "${route}-${cidr}" => {
│   18:         route_table_id         = route.route_table_ids
│   19:         destination_cidr_block = cidr
│   20:       }
│   21:   }
│ 
│ Key expression is required when building an object.
╵
╷
│ Error: Invalid 'for' expression
│ 
│   on routes.tf line 17, in resource "aws_route" "vpc_meta_route":
│   15:   for_each = {
│   16:     for route in local.routes :
│   17:       for cidr in route.cidr_blocks : "${route}-${cidr}" => {
│ 
│ Extra characters after the end of the 'for' expression.
╵
FAIL

问题分析

  1. 嵌套for循环语法错误:Terraform构建映射的嵌套for表达式,需要明确外层循环的键值处理逻辑,原写法缺少外层键定义,格式不符合规范。
  2. 路由表ID类型不匹配:module.vpc.private_route_table_ids通常是列表类型(包含多个路由表ID),但aws_route的route_table_id参数要求单个字符串值,直接赋值会报错。

修复后的代码

方案1:通过本地值扁平化配置

先将多层嵌套的路由配置扁平化,再转换为for_each可用的映射:

locals {
  routes = {
    private = {
      route_table_ids  = module.vpc.private_route_table_ids
      cidr_blocks      = ["10.1.0.0/16", "10.2.0.0/16", "10.5.0.0/16"]
    }
    public = {
      route_table_ids  = module.vpc.public_route_table_ids
      cidr_blocks      = ["10.1.0.0/16", "10.2.0.0/16", "10.5.0.0/16"]
    }
  }

  # 扁平化路由配置:路由类型 + 单个路由表ID + 单个CIDR块
  flattened_routes = flatten([
    for route_type, config in local.routes : [
      for rt_id in config.route_table_ids : [
        for cidr in config.cidr_blocks : {
          route_type = route_type
          rt_id      = rt_id
          cidr       = cidr
        }
      ]
    ]
  ])

  # 生成唯一键的映射,满足for_each要求
  route_map = {
    for route in local.flattened_routes :
    "${route.route_type}-${route.rt_id}-${route.cidr}" => route
  }
}

resource "aws_route" "vpc_route" {
  for_each = local.route_map

  route_table_id         = each.value.rt_id
  destination_cidr_block = each.value.cidr
  gateway_id             = module.vpc.vgw_id
}

方案2:直接在for_each中处理

无需额外本地值,直接在for_each表达式内完成扁平化:

locals {
  routes = {
    private = {
      route_table_ids  = module.vpc.private_route_table_ids
      cidr_blocks      = ["10.1.0.0/16", "10.2.0.0/16", "10.5.0.0/16"]
    }
    public = {
      route_table_ids  = module.vpc.public_route_table_ids
      cidr_blocks      = ["10.1.0.0/16", "10.2.0.0/16", "10.5.0.0/16"]
    }
  }
}

resource "aws_route" "vpc_route" {
  for_each = {
    for route in flatten([
      for route_type, config in local.routes : [
        for rt_id in config.route_table_ids : [
          for cidr in config.cidr_blocks : {
            key = "${route_type}-${rt_id}-${cidr}"
            rt_id = rt_id
            cidr = cidr
          }
        ]
      ]
    ]) : route.key => route
  }

  route_table_id         = each.value.rt_id
  destination_cidr_block = each.value.cidr
  gateway_id             = module.vpc.vgw_id
}

内容的提问来源于stack exchange,提问作者João Amaro

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 04:40:24