nato243 weblog.n-jitter brand iconweblog.n-jitter
テクノロジー

AWS Lambda のデプロイを待ってからキャッシュの消去や再生成を行おう

2024.09.26
DockerAWS
AWS Lambda のデプロイを待ってからキャッシュの消去や再生成を行おう アイキャッチ

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のキャッシュを消去するとよいかと思います。