Lambdaのデプロイには諸派あり
AWS Lambda はコード実体とIAMによる認可系インフラが若干密結合しており、誰しも一度はそのデプロイ方法に頭を悩ませます。
勝手にLambdaの卵鶏問題と呼んでます。
私はインフラとしてのLambdaとコード内容のデプロイは、公私ともにある程度分離して実装することが多いです。
すなわち、LambdaをDeployする際は、Lambdaは先にterraformやCDKなどのIaCツールでデプロイしておき、ビジネスロジックたるLambdaのコードはインフラとは別にあとでデプロイします。
これは、リンク先にもあるように、仕事で使っているIaCが完全にビジネスロジックとは別リポジトリであることも大きいです。
この場合、Lambdaのデプロイはlambrollなどを使って行うことがおすすめではありますが、
とはいえ一度deploy scriptを書いてさえしまえば、aws-cliによるデプロイでもたいして難しくはありません。
Lambda x Docker をビルド/デプロイする例
LAMBDA_FUNC_NAME = sample_lambda_docker
ECR_COM = xxxx.dkr.ecr.ap-northeast-1.amazonaws.com
REPOSITORY_URI_LAMBDA=${ECR_COM}/sample_lambda_docker
build:
mkdir -p .build
docker build \
-f ./Dockerfile \
--platform linux/arm64 \
--progress=plain \
-t sample_lambda_docker:latest ../..
rm -rf .build || true
deploy:
export AWS_PAGER="" && \
aws ecr get-login-password | docker login --username AWS --password-stdin ${ECR_COM} && \
docker tag sample_lambda_docker:latest ${REPOSITORY_URI_LAMBDA}:latest && \
docker push ${REPOSITORY_URI_LAMBDA}:latest
# UPDATE
aws lambda update-function-code \
--function-name ${LAMBDA_FUNC_NAME} \
--image-uri "${REPOSITORY_URI_LAMBDA}:latest" \
--publish
これは、本ブログのようなDocker x Lambda 構成をデプロイするためのMakefileです。
Dockerをビルド後、ECRにpushし、aws-cli
の lambda update-function-code
を実行します。
これによってDocker Imageの変更を明示的にLambdaに伝達します。
基本的にはこれでOKなのですが、CDN のキャッシュリセットやなんらかのLambdaの暖機運転(cold start回避)を行いたい場合は、一工夫が必要です。
更新状態をポーリングする
deploy:
export AWS_PAGER="" && \
aws ecr get-login-password | docker login --username AWS --password-stdin ${ECR_COM} && \
docker tag sample_lambda_docker:latest ${REPOSITORY_URI_LAMBDA}:latest && \
docker push ${REPOSITORY_URI_LAMBDA}:latest
# UPDATE
@echo "Lambdaを更新"
aws lambda update-function-code \
--function-name ${LAMBDA_FUNC_NAME} \
--image-uri "${REPOSITORY_URI_LAMBDA}:latest" \
--publish
@echo "更新の伝播を待機中...."
@while [ "$$(aws lambda get-function --function-name ${LAMBDA_FUNC_NAME} --query 'Configuration.LastUpdateStatus' --output text)" = "InProgress" ]; do \
echo "更新中... 待機しています"; \
sleep 5; \
done
@echo "更新が完了しました。"
# CloudFrontキャッシュ無効化
@echo "CloudFrontのキャッシュを無効化中..."
aws cloudfront create-invalidation \
--distribution-id "xxxxxxx" \
--paths "/*"
@echo "CloudFrontのキャッシュ無効化が完了しました。"
update-function-code
の後、実際にDocker Imageの更新が伝播するまでには時間がかかります。なので、すぐにCDNなどのキャッシュを消しても、更新前の古いコードへのアクセスでキャッシュが作られてしまうことがあります。
そこで、 Lambdaの更新ステータスをポーリングした後で処理を行います。
上記MakefileのConfiguration.LastUpdateStatus
の部分ですね。
その後、あらめてLambdaをinvokeするなり、CDNのキャッシュを消去するとよいかと思います。