如何更新通过AWS SAM/CodePipeline定义和部署的Lambda代码?
问题根因
CloudFormation 生成 ChangeSet 时仅会对比模板的配置项是否发生变更,你当前的 SAM 模板中 Lambda 的 CodeUri 配置的 Key 是固定值,即便 S3 存储桶内对应路径的 zip 包内容更新,模板本身没有任何参数变化,CloudFormation 就会判定没有需要更新的资源,最终出现无新内容可部署的错误。
你之前新增构建阶段未生效的原因也在此:如果没有同步修改模板中的 CodeUri 配置,不管执行多少次 sam build、sam package,生成的部署模板和之前完全一致,CloudFormation 自然不会识别到变更。
可行解决方案
方案1:基于S3对象版本触发变更(推荐)
- 首先为
lambda-bucket开启S3版本控制功能,每次上传新的Lambda zip包时S3会自动生成全局唯一的版本ID - 调整SAM模板,新增S3版本号的参数,CodeUri中新增Version字段引用该参数,示例如下:
Parameters: StackStage: Type: String MyFirstLambdaS3Version: Type: String Description: myFirstLambda对应的S3对象版本号 Resources: myFirstLambda: Type: AWS::Serverless::Function Properties: FunctionName: !Sub myFirstLambda-${StackStage} CodeUri: Bucket: lambda-bucket Key: !Sub lambdas/myFirstLambda-${StackStage}.zip Version: !Ref MyFirstLambdaS3Version Handler: lambda_function.lambda_handler Runtime: python3.8 AutoPublishAlias: live
- 每个Lambda专属打包流水线上传zip包后,将返回的版本ID同步更新到CodePipeline的部署参数中,运行部署时版本号发生变化,CloudFormation就会识别到需要更新Lambda代码
- 优势:不需要修改zip包的存储路径,S3版本历史也可以用于后续回滚操作
方案2:基于代码哈希修改文件路径
- Lambda打包阶段对生成的zip包计算内容哈希(比如SHA256),将哈希值拼接到zip包的文件名中,示例路径为
lambdas/myFirstLambda-${StackStage}-${hash值}.zip - 打包流水线上传zip包后,同步更新SAM模板中对应Lambda的CodeUri Key值,再执行SAM打包部署
- 优势:不需要开启S3版本控制,文件名本身就可以标识代码版本;需要额外做旧包清理避免存储桶冗余文件过多
方案3:前置执行Lambda代码更新(适合快速修复)
- 在CodePipeline的CloudFormation ChangeSet步骤前新增一个CodeBuild阶段,执行
aws lambda update-function-code命令直接更新Lambda代码,示例命令:
aws lambda update-function-code --function-name myFirstLambda-${StackStage} --s3-bucket lambda-bucket --s3-key lambdas/myFirstLambda-${StackStage}.zip
- 该方案不需要修改现有SAM模板,但会导致CloudFormation栈资源漂移,不建议作为长期方案使用
内容的提问来源于stack exchange,提问作者shep2180
相关产品推荐
相关产品推荐

