如何在CloudFormation模板中关联指定API Gateway阶段与对应Lambda别名?
关联API Gateway阶段到Lambda别名的CloudFormation配置方案
我来帮你搞定这个配置问题!要让QA和Prod的API阶段分别调用对应的Lambda别名,你需要在模板里添加几个关键部分:API方法与Lambda集成、Lambda权限配置,还有利用阶段变量来区分不同环境的别名。
核心思路
我们会用API Gateway阶段变量来动态指定要调用的Lambda别名,这样不同阶段可以复用同一个API配置,只通过变量切换目标Lambda版本/别名,既灵活又能减少重复代码。
具体修改步骤
1. 添加API方法与Lambda集成
首先要给你的/test资源添加一个方法(这里以POST为例),并配置集成到Lambda,通过阶段变量${stageVariables.lambdaAlias}来动态指向不同别名:
RestApiMethod: Type: "AWS::ApiGateway::Method" Properties: RestApiId: !Ref RestApi ResourceId: !Ref RestApiResource HttpMethod: POST AuthorizationType: NONE Integration: Type: AWS_PROXY IntegrationHttpMethod: POST Uri: !Sub "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${EndpointLambda.Arn}:${stageVariables.lambdaAlias}/invocations"
2. 配置Lambda权限,允许API Gateway调用
需要创建两个Lambda权限资源,分别允许QA和Prod阶段的API请求调用对应的Lambda别名,确保权限的最小化:
QaLambdaPermission: Type: "AWS::Lambda::Permission" Properties: FunctionName: !Sub "${EndpointLambda.Arn}:QA" Action: "lambda:InvokeFunction" Principal: "apigateway.amazonaws.com" SourceArn: !Sub "arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/qa/*/*" ProdLambdaPermission: Type: "AWS::Lambda::Permission" Properties: FunctionName: !Sub "${EndpointLambda.Arn}:Prod" Action: "lambda:InvokeFunction" Principal: "apigateway.amazonaws.com" SourceArn: !Sub "arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/prod/*/*"
3. 更新API阶段配置,添加阶段变量
修改你的QA和Prod阶段资源,加入Variables字段,把lambdaAlias变量映射到对应的Lambda别名:
QaRestApiStage: Type: "AWS::ApiGateway::Stage" Properties: DeploymentId: !Ref "RestApiDeployment" RestApiId: !Ref "RestApi" StageName: "qa" Variables: lambdaAlias: "QA" # 关联QA别名 ProdRestApiStage: Type: "AWS::ApiGateway::Stage" Properties: DeploymentId: !Ref "RestApiDeployment" RestApiId: !Ref "RestApi" StageName: "prod" Variables: lambdaAlias: "Prod" # 关联Prod别名
4. 修复部署依赖问题
确保API部署依赖于方法资源的创建,否则部署时方法还未生成会导致失败:
RestApiDeployment: Type: "AWS::ApiGateway::Deployment" Properties: RestApiId: !Ref "RestApi" DependsOn: RestApiMethod # 等待方法创建完成再部署
5. 修正资源路径的小问题
原模板中RestApiResource的PathPart写了/test,API Gateway的路径部分不需要开头的斜杠,根资源已经是/,修改后拼接出来的路径才是正确的/test:
RestApiResource: Type: "AWS::ApiGateway::Resource" Properties: RestApiId: !Ref "RestApi" ParentId: !GetAtt "RestApi.RootResourceId" PathPart: "test"
完整修改后的模板
把所有修改整合到原模板里,完整内容如下:
AWSTemplateFormatVersion: "2010-09-09" Transform: "AWS::Serverless-2016-10-31" Description: Lambda function configuration Resources: EndpointLambda: Type: "AWS::Lambda::Function" Properties: FunctionName: "endpoint-lambda" Handler: "com.test.aws.RequestHandler::handleRequest" Runtime: java8 Code: S3Bucket: "lambda-functions" S3Key: "test-endpoint-lambda-0.0.1.jar" Description: Test Lambda function MemorySize: 256 Timeout: 60 Environment: Variables: ES_HOST: test-es-host-url ES_ON: true ES_PORT: 443 ES_PROTOCOL: https REDIS_URL: test-redis-host-url QaLambdaAlias: Type: "AWS::Lambda::Alias" Properties: FunctionName: !Ref EndpointLambda FunctionVersion: 1 Name: "QA" Description: "QA alias" ProdLambdaAlias: Type: "AWS::Lambda::Alias" Properties: FunctionName: !Ref EndpointLambda FunctionVersion: 1 Name: "Prod" Description: "Production alias" RestApi: Type: "AWS::ApiGateway::RestApi" Properties: Name: "test-rest-api" Description: "Test REST API" RestApiResource: Type: "AWS::ApiGateway::Resource" Properties: RestApiId: !Ref "RestApi" ParentId: !GetAtt "RestApi.RootResourceId" PathPart: "test" RestApiMethod: Type: "AWS::ApiGateway::Method" Properties: RestApiId: !Ref RestApi ResourceId: !Ref RestApiResource HttpMethod: POST AuthorizationType: NONE Integration: Type: AWS_PROXY IntegrationHttpMethod: POST Uri: !Sub "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${EndpointLambda.Arn}:${stageVariables.lambdaAlias}/invocations" RestApiDeployment: Type: "AWS::ApiGateway::Deployment" Properties: RestApiId: !Ref "RestApi" DependsOn: RestApiMethod QaLambdaPermission: Type: "AWS::Lambda::Permission" Properties: FunctionName: !Sub "${EndpointLambda.Arn}:QA" Action: "lambda:InvokeFunction" Principal: "apigateway.amazonaws.com" SourceArn: !Sub "arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/qa/*/*" ProdLambdaPermission: Type: "AWS::Lambda::Permission" Properties: FunctionName: !Sub "${EndpointLambda.Arn}:Prod" Action: "lambda:InvokeFunction" Principal: "apigateway.amazonaws.com" SourceArn: !Sub "arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/prod/*/*" QaRestApiStage: Type: "AWS::ApiGateway::Stage" Properties: DeploymentId: !Ref "RestApiDeployment" RestApiId: !Ref "RestApi" StageName: "qa" Variables: lambdaAlias: "QA" ProdRestApiStage: Type: "AWS::ApiGateway::Stage" Properties: DeploymentId: !Ref "RestApiDeployment" RestApiId: !Ref "RestApi" StageName: "prod" Variables: lambdaAlias: "Prod"
额外说明
- 这里使用的
AWS_PROXY集成是最常用的Lambda代理模式,会把整个API请求传递给Lambda,适合大多数场景;如果是普通集成,需要调整集成配置。 - 权限配置中的
SourceArn限制了只有对应阶段的API请求才能调用Lambda别名,遵循了最小权限原则,提升了安全性。
内容的提问来源于stack exchange,提问作者Hleb
相关产品推荐
相关产品推荐

