LocalStackにLambdaとSQSをデプロイしてみる。
今回使用するLambda Function(Python)
def lambda_handler(event, context):
for record in event['Records']:
print(record['body'])
LocalStack向けのsam localを実行する手順
けっこう長いことLambdaを使ってきていて知らなかったんだけど、 sam local コマンドを LocalStack 向けにラップした localstack/aws-sam-cli-local: Simple wrapper around AWS SAM CLI for use with LocalStack があり、LocalStackにデプロイしたりinvokeしたりができる。
合わせて localstack/awscli-local: 💲 “awslocal” - Thin wrapper around the “aws” command line interface for use with LocalStack も入れておこう。
LocalStack 用のDocker composeファイルを作成する
version: "3.8"
services:
localstack:
container_name: "${LOCALSTACK_DOCKER_NAME-localstack_main}"
image: localstack/localstack
ports:
- "127.0.0.1:4566:4566" # LocalStack Gateway
environment:
- DEBUG=${DEBUG-}
- AWS_DEFAULT_REGION=ap-northeast-1
- DOCKER_HOST=unix:///var/run/docker.sock
volumes:
- "/var/run/docker.sock:/var/run/docker.sock"
sam用のtemplate.yaml
AMyQueueMyQueueWSTemplateFormatVersion: 2010-09-09
Transform: AWS::Serverless-2016-10-31
Resources:
Function:
Type: AWS::Serverless::Function
Properties:
FunctionName: my-function
CodeUri: app/
Handler: app.lambda_handler
Runtime: python3.9
Architectures:
- arm64
Events:
SqsEvent:
Type: SQS
Properties:
Queue: arn:aws:sqs:ap-northeast-1:000000000000:my-queue
デプロイしてみる
$ samlocal build
$ samlocal deploy --guided
(いろいろパラメータを入力する)
これでデプロイできたはず。
aws lambda create-functionでアップロードする手順
これのためにsam localを入れるのはどうかと思ったので、aws cliだけでもできないかを検討してみた。
まずtemplate.yamlで作っていたqueueをLocalStackの起動時処理で作るようにする
version: "3.8"
services:
localstack:
container_name: "${LOCALSTACK_DOCKER_NAME-localstack_main}"
image: localstack/localstack
ports:
- "127.0.0.1:4566:4566" # LocalStack Gateway
environment:
- DEBUG=${DEBUG-}
- AWS_DEFAULT_REGION=ap-northeast-1
- DOCKER_HOST=unix:///var/run/docker.sock
volumes:
- ./init/ready.d:/etc/localstack/init/ready.d
- "/var/run/docker.sock:/var/run/docker.sock"
ライフサイクルフックでqueueを作る
#!/bin/bash
awslocal sqs create-queue --queue-name my-queue
Lambda Functionを作成する
$ zip app app.py
$ awslocal lambda create-function --function-name my-app --runtime python3.9 --role arn:aws:iam::000000000000:role/my-app --handler app.lambda_handler --zip-file fileb://app.zip
# 起動後に、作成済みの関数を更新したい場合はこちら
$ awslocal lambda update-function-code --function-name my-app --zip-file fileb://app.zip
# 作成or更新する関数を作っちゃうのもあり
function create_or_update_lambda_function() {
FUNCTION_NAME=$1
if ! awslocal lambda create-function --function-name my-app --runtime python3.9 --role arn:aws:iam::000000000000:role/my-app --handler app.lambda_handler --zip-file fileb://app.zip; then
awslocal lambda update-function-code --function-name my-app --zip-file fileb://app.zip
fi
}
# SQSと紐付ける
$ if [[ "$(awslocal lambda list-event-source-mappings --query "EventSourceMappings[?contains(EventSourceArn, 'my-queue')]")" == "[]" ]]; then
awslocal lambda create-event-source-mapping --function-name my-app --event-source-arn arn:aws:sqs:ap-northeast-1:000000000000:my-queue
fi
動作確認
$ awslocal sqs send-message --queue-url http://localhost:4566/000000000000/my-queue --message-body '{ "my-key": "my-value" }'
# ログを確認
$ function_name=my-app
$ awslocal logs get-log-events --log-group-name /aws/lambda/${function_name} --log-stream-name $(awslocal logs describe-log-streams --log-group-name /aws/lambda/${function_name} | jq -r '.logStreams[0].logStreamName')