🐕

LocalStackでAWSイベント駆動アーキテクチャのE2Eテスト環境を作る

2023/10/29に公開

はじめに

AWSを使って何かサービスを開発する際に、SQSやLambdaなどを利用したイベント駆動アーキテクチャを採用すると運用負荷を抑えつつスケールしやすい構成になります。一方で、そうしたアーキテクチャはテストが難しいという課題もあります。例えば、S3へのファイルアップロードをトリガーにSQSにメッセージ送信してLambdaで処理するようなアーキテクチャを考えたとき、Lambdaの処理そのものは単体テストが容易な設計ができますが、S3の通知設定やSQSをトリガとしたLambdaの起動などインフラ構成含めた設計の試行錯誤やテストをしなければ実際に動くところまで担保できません。また、継続的に改善開発することを考えると、毎回AWSにデプロイして確認するよりできるだけローカルで手早く回帰テストを実行したくなります。
LocalStackはローカル環境でクラウドサービスをエミュレートすることができるツールです。無料で利用できるCommunity版と有料のPro版があります(機能差はこちらに載っています)が、Community版でもいくつかのAWSサービスをローカル環境でエミュレートすることができます。
https://localstack.cloud/

今回検証したいアーキテクチャの概要

今回は以下のようなS3、SQS、Lambdaの構成をLocalStackを使って動作検証してみました。
S3にCSVファイルをアップロードするとSQSを介してLambdaが起動し、イベント内容をプリント出力します。

LocalStackコンテナの構築

LocalStackはコンテナで立ち上げることもできますので、以下のようにdocker-compose.ymlファイルを記述することで簡単に構築できます。
https://github.com/manaty226/localstack-s3-sqs-lambda/blob/b3e64bc4973206025ee03f13c708767ebc0027d5/docker-compose.yml#L4-L19

Terraformによる環境構築

インフラをterraformで開発している場合、terraformの設定も含めて正しくなければ実装が動かないところが、AWSのイベント駆動アーキテクチャを実現しようとしたときの難しさの一つと感じています。コンテナで立ち上げたLocalStackのエミュレート環境のインフラをterraformで構築することができるので、ローカルでインフラ含めた試行錯誤をしたり、実際の構築設定に準じたE2Eテストができるのも嬉しいところです。
LocalStackに対してterraformを実行するときは、以下のようにプロバイダ設定を色々とローカル向けにごまかす必要があります。
https://github.com/manaty226/localstack-s3-sqs-lambda/blob/b3e64bc4973206025ee03f13c708767ebc0027d5/main.tf#L14-L31

実行例

構築した環境でS3にCSVファイルをアップロードしてLambdaが起動するか確かめます。
LocalStackコンテナに入ってCSVファイルをアップロードしてみます。

docker compose exec localstack /bin/bash
# csvファイルを作成
touch test.csv
# S3にアップロード
awslocal s3 cp ./test.csv s3://test-bucket-4i9k6jgxye

すると、localstackコンテナの標準出力に以下のようなログがでてくるので、S3のイベント通知をトリガーにLambdaが起動していることがわかります。

localstack  | 2023-xx-xxTxx:xx:xx.xxx DEBUG --- [   Thread-29] 
l.s.l.i.version_manager    : > The message 70605d8b-bd2c-444d-8b46-d55a26e1a655 for event source aws:sqs = 
{"Records": [{"eventVersion": "2.1", "eventSource": "aws:s3", "awsRegion": "ap-northeast-1", "eventTime": "2023-xx-xxTxx:xx:xx.xxx", "eventName": "ObjectCreated:Put", "userIdentity": {"principalId": "xxxxxxxxxxx"}, "requestParameters": {"sourceIPAddress": "127.0.0.1"}, "responseElements": {"x-amz-request-id": "c95eaca0", "x-amz-id-2": "eftixk72aD6Ap51TnqcoF8eFidJG9Z/2"}, "s3": {"s3SchemaVersion": "1.0", "configurationId": "tf-s3-queue-20231028130921223900000001", "bucket": {"name": "test-bucket-4i9k6jgxye", "ownerIdentity": {"principalId": "xxxxxxxxxxx"}, "arn": "arn:aws:s3:::test-bucket-4i9k6jgxye"}, "object": {"key": "test.csv", "sequencer": "0055AED6DCD90281E5", "size": 0, "eTag": "d41d8cd98f00b204e9800998ecf8427e"}}}]} 

おわりに

LocalStackを使ってAWS環境のエミュレートをすることで、テストが難しいアーキテクチャのテスト環境をローカルに構築することができました。初期立ち上げではインフラ含めた試行錯誤をローカルで試すことができるのと、継続開発時には回帰テストをAWSにデプロイすることなく高速にできる可能性があるのが嬉しさだと思います。

Discussion