如何用Terraform模块创建含多资源的单个API Gateway?
解决Terraform API Gateway模块创建多资源而非多网关的问题
你遇到的问题根源很明确:你的../apigateway模块里应该包含了aws_api_gateway_rest_api这个核心资源,所以每次调用模块都会新建一个独立的API Gateway实例,而不是在同一个网关下添加资源。下面给你两种可行的解决方案,你可以根据自己的需求选择:
方案一:重构模块,支持批量定义多资源
这种方案适合你预先知道所有需要创建的资源,希望通过一个模块调用就能完成所有资源配置的场景。
步骤1:修改模块代码
更新你的../apigateway模块,让它接受一个资源列表作为输入,而不是单个的path和method:
首先在模块里定义变量:
variable "api_name" { type = string description = "名称,用于标识这个API Gateway" } variable "resources" { type = list(object({ path = string method = string # 如果需要的话,还可以添加其他配置字段,比如authorization、api_key_required等 })) description = "需要添加到网关的资源及方法列表" }
然后在模块里创建网关,并通过for_each循环生成资源和方法:
# 创建单个API Gateway实例 resource "aws_api_gateway_rest_api" "main" { name = var.api_name } # 循环创建资源 resource "aws_api_gateway_resource" "api_resource" { # 用path+method作为唯一键,避免重复 for_each = { for res in var.resources : "${res.path}-${res.method}" => res } rest_api_id = aws_api_gateway_rest_api.main.id parent_id = aws_api_gateway_rest_api.main.root_resource_id # 挂载到根路径下 path_part = each.value.path } # 循环创建对应方法 resource "aws_api_gateway_method" "api_method" { for_each = aws_api_gateway_resource.api_resource rest_api_id = aws_api_gateway_rest_api.main.id resource_id = each.value.id http_method = each.value.method authorization = "NONE" # 根据你的实际需求调整授权方式,比如"COGNITO_USER_POOLS"等 }
步骤2:根模块调用更新后的模块
现在你只需要调用一次模块,传入所有资源配置即可:
module "combined_api_gateway" { source = "../apigateway" api_name = "my-unified-api" resources = [ { path = "path1" method = "GET" }, { path = "path2" method = "POST" } # 可以继续添加更多资源 ] }
方案二:拆分模块,分离网关与资源创建
这种方案适合你需要灵活添加资源(比如后续可能动态增加),或者不同资源有不同配置的场景。核心思路是在根模块创建唯一的API Gateway,然后用专门的模块来添加资源和方法。
步骤1:创建资源专用模块
新建一个../apigateway-resource模块,只负责创建单个资源和方法,依赖外部传入的网关ID:
模块变量定义:
variable "rest_api_id" { type = string description = "已存在的API Gateway的ID" } variable "parent_resource_id" { type = string description = "父资源ID,通常是网关的根资源ID" } variable "path" { type = string description = "资源的路径片段" } variable "method" { type = string description = "资源对应的HTTP方法" } # 可选:如果需要不同资源有不同授权方式,可以添加这个变量 variable "authorization" { type = string default = "NONE" description = "资源的授权方式" }
模块资源定义:
resource "aws_api_gateway_resource" "resource" { rest_api_id = var.rest_api_id parent_id = var.parent_resource_id path_part = var.path } resource "aws_api_gateway_method" "method" { rest_api_id = var.rest_api_id resource_id = aws_api_gateway_resource.resource.id http_method = var.method authorization = var.authorization }
步骤2:根模块创建网关并调用资源模块
在根模块里先创建唯一的API Gateway,然后多次调用资源模块添加不同的资源:
# 创建单个API Gateway实例 resource "aws_api_gateway_rest_api" "main" { name = "my-single-api" } # 添加第一个资源 module "api1" { source = "../apigateway-resource" rest_api_id = aws_api_gateway_rest_api.main.id parent_resource_id = aws_api_gateway_rest_api.main.root_resource_id path = "path1" method = "GET" } # 添加第二个资源 module "api2" { source = "../apigateway-resource" rest_api_id = aws_api_gateway_rest_api.main.id parent_resource_id = aws_api_gateway_rest_api.main.root_resource_id path = "path2" method = "POST" }
补充说明
- 如果你的API还需要集成后端(比如Lambda、HTTP服务),可以在模块里添加
aws_api_gateway_integration资源,同样用for_each或者传入对应配置来实现。 - 记得根据实际需求调整授权方式、CORS配置等细节。
内容的提问来源于stack exchange,提问作者CC.
相关产品推荐
相关产品推荐

