はじめに
前回に引き続きAWS Lambdaについて取り扱っていきます。今回はLocakStackでホットリロードさせるための設定について紹介します。
全体の流れ
まず初めに、どのようにホットリロードを実現するかについて簡単に紹介します。
大まかな流れは以下のとおりです。
- コードの変更を検知する(Watchman)
- 実行ファイルををビルドして、Lambdaにdeployする
それぞれについて、もう少し深掘りします。
コードの変更を検知する
コードの変更の検知にはWatchmanを用います。
Watchmanの機能の1つとして、ファイルを監視しファイルが変更されたときにアクションをトリガーすることができます。
インストール方法については割愛しますので、適宜公式ドキュメントを確認の上、予めインストールしてください。
ファイルをビルドしてdeployする
実行ファイルのdeployについては、AWS CLIの update-function-code APIで行います。
ホットリロードを実現する
それでは、前回のコードをホットリロードできるように改修します。
deployスクリプトを作成する
前回のdeployスクリプトでは、Lambda関数を一度削除してから再度作り直していました。今回はSQS周りの設定などは使い回せるように、実行ファイルのみアップデートするdeployスクリプトを新たに作成します(既存のdeployスクリプトは初回だけ実行するため、lambda_create.shにリネームしておきます)。
新しいdeployスクリプトは以下のとおりです。
1 2 3 4 5 6 7 8 9 10 11 12 | #!/usr/bin/env bash # intel mac用 GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -ldflags '-w -s' -o main ./get_message/main.go zip main.zip main # Lambdaの設定 aws lambda update-function-code --function-name example-sqs-consumer \ --zip-file fileb://main.zip --endpoint-url http://localhost:4566 > /dev/null 2>&1 # 後始末 rm main main.zip |
get_message/main.go
をビルドしてZIP化し、
update-function-code
でZIPをアップロードしています。
Watchmanのラッパースクリプトを作成する
つぎに、Watchmanのラッパースクリプトを作成します。
このスクリプトでは、 get_message ディレクトリを監視対象として、更新があった場合に lambda_deploy.sh を実行します。
スクリプトは以下のとおりです(こちらをほぼそのまま使用)。
1 2 3 4 5 6 7 8 9 10 11 | #!/bin/bash trap "watchman watch-del $(pwd)" EXIT folder=$(pwd)/get_message echo "watching folder $folder for changes" while watchman-wait $folder; do bash -c "./lambda_deploy.sh" watchman watch-del $folder done |
get_message
ディレクトリのファイルに変更があった場合、
lambda_deploy.sh
が実行され、Lambdaが更新されます。
実際に動かしてみる
前回と同様に、LocakStack上にLambdaをdeployして実行すると、コンテナ内に以下のようなログが出力されます。
1 2 | 2023-10-14 03:07:20 localstack_main | 2023-10-13T18:07:20.643 DEBUG --- [ Thread-38] l.s.l.i.version_manager : > Message Body: hoge 2023-10-14 03:07:20 localstack_main | 2023-10-13T18:07:20.644 DEBUG --- [ Thread-38] l.s.l.i.version_manager : > END RequestId: e189eef5-bd31-4354-b19f-56bb13b9206c |
そして、先程作成した
hot-reload.go
を実行した状態で
get_message/main.go
を変更してみると、Lambdaが更新され、コンテナが削除されます。
1 2 3 4 5 6 7 8 9 10 11 12 13 | 2023-10-14 03:11:13 localstack_main | 2023-10-13T18:11:13.264 INFO --- [ asgi_gw_2] localstack.request.aws : AWS lambda.UpdateFunctionCode => 200 2023-10-14 03:11:13 localstack_main | 2023-10-13T18:11:13.267 DEBUG --- [rvice-task_2] l.s.l.i.lambda_models : Saving code example-sqs-consumer-a0cdebbe-8d1a-45b9-b672-fd7013cd25ce to disk 2023-10-14 03:11:13 localstack_main | 2023-10-13T18:11:13.318 DEBUG --- [rvice-task_2] localstack.utils.run : Executing command: ['unzip', '-o', '-q', '/tmp/tmpcx_w0h27'] 2023-10-14 03:11:13 localstack_main | 2023-10-13T18:11:13.384 DEBUG --- [rvice-task_2] l.s.l.i.version_manager : Version preparation of function arn:aws:lambda:ap-northeast-1:000000000000:function:example-sqs-consumer:$LATEST took 116.54ms 2023-10-14 03:11:13 localstack_main | 2023-10-13T18:11:13.384 DEBUG --- [rvice-task_2] l.s.l.i.version_manager : Changing Lambda arn:aws:lambda:ap-northeast-1:000000000000:function:example-sqs-consumer:$LATEST (id ef47b014) to active 2023-10-14 03:11:13 localstack_main | 2023-10-13T18:11:13.384 DEBUG --- [rvice-task_2] l.s.l.i.event_manager : Starting event manager arn:aws:lambda:ap-northeast-1:000000000000:function:example-sqs-consumer:$LATEST id 140064224615376 2023-10-14 03:11:13 localstack_main | 2023-10-13T18:11:13.404 DEBUG --- [rvice-task_2] l.s.l.i.event_manager : Stopping event manager but keep queue arn:aws:lambda:ap-northeast-1:000000000000:function:example-sqs-consumer:$LATEST id 140064208828688 2023-10-14 03:11:13 localstack_main | 2023-10-13T18:11:13.404 DEBUG --- [rvice-task_2] l.s.l.i.event_manager : Stopping event poller arn:aws:lambda:ap-northeast-1:000000000000:function:example-sqs-consumer:$LATEST 140064208335968 2023-10-14 03:11:13 localstack_main | 2023-10-13T18:11:13.405 DEBUG --- [rvice-task_0] l.s.l.i.version_manager : Stopping lambda version 'arn:aws:lambda:ap-northeast-1:000000000000:function:example-sqs-consumer:$LATEST' 2023-10-14 03:11:13 localstack_main | 2023-10-13T18:11:13.405 DEBUG --- [rvice-task_1] l.s.l.i.lambda_models : Final code destruction for example-sqs-consumer-73f63a74-8953-4420-a61d-5a7a8ca417f7 2023-10-14 03:11:13 localstack_main | 2023-10-13T18:11:13.407 DEBUG --- [rvice-task_0] l.u.c.docker_sdk_client : Stopping container: localstack-main-lambda-example-sqs-consumer-e3c71782b7f89a010821a806f8734fa5 2023-10-14 03:11:13 localstack_main | 2023-10-13T18:11:13.591 DEBUG --- [rvice-task_0] l.u.c.docker_sdk_client : Removing container: localstack-main-lambda-example-sqs-consumer-e3c71782b7f89a010821a806f8734fa5 2023-10-14 03:11:15 localstack_main | 2023-10-13T18:11:15.159 DEBUG --- [rvice-task_2] l.s.l.i.event_manager : Waited for poller thread <FuncThread(lambda-poller-example-sqs-consumer:$LATEST-functhread12402, stopped daemon 140063304312576)> |
この状態で再度Lambdaを動かしてみると、このようにログに hot reloaded のメッセージ(fmt.Printlnで出力させた)が表示されるようになっています。
1 2 3 | 2023-10-14 03:18:04 localstack_main | 2023-10-13T18:18:04.316 DEBUG --- [ Thread-42] l.s.l.i.version_manager : > hot reloaded 2023-10-14 03:18:04 localstack_main | 2023-10-13T18:18:04.316 DEBUG --- [ Thread-42] l.s.l.i.version_manager : > Message ID: faf97270-d1d1-40e3-b200-56cf1ac5c82a 2023-10-14 03:18:04 localstack_main | 2023-10-13T18:18:04.316 DEBUG --- [ Thread-42] l.s.l.i.version_manager : > Message Body: hoge |
これで、変更がLambdaに反映されていることが確認できました。
おまけ
おまけとして、Lambdaに実行ファイルではなくコンテナをdeployして実行する方法を紹介します。
やりかたは簡単で、ECRにDockerイメージをアップロードしておき、Lambda関数の作成時に「コンテナイメージ」を選択して、イメージのURIを指定するだけです。
その際、コンテナイメージの下記の項目を上書きすることができます。
- ENTRYPOINT
- CMD
- WORKDIR
ENTRYPOINTとCMDに関してはカンマ区切りで複数の値を指定できます。