CloudFormationでIaCを構成しているとき、テンプレートの更新は反映されても、Lambdaのコードの更新が反映されない場合があります。
SAMを使用せず、以下のようなLambdaのテンプレートでデプロイしようとした時に発生しました。
lambda.yaml
TestPythonCode:
Type: AWS::Lambda::Function
Properties:
FunctionName: TestPythonCode
Code:
S3Bucket: !Ref RootBucket
S3Key: 'TestPythonCode.zip'
Role: 'arn:aws:iam::${AWS::AccountId}:role/lambdaExecusionRole'
Handler: fileName.lambda_handler'
Runtime: python3.12
この場合、S3Keyの値に更新がないと、CloudFormationの更新でLambdaのデプロイが反映されません。
変更セットに値の変更がないため、デプロイが実行されないようです。
解決策
CodeBuild内でTimeStampを生成して、LambdaのZipファイル名につける。
S3のZip名にタイムスタンプを組み込むことで、CloudFormation内で毎回Lambda.zipファイルのデプロイが行われるようになります。
記載例
タイムスタンプ作成シェル
timestamp.sh
#!/bin/bash
# 変数に格納
timestamp=$(date +"%Y%m%d%H%M%S")
echo $timestamp
LambdaをZip化するCodeBuildのアクション
BuildSpec.yaml
version: 0.2
# ここでのちのアクションに受け渡す環境変数を作成
env:
exported-variables:
- TIMESTAMP_LAMBDA
phases:
install:
runtime-versions:
python: 3.11
command:
- echo install
- pip install --upgrade pip
- pip install --upgrade --user awscli
- aws --version
pre_build:
commands:
- echo pre_build
build:
commands:
- echo "CloudFormation Build"
post_build:
commands:
- echo "CloudFormation template S3 push"
- pwd
- cd ./deploy/template/lambda/src
- export TIMESTAMP_LAMBDA=$(sh ./timestamp.sh) # 環境変数にタイムスタンプを指定
- echo $TIMESTAMP_LAMBDA
- sh ./build.sh "$TIMESTAMP_LAMBDA"
- cd ../../../../../
- pwd
- aws s3 cp ./02_deploy/$EnvironmentType s3://deploy/ --recursive --exclude "*" --include "*.yaml" --include "*.zip"
CodePipelineのテンプレート
codepipeline.yaml
Resources:
# Deploy Pipeline
ppline:
Type: AWS::CodePipeline::Pipeline
Properties:
# ~パイプラインの設定省略~
Stages:
# 変更セット作成ステージ
- Name: ChangeSetCreateStage
Actions:
- Name: ChangeSetReplaceAction
ActionTypeId:
Category: Deploy
Owner: AWS
Version: 1
Provider: CloudFormation
InputArtifacts:
- Name: SourceZip
Configuration:
ChangeSetName: Hoge
ActionMode: CHANGE_SET_REPLACE
StackName: Hoge
Capabilities: CAPABILITY_NAMED_IAM,CAPABILITY_AUTO_EXPAND
TemplatePath: "TemplateFilePath"
RoleArn: "RoleArn"
RunOrder: 1
# 変更セットデプロイステージ
- Name: Deploy
Actions:
- Name: DeployRoot1
ActionTypeId:
Category: Deploy
Owner: AWS
Provider: CloudFormation
Version: 1
Configuration:
ActionMode: CHANGE_SET_EXECUTE
RoleArn: "RoleArn"
StackName: Hoge
ChangeSetName: Hoge
# CodeBuild内で作成したタイムスタンプを指定
ParameterOverrides: !Sub |
{
"TimeStampLambda": "#{BuildVariables.TIMESTAMP_LAMBDA}"
}
ParameterOberridesの項で、BuildSpec.yaml内でエクスポートした環境変数を指定してCloudFormationのパラメータに指定しています。
Lambdaのテンプレート
Lambda.yaml
TestPythonCode:
Type: AWS::Lambda::Function
Properties:
FunctionName: TestPythonCode
Code:
S3Bucket: "TestBucketS3URI"
# ポストフィックスにタイムスタンプをつける
S3Key: 'TestPythonCode_${TimeStampLambda}.zip'
Role: 'arn:aws:iam::${AWS::AccountId}:role/lambdaExecusionRole'
Handler: fileName.lambda_handler'
Runtime: python3.12
S3のZip名にタイムスタンプを組み込むことで、CloudFormation内で毎回Lambda.zipファイルのデプロイが行われるようになります。
最後に
今回は既存のソースコードを修正、かつSAMを使わないという縛りだったため、このようになりましたが、
新規開発の場合はSAMを使用してcloudformation --packageをした方が良いかと思います。