localstack×terraformでlayer付きlambdaをローカルデプロイ
本記事では、localstackとterraformを組み合わせて、layerありのlambda関数をローカル環境で効率的にデプロイする方法を解説します。
実際のコードやディレクトリ構成、ハマりどころも紹介します。
結論
コードを見るのが一番わかり易いと思うので、こちら!
はじめに
従来、localstackの初期化処理でbashスクリプトを用いてS3やLambdaなどのリソースを手動で作成していました(/etc/localstack/init/ready.d
配下でawslocalコマンドを実行)。
しかし、localstackの無料版ではlambda layerが使えないという制約があり、独自実装が必要でした。
この方法には以下の課題がありました。
-
実装が複雑
命令的なスクリプトとなり、リソース作成順序の管理やエラー対応が煩雑でした。 -
キャッシュが効かない
dockerのキャッシュが効かず、初期化のたびに数分かかることもありました。
解決策:terraformによる宣言的な環境構築
これらの課題を解決するため、terraformを用いてリソースを宣言的に管理する方法に切り替えました。(s3も同時に作成したかったため、samではなくterraformを選択)
システム構成図
下図は、lambdaのビルドとデプロイで別々のコンテナを立てている構成です。
一見複雑になった様に見えますが、従来の手動実装と比べてリソース定義がシンプルになり、ビルドとデプロイの責務分離で見通しも良くなりました。
lambdaのビルドは独立しているので、動作確認もしやすいです。[1]
変更前
変更後
参考リポジトリ
今回の実装の全コードは以下のブランチにあります。
ディレクトリ構成と各役割
以下のような構成になっています。
-
lambda_builder
でlambdaのコードをビルド、zip化します。 -
terraform
でzip化したファイルを参照し、lambdaを定義します。 - docker-compose.ymlでディレクトリの共有やビルド設定コマンドの設定をします。
.
├── README.md
├── docker-compose.yml ... 全体の設定
├── lambda_builder
│ ├── Dockerfile ... lambda をビルドするDockerの設定。lambda.tfで指定するpythonのバージョンと合わせる
│ └── Makefile ... ビルド時に使うpythonのインストールやrequirements.txtを使った必要なライブラリのインストールをする
├── src
│ ├── index.py ... lambdaの実装
│ └── requirements.txt ... lambdaで使うライブラリを定義
└── terraform
├── Dockerfile ... terraformのイメージを使う。zipやmake等必要なツールをインストール
├── build ... lambda_builderでビルドした結果が配置される。terraformのコンテナから参照してlambdaをdeployする
│ ├── func
│ └── func.zip
├── lambda.tf ... lambdaをdeployする
└── provider.tf ... terraformの基本設定
実装時の注意点・ハマりどころ
- lambda_builderのDockerfileで指定するpythonバージョンと、lambda.tfで指定するバージョンは必ず合わせること。
バージョン不一致の場合、ModuleNotFoundError: No module named 'psycopg2._psycopg'などのエラーが発生します。
まとめ
以上の方法で、localstackとterraformを連携させ、layerありのlambdaをローカルで効率的にデプロイできるようになりました!!!
開発用のlocal環境などは、その時にすぐできる方法でやってしまいがちですが、ちゃんと考えて作るのは大事ですね。
-
例えば以下のように実行できます。
python -c 'import index; print(index.handler({}, {}))'
↩︎
Discussion