我正在尝试使用CloudFormation创建一个新版本的Lambda函数 .
我想拥有相同Lambda函数的多个版本,这样我就可以(a)指向不同版本的别名 - 比如DEV和PROD - 以及(b)能够回滚到早期版本
这是我的Lambda版本的定义:
LambdaVersion:
Type: AWS::Lambda::Version
Properties:
FunctionName:
Ref: LambdaFunction
运行“aws cloudformation create-stack”时会创建一个版本,但后续的“aws cloudformation update-stack”命令不会执行任何操作 . 没有创建新的Lambda版本 .
我正在尝试在将新的zip文件上传到S3然后运行"update-stack"后创建新版本的Lambda函数 . 我可以使用CloudFormation做到吗? AWS :: Lambda :: Version真的坏了(这里提到https://github.com/hashicorp/terraform/issues/6067#issuecomment-211708071)或者我只是没有得到什么?
Update 1/11/17 亚马逊支持的官方回复:“...对于要发布的任何新版本,您需要定义一个添加(原文如此)AWS :: Lambda :: Version资源......”
AWS CloudFormation / Lambda团队,如果您正在阅读此内容 - 这是不可接受的 . 修理它 .
7 回答
我们可以制作一个Lambda部署包;
将Lambda包与版本一起作为Cloud Formation参数之一传递,例如"LambdaPakcageNameWithVersion";
使用"LambdaPakcageNameWithVersion"作为Lambda代码s3键;
在运行aws-cli命令以更新 Cloud 形式堆栈或运行CI / CD管道时,将部署新的Lamdba软件包 .
Answer updated for February 2018
You can use AWS SAM (Serverless Application Model), and its sam package and sam deploy commands to update Lambda . 它们类似于
aws cloudformation package
和aws cloudformation deploy
命令,但也允许您自动更新Lambda版本 .SAM可以打包您的代码(或者使用您创建的ZIP包),将其上传到S3,然后从中更新Lambda的
$LATEST
版本 . (如果这就是你所需要的,这也可以用aws cloudformation
完成,没有SAM;代码示例与下面相同,但仅使用CloudFormation
的标准声明) . 然后,使用SAM,如果进行了相应配置,您还可以自动发布版本并更新别名以指向它 . 它还可以选择使用AWS CodeDeploy逐渐将流量从先前版本移动到新版本,并在发生错误时回滚 . 所有这些都在Safe Lambda deployments中解释 .从技术上讲,这个想法是每次更新堆栈时,都需要
AWS::Lambda::Function
的Code
指向S3中的 new 包 . 这将确保在更新堆栈时,Lambda的$ LATEST版本将从新包中更新 . 然后,您还可以自动发布新版本并将Alias切换到该版本 .为此,创建一个SAM模板,类似于CloudFormation模板的(超集) . 它可能包含特定于SAM的声明,如下面的
AWS::Serverless::Function
声明 . 将Code
指向源代码目录(或预先打包的ZIP),并设置AutoPublishAlias
属性 .跑:
这将源目录内容打包为ZIP(如果
Code
不是ZIP),在新的自动生成密钥下将其上传到S3,并生成最终的CloudFormation模板到packaged.yaml
,为您提供正确的Code
引用;像这样:现在您可以使用SAM生成
packaged.yaml
来创建函数版本:这将更新Lambda的
$LATEST
版本,如果定义了AutoPublishAlias
,则将其发布为新版本并更新Alias以指向新发布的版本 .有关完整的模板代码,请参阅examples in SAM GitHub repo .
AWS::Lambda::Version资源仅表示单个已发布的Lambda函数版本 - 它不会在每次更新代码时自动发布新版本 . 要实现此目的,您有两种选择:
1.自定义资源
您可以实现自己的Custom Resource,在每次更新时调用PublishVersion .
对于这种方法,每次更新堆栈时仍需要更改至少一个参数,以便触发将触发PublishVersion操作的自定义资源的更新 . (但是,您不必实际更新模板 . )
这是一个完整的,有效的例子:
2.模板预处理器
您可以使用模板预处理器(如embedded Ruby)(或仅在每次部署时手动更新模板),在代码更新时通过更改
AWS::Lambda::Version
资源的Logical ID来在代码的每次更新时发布新版本 .例:
要在通过
erb
模板预处理器传递template.yml
时创建/更新堆栈,请运行:不幸的是,使用CloudFormation无法做到这一点 . 您需要在CloudFormation模板中为每个版本添加新的
AWS::Lambda::Version
部分 .最接近的解决方案是创建.erb模板并让它生成包含所有版本的CloudFormation模板 .
AWS :: Lambda :: Version无用 . 您必须为每个Lambda版本添加新资源 . 如果要为每个Cloudformation更新发布新版本,则必须进行修改系统 .
我解决了这个问题,创建了一个为每个部署触发的Lambda支持的自定义资源 . 在这个Lambda中,我正在为参数中给出的Lambda函数创建一个新版本 .
对于Lambda的源代码,您可以查看http://serverless-arch-eu-west-1.s3.amazonaws.com/serverless.zip
以下是使用此部署Lambda函数的示例Cloudformation(您可能需要进行一些修改):
(免责声明:此代码是我的书的一部分,有关Lambda和API Gateway的更多信息,请查看:https://www.amazon.com/Building-Serverless-Architectures-Cagatay-Gurturk/dp/1787129195)
我有一个类似的用例(需要使用CloudFormation来管理在CloudFront中使用@edge的lambda函数,对于该函数,总是需要一个特定的lambda函数版本,而不是
$LATEST
)并且我的搜索首先在这个问题上找到了我,但之后更多的挖掘我很高兴地发现现在支持自动lambda版本使用AWS无服务器应用程序模型的新AutoPublishAlias
功能(基本上是为CloudFormation模板提供的一组可选的更高级别构造) .在这里宣布:https://github.com/awslabs/serverless-application-model/issues/41#issuecomment-347723981
详情见:
https://github.com/awslabs/serverless-application-model/blob/master/docs/safe_lambda_deployments.rst#instant-traffic-shifting-using-lambda-aliases
https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#referencing-lambda-version--alias-resources
基本上你在
AWS::Serverless::Function
定义中包含AutoPublishAlias
:然后在CloudFormation模板的其他位置,您可以将最新发布的版本引用为
!Ref MyFunction.Version
(yaml语法) .寻找与从S3部署的Lambda函数一样的类似事物 .
我的用例是这样的:
您有一个cloudformation模板,可以从S3存储桶位置创建Lambda函数
您需要更新此功能,以便在本地进行代码更改并将更改推送到S3
您现在想要将这些更改推送到Lambda,以便您尝试更新堆栈,并且cloudformation表示没有更新更新,因此您必须使用AWS Lambda控制台手动更新代码 .
对此不满意我找了一个替代方案并遇到了这个问题 . 没有一个答案对我有用,所以我已经采取了一些想法并在这里修改了答案,并用Python编写了我自己的版本 .
这段代码改编自@wjordan的答案,因此对他的想法和原始答案给予了褒奖 . 不同之处是:
这是用Python编写的
它适用于从S3存储桶部署的Lambda代码
它更新代码并发布新版本
您需要一个nonce参数 . 当代码需要重新发布到Lambda时,您可以更改此参数的值 . 这是为了确保cloudformation将更新您的自定义资源 . 更新自定义资源后,它将运行最终更新Lambda代码的Python代码 .
希望这有助于某人 .