AWS CloudFormation 更新 Lambda 代码以在 S3 存储桶中使用最新版本
Posted
技术标签:
【中文标题】AWS CloudFormation 更新 Lambda 代码以在 S3 存储桶中使用最新版本【英文标题】:AWS CloudFormation update Lambda Code to use latest version in S3 bucket 【发布时间】:2020-01-26 08:37:21 【问题描述】:我正在尝试创建一个支持 Lambda 函数和 AWS CodeBuild 项目的 CloudFormation 模板,用于将 .netcore 源代码构建到 S3 存储桶中已部署的 zip 文件中。 详情如下:
在 .netcore 解决方案中使用具有多个 Lambda 函数的 GitHub 单一存储库作为不同项目 每个 Lambda 函数(又名 .netcore 项目)都有一个 CloudFormation YAML 文件,该文件生成一个包含 Lambda 函数本身和 CodeBuild 项目的堆栈。 CodeBuild 项目从 GitHub Web 挂钩启动,该挂钩从 GitHub 子项目中检索代码并使用其 buildspec.yaml 来控制构建应该如何进行。 buildspec 使用 .netcore 构建项目,然后将输出压缩并复制到目标 S3 存储桶 Lambda 函数指向 S3 存储桶获取源代码这一切都很好。我正在苦苦挣扎的是如何更新 Lambda 函数以在 S3 存储桶中使用更新后的编译源代码。
这是 CloudFormation 模板的子集:
Resources:
Lambda:
Type: AWS::Lambda::Function
Properties:
FunctionName: roicalculator-eventpublisher
Handler: RoiCalculator.Serverless.EventPublisher::RoiCalculator.Serverless.EventPublisher.Function::FunctionHandler
Code:
S3Bucket: deployment-artifacts
S3Key: RoiCalculatorEventPublisher.zip
Runtime: dotnetcore2.1
CodeBuildProject:
Type: AWS::CodeBuild::Project
Properties:
Name: RoiCalculator-EventPublisher-Master
Artifacts:
Location: deployment-artifacts
Name: RoiCalculatorEventPublisher.zip
Type: S3
Source:
Type: GITHUB
Location: https://github.com/XXXXXXX
BuildSpec: RoiCalculator.Serverless.EventPublisher/buildspec.yml
这是 buildspec.yaml 的子集:
phases:
install:
runtime-versions:
dotnet: 2.2
commands:
dotnet tool install -g Amazon.Lambda.Tools
build:
commands:
- dotnet restore
- cd RoiCalculator.Serverless.EventPublisher
- dotnet lambda package --configuration release --framework netcoreapp2.1 -o .\bin\release\netcoreapp2.1\RoiCalculatorEventPublisher.zip
- aws s3 cp .\bin\release\netcoreapp2.1\RoiCalculatorEventPublisher.zip s3://deployment-artifacts/RoiCalculatorEventPublisher.zip
您可以看到构建规范(用于生成和复制)和 CloudFormation 模板(用于 Lambda 函数的源)中使用了相同的工件名称 (RoiCalculatorEventPublisher.zip) 和 S3 存储桶 (deployment-artifacts)。
由于我使用 Lambda 使用的相同文件名覆盖 S3 存储桶中的应用程序代码,为什么 Lambda 没有更新为最新代码?
版本号如何工作?是否可以在 buildspec AND CloudFormation 模板中拥有一个包含工件名称(文件名 + 版本号)的“系统变量”并访问相同的“系统变量”?
利用 CloudFormation 模板通过 CodeBuild 生成源代码(通过 buildspec)以及更新使用生成代码的 Lambda 函数的秘诀是什么?
谢谢。
【问题讨论】:
this 问题的可能重复 【参考方案1】:很遗憾,除非您在每次更新时更改“AWS::Lambda::Function”资源上的“S3Key”,否则 CloudFormation 不会将其视为更改(它不会查看压缩代码内部的更改)。
选项:
选项 1) 每次上传时更新 S3 密钥
选项 2) 推荐的建议是使用 AWS SAM 编写 Lambda 模板,然后使用“cloudformation package”命令打包模板,该模板负责为 S3 创建唯一密钥并将文件上传到存储桶。详情在这里:https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-deploying.html
编辑 1:
针对您的评论,让我补充一些 SAM 方法的细节:
将 CloudFormation 用作管道中 Lambda 函数的部署工具。部署 Lambda 函数的基本思路如下:
1) 为您的 Lambda 函数创建一个 SAM 模板
2) 一个基本的 SAM 模板如下所示:
AWSTemplateFormatVersion: '2010-09-09'
Transform: 'AWS::Serverless-2016-10-31'
Resources:
FunctionName:
Type: 'AWS::Serverless::Function'
Properties:
Handler: index.handler
Runtime: nodejs6.10
CodeUri: ./code
3) 添加目录“code”,并将 lambda 代码文件保存在该目录中
4) 安装 SAM Cli [1]
5) 运行命令打包上传:
$ sam package --template-file template.yaml --output-template packaged.yaml --s3-bucket your_S3_bucket
6) 部署包:
$ aws cloudformation deploy --template-file packaged.yaml --stack-name stk1 --capabilities CAPABILITY_IAM
您可以将模板代码(步骤 1-2)保留在 CodeCommit/Github 中,并在 CodeBuild 步骤中执行步骤 4-5。对于第 6 步,我建议通过 CodePipeline 中的 CloudFormation 操作执行此操作,该操作将“packaged.yaml”文件作为输入工件提供。
另见 [2]。
参考资料:
[1] 在 Linux 上安装 AWS SAM CLI - https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-install-linux.html
[2] 使用 AWS CodePipeline 为 Lambda 应用程序构建持续交付管道 - https://docs.aws.amazon.com/en_us/lambda/latest/dg/build-pipeline.html
【讨论】:
所以您推荐的方法是将 CloudFormation 模板更改为使用 SAM 方法,然后修改 buildspec 命令以打包模板?您的建议是否适合我正在使用的构建规范方法?将代码签入 GitHub 后,我还能进行自动构建和部署吗?或者,这是一种不同的方法吗? 我不确定正确的操作顺序是否适合您推荐的方法。 cloudformation 包如何与使用 .netcore 构建 C# 位的 buildspec 配合使用?【参考方案2】: 我使用的是aws scp
,而不是aws cp
,从来没有遇到过这个问题。
我正在开发一个具有多个 lambda 的无服务器架构的项目,其中我们有多个文件夹,其中只有一个 python 文件和 require.txt 文件。
通常为方便起见,目录和 lambda 名称相同,例如。文件夹 email_sender
将有 python 文件作为 email_sender.py
和 requirement.txt
如果需要的话。
在安装依赖项后的代码构建中,我只是在下面展示我们是如何压缩的
echo "--- Compiling lambda zip: $d.zip"
d=$(tr "_" "-" <<< "$d")
zip -q -r $d.zip . --exclude ".gitignore" --exclude "requirements.txt" --exclude "*__pycache__/*" > /dev/null 2>&1
mv $d.zip ../../$CODEBUILD_SOURCE_VERSION/$d.zip
在复制到 s3 存储桶时,我们使用 scp,如下所示
aws s3 sync $CODEBUILD_SOURCE_VERSION/ $S3_URI --exclude "*" --include "*.zip" --sse aws:kms --sse-kms-key-id $KMS_KEY_ALIAS --content-type "binary/octet-stream" --exact-timestamps
【讨论】:
以上是关于AWS CloudFormation 更新 Lambda 代码以在 S3 存储桶中使用最新版本的主要内容,如果未能解决你的问题,请参考以下文章
AWS API Gateway RestAPI CloudFormation 更新不更新部署资源
使用CloudFormation模板更新AWS Athena工作组
使用 AWS CLI 时发布的错误中更新 cloudformation 堆栈时出现回滚错误
AWS - 错误 - 更新 Auto Scaling 组、Amazon CloudFormation、无法部署配置