以前、「AWS SAMで作成したLambdaのバージョン管理することができないか」といった事象を経験したことがあり、その時調べた内容などの備忘録になります。
AWS SAM におけるUpdateの挙動
まず初めに、AWS SAMにてLambdaバージョンを作成するには、AutoPublishAliasを有効にする必要があります。(これによりLambdaのバージョンとエイリアスが作成。)
結論から言うと、旧Versionの保持についてはAWS::Serverless::Function上のプロパティからも保持するオプションのようなものはありません。
理由としては、以下の通りです。
以下のように、SAMで作成されたCfn スタックをアップデートする前に変更セットを作成します。
その時のリソースの変更部分を確認した結果、
SAM で作成したLambdaのUpdateを実施すると以下のように古いLambdaバージョンを削除して、新しいバージョンを作成し、Lambdaのエイリアスに最新バージョンを登録するような動きが確認できます。
CloudFormation stack changeset
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Operation LogicalResourceId ResourceType Replacement
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+ Add DemoMomentoFunctionVersion92c48a93f7 AWS::Lambda::Version N/A
* Modify DemoMomentoFunctionAliasdemo AWS::Lambda::Alias False
* Modify DemoMomentoFunction AWS::Lambda::Function False
- Delete DemoMomentoFunctionVersion9215c6e11b AWS::Lambda::Version N/A
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
実際にやってみた結果は以下の通りです。
スタック更新前と更新後のリソースを確認した結果、やはりバージョンのリソースAWS::Lambda::Version
自体が削除され、新規で作成したバージョンがCfnスタックに登録されています。
そのため、旧バージョンがこのままでは保持できないということになります。
対処法
対処としては結構シンプルでCloudformationのテンプレート 上でDeletionPolicy: Retain
を追加してあげればリソース自体はCloudformationのスタックの管理対象からは外れますが、Version自体は保持されます。
注意として、Lambdaに関する全てのリソースが保持されるため、スタック自体を削除したい場合は、Retainの記述を削除してから更新をかけた方がよろしいかと。
そのため、以下のようなCloudformationテンプレートで、SAMリソースに対して、DeletionPolicy: Retain
とすれば良いかと思います。
AWSTemplateFormatVersion: "2010-09-09"
Transform: AWS::Serverless-2016-10-31
Description: >
momento_api_demo
Sample SAM Template for momento_api_demo
Globals:
Function:
Timeout: 30
Resources:
API:
Type: AWS::Serverless::Api
DeletionPolicy: Retain
Properties:
Name: demo-sam-api-momento
EndpointConfiguration:
Type: REGIONAL
StageName: demo
DemoMomentoFunction:
Type: AWS::Serverless::Function
DeletionPolicy: Retain
Properties:
FunctionName: demo-sam-function-momento
CodeUri: demo_momento/
Handler: lambda_function.lambda_handler
Runtime: python3.10
AutoPublishAlias: demo
Architectures:
- x86_64
Environment:
Variables:
TestEnv: "hoge"
Events:
DemoMomento:
Type: Api # More info about API Event Source: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#api
Properties:
Path: /demo_momento
Method: get
RestApiId: !Ref API
上記の内容でSAMを更新してみました結果は以下の通りです。
Lambdaのバージョンですが、画像のようにバージョン管理できていることが確認できます。
ただし、AutoPublishAliasでエイリアスを作成している場合、バージョンは自動的に$LATESTのバージョンに更新されます。
AutoPublishAlias上で作成されるエイリアスのため、エイリアスと関連づけるバージョンを明示的に指定したい場合は、SAMを諦めるかもしくは、AutoPublishAliasを使わず外出しでAWS::Lambda::Aliasを定義する必要があると思います。
結論
AWS SAM で作成したLambdaのUpdateは、
- 新バージョンの作成
- エイリアスを新バージョンに設定
- 旧バージョンの削除
という動きをするため、旧バージョンは自動的に削除される挙動をします。
DeletionPolicyをRetainにすることで、旧バージョンを保持しつつ関数を更新することができ、何かあった際は迅速に旧バージョンへ手動でロールバックできます。
ただしエイリアスの明示的なバージョン指定はできないため、もし必要ならAutoPublishAliasを使わず別だしでAWS::Lambda::Aliasを定義する必要があると思います。