如何在CloudFormation中创建可重用块?解决Lambda重复部署问题
摆脱CloudFormation重复代码:可重用Lambda+API Gateway部署方案
作为刚接触AWS的开发者,这种复制粘贴堆配置的痛苦我太懂了!CloudFormation其实有几个原生特性能帮你彻底解决这个问题,不用再靠复制粘贴维持多实例部署。下面是最适合新手的两种方案,一步步来:
1. 先做一个参数化的基础模板(核心)
首先把你的Lambda+API Gateway组合封装成一个参数化的独立模板,把每个实例不一样的配置抽成参数。比如新建一个base-lambda-api.yaml,内容大概是这样:
AWSTemplateFormatVersion: '2010-09-09' Parameters: # 每个实例唯一的标识,用来命名资源 InstanceName: Type: String Description: Unique name for this Lambda+API instance # Lambda的环境变量,每个实例不同的配置放这 LambdaEnvVars: Type: Map Description: Environment variables for the Lambda function # API Gateway的路径,比如"/service-a"、"/service-b" ApiResourcePath: Type: String Description: Path for the API Gateway resource # Lambda代码的S3位置(如果是打包上传的话,也可以用InlineCode) LambdaCodeS3Bucket: Type: String LambdaCodeS3Key: Type: String Resources: # Lambda函数,用参数动态命名和配置 LambdaFunction: Type: AWS::Lambda::Function Properties: FunctionName: !Sub "${InstanceName}-Function" Runtime: python3.11 # 换成你的运行时 Handler: index.lambda_handler # 换成你的handler Code: S3Bucket: !Ref LambdaCodeS3Bucket S3Key: !Ref LambdaCodeS3Key Environment: Variables: !Ref LambdaEnvVars Role: !GetAtt LambdaExecutionRole.Arn LambdaExecutionRole: Type: AWS::IAM::Role Properties: RoleName: !Sub "${InstanceName}-ExecutionRole" AssumeRolePolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Principal: Service: lambda.amazonaws.com Action: sts:AssumeRole ManagedPolicyArns: - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole # 基础执行权限,按需添加 # API Gateway部分,同样用参数动态配置路径 ApiGatewayRestApi: Type: AWS::ApiGateway::RestApi Properties: Name: !Sub "${InstanceName}-API" ApiGatewayResource: Type: AWS::ApiGateway::Resource Properties: ParentId: !GetAtt ApiGatewayRestApi.RootResourceId PathPart: !Ref ApiResourcePath RestApiId: !Ref ApiGatewayRestApi ApiGatewayMethod: Type: AWS::ApiGateway::Method Properties: HttpMethod: POST # 换成你的HTTP方法 ResourceId: !Ref ApiGatewayResource RestApiId: !Ref ApiGatewayRestApi AuthorizationType: NONE # 按需改认证方式 Integration: Type: AWS_PROXY IntegrationHttpMethod: POST Uri: !Sub "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${LambdaFunction.Arn}/invocations" ApiGatewayDeployment: Type: AWS::ApiGateway::Deployment DependsOn: ApiGatewayMethod Properties: RestApiId: !Ref ApiGatewayRestApi StageName: prod # 换成你的阶段名 # Lambda权限:允许API Gateway调用Lambda LambdaInvokePermission: Type: AWS::Lambda::Permission Properties: FunctionName: !Ref LambdaFunction Action: lambda:InvokeFunction Principal: apigateway.amazonaws.com SourceArn: !Sub "arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${ApiGatewayRestApi}/${ApiGatewayDeployment.StageName}/*/${ApiResourcePath}"
这个模板把所有可变的部分都做成了参数,每个实例只需要传入不同的参数值就行,不用改资源定义。
2. 在主模板中用嵌套栈(Nested Stacks)重用
接下来在你的主CloudFormation模板里,通过AWS::CloudFormation::Stack资源来引用上面的基础模板,每个实例对应一个嵌套栈,传入不同的参数。比如主模板main-stack.yaml:
AWSTemplateFormatVersion: '2010-09-09' Parameters: # 可以把公共的参数抽出来,比如代码桶的名字 CommonLambdaCodeS3Bucket: Type: String Description: S3 bucket holding Lambda code Resources: # 第一个实例:Service A ServiceAStack: Type: AWS::CloudFormation::Stack Properties: TemplateURL: ./base-lambda-api.yaml # 如果是上传到S3的话,换成S3的URL Parameters: InstanceName: ServiceA LambdaEnvVars: CONFIG_KEY: service-a-value ANOTHER_CONFIG: foo ApiResourcePath: service-a LambdaCodeS3Bucket: !Ref CommonLambdaCodeS3Bucket LambdaCodeS3Key: lambda-code.zip # 你的代码包路径 # 第二个实例:Service B ServiceBStack: Type: AWS::CloudFormation::Stack Properties: TemplateURL: ./base-lambda-api.yaml Parameters: InstanceName: ServiceB LambdaEnvVars: CONFIG_KEY: service-b-value ANOTHER_CONFIG: bar ApiResourcePath: service-b LambdaCodeS3Bucket: !Ref CommonLambdaCodeS3Bucket LambdaCodeS3Key: lambda-code.zip
这样你要新增多少个实例,就在主模板里加一个ServiceXStack资源就行,完全不用复制粘贴Lambda和API的配置代码,只需要改参数!
进阶方案:CloudFormation模块(Modules)
如果你想更灵活的封装(比如支持更多自定义选项,或者跨模板共享),可以试试CloudFormation的模块(Modules)。模块是比嵌套栈更轻量的可重用组件,你可以把Lambda+API的组合做成一个模块,然后在模板里用AWS::CloudFormation::ModuleVersion引用,用法和嵌套栈类似,但更适合复杂的可重用场景。不过对于新手来说,嵌套栈已经足够解决你的问题,模块可以等你熟悉后再尝试。
注意事项
- 如果你的Lambda代码是内联的(InlineCode),也可以把代码内容做成参数,但更推荐把代码打包上传到S3,这样基础模板更干净。
- 嵌套栈的模板URL如果是本地文件,在部署的时候需要用
aws cloudformation package命令把本地模板上传到S3,或者直接把基础模板上传到S3后用S3 URL。 - 权限方面,确保部署CloudFormation的角色有创建嵌套栈、Lambda、API Gateway等资源的权限。
内容的提问来源于stack exchange,提问作者Rohan Büchner
相关产品推荐
相关产品推荐

