背景
CloudFormation(以降、cfnと記載)を使用して、lambdaソースコードの更新を行いたい時があると思います。
cfnでは、テンプレートファイルに変更があれば更新してくれますが、lambdaのソースコードをS3にアップロードしている場合、lambdaのS3BuketやS3Keyは変化しないので、テンプレートファイルには変更が起きず、結果的にcfnでの更新ができません。
Resources:
layer:
Type: AWS::Lambda::LayerVersion
Properties:
Description: 'pacakge deploy test layer'
LayerName: 'PacakgeDeployTestLambdaLayer'
Content:
S3Bucket: Hoge
S3Key: Layer.zip // Layerの内容を更新してもここの値は一定
Lambda:
Type: AWS::Lambda::Function
Properties:
FunctionName: 'PacakgeDeployTestLambda'
Description: 'pacakge deploy test lambda'
Handler: handler.index
Role: !Ref LambdaIamRoleArn
Runtime: python3.10
MemorySize: 128
PackageType: Zip
Architectures:
- x86_64
Layers:
- !Ref layer
Code:
S3Bucket: Hoge
S3Key: Source.zip // Sourceの内容を更新してもここの値は一定
今回はその対応策をまとめたいと思います。
結論
aws cloudformation packageを使用しよう
aws cloudformation packageコマンドとは?
cfnのテンプレートファイルで記載したファイルやディレクトリを自動でS3にアップロードしてくれて、アップロードしたS3URIをテンプレートファイルに自動で記載してくれるコマンドです。
以下のサイトが参考になるかもです。
具体例
例えば、以下のようなフォルダ構成を考えます。
LambdaのソースコードディレクトリやLayerディレクトリのS3BucketやS3Keyがcfnのテンプレートファイルに自動で更新されたら目的達成です。
目標を達成するために以下の手順を実行します
- cfnテンプレートファイルの修正
- aws cloudformation packageの実行
- 生成されたテンプレートファイルの確認
- 手順2で自動生成されたテンプレートファイルを使用してDeploy
1. cfnテンプレートファイルの修正
S3の値を指定いた部分を修正します
Resources:
layer:
Type: AWS::Lambda::LayerVersion
Properties:
Description: 'pacakge deploy test layer'
LayerName: 'PacakgeDeployTestLambdaLayer'
Content: ./layer // templeteファイルから見た相対パス
Lambda:
Type: AWS::Lambda::Function
Properties:
FunctionName: 'PacakgeDeployTestLambda'
Description: 'pacakge deploy test lambda'
Handler: handler.index
Role: !Ref LambdaIamRoleArn
Runtime: python3.10
MemorySize: 128
PackageType: Zip
Architectures:
- x86_64
Layers:
- !Ref layer
Code: ./source // templeteファイルから見た相対パス
2. aws cloudformation packageの実行
今回はCloudShellを使用してコマンドをたたきます
そのため、テンプレートファイルやSourceディレクトリなどを1つのフォルダにまとめてZip化し、CloudShellにアップロードします。(この際、SourceディレクトリやLayerディレクトリを先にZip化する必要はありません)
CloudShellのアクションから「アップロード」を選択し、Zip化したファイル一式をアップロードします
Unzipしてディレクトリに移動します
ここで aws cloudformation packageコマンドをたたきます
aws cloudformation package --template-file 'package.yaml' --s3-bucket 'cfn-test-main' --s3-prefix lambda --region 'XXXXX-1' --output-template-file 'Lambda.yaml'
各引数の意味
--template-file → S3の値を書き換えたいcfnのテンプレートファイルのパス
--s3-bucket → SourceやLayerなどをアップロードするS3バケット名
--s3-prefix → S3にアップロードしたいディレクトリ.指定がなければ、S3バケット直下にアップロードされる
--region → バケットのリージョン?なくてもいい
--output-template-file → S3の値を書き換えたテンプレートファイルの名前.指定がなければ標準出力に出される
すると、Lambda.yamlというファイルが生成されています。
内容を確認するために、CloudShellのアクションから「ファイルダウンロード」を選択します。
ファイルパスは以下だと思います。※Pacakgeとかは各自で異なります
/home/cloudshell-user/Package/lambda.yaml
3. 生成されたテンプレートファイルの確認
以下の内容のように、ContentやCodeの部分の値が変更されています。
Resources:
layer:
Type: AWS::Lambda::LayerVersion
Properties:
Description: pacakge deploy test layer
LayerName: PacakgeDeployTestLambdaLayer
Content:
S3Bucket: cfn-test-main // --s3-bucketで指定した値
S3Key: lambda/f36168fedef3585c635ae45f998a6706 // 自動で割り当てられる乱数
Lambda:
Type: AWS::Lambda::Function
Properties:
FunctionName: PacakgeDeployTestLambda
Description: pacakge deploy test lambda
Handler: handler.index
Role:
Ref: LambdaIamRoleArn
Runtime: python3.10
MemorySize: 128
PackageType: Zip
Architectures:
- x86_64
Layers:
- Ref: layer
Code:
S3Bucket: cfn-test-main // --s3-bucketで指定した値
S3Key: lambda/391f85c3f6f07f7a979cbc243fea3f83 // 自動で割り当てられる乱数
S3バケットを確認すると指定したバケットのlambdaフォルダ内に自動で割り当てられた乱数のファイルが存在していることが分かります
ここまでで、コマンドを使用したテンプレートファイルの生成とS3へのアップロードが確認できました。
テンプレートファイルには、lambdaのソースコード置き場の値が変更されているので、cfnを使用してlambdaが自動で更新されることができると思います。
4. 手順2で自動生成されたテンプレートファイルを使用してDeploy
コマンドで生成されたテンプレートファイルでlmabdaを更新してみます。
今回はテンプレートファイルをS3に置いて、AWSマネジメントコンソールでcloudformationサービスをポチポチしながらdeployしてみたい思います。
aws cloudformation packageコマンドで作成されたテンプレートファイルをS3に配置します
AWSマネジメントコンソールでcloudformationからstackを立ち上げます
自動でアップロードされたsoruceコードがアップロードされていることが確認できます
まとめ
今回はaws cloudformation packageコマンドを使用して、cloudformationでLambda, Lambda Layerを更新する方法を紹介しました。
今回はAWSマネジメントコンソールで更新処理をしましたが、aws cloudformation deployコマンドを使用すれば手作業をより減らして対応できるかもですね。