ほぼclassmethodさんの記事通りですが
ソースコード
$ tree . ├── README.md ├── build-layer.sh ├── iam.tf ├── lambda │ ├── function.zip │ └── lib.zip ├── lambda.tf ├── provider.tf ├── requirements.txt ├── src │ └── index.py ├── terraform.tfstate ├── terraform.tfstate.backup └── variables.tf
DeployするLambda functionのソースコード
import os import sys import requests from bs4 import BeautifulSoup def lambda_handler(event: dict, context): response = requests.get("http://example.com/") bs = BeautifulSoup(response.text) return bs.title.name
lambda functionでrequestsとBeautifulSoupを使いたい。そのためにlambda layerを利用する。
Lambda Layer
見るのはlambda.tfとbuild-layer.sh
data "archive_file" "function" { type = "zip" source_file = "./src/index.py" output_path = "lambda/function.zip" } data "archive_file" "layer" { type = "zip" source_dir = "./lib" output_path = "lambda/lib.zip" } resource "aws_lambda_layer_version" "layer" { filename = "${data.archive_file.layer.output_path}" layer_name = "lib" source_code_hash = "${data.archive_file.layer.output_base64sha256}" compatible_runtimes = ["python3.6"] } resource "aws_lambda_function" "example_lambda" { function_name = "example_lambda" runtime = "python3.6" handler = "index.lambda_handler" filename = "${data.archive_file.function.output_path}" role = "${aws_iam_role.iam_role.arn}" source_code_hash = "${data.archive_file.function.output_base64sha256}" layers = ["${aws_lambda_layer_version.layer.arn}"] }
肝になるのはlambda functionとlayerのsourceの参照先の違い。
lambda functionのソースコードは project/src/index.py
を利用するが、
lambda layerは lib/
を利用する。pipライブラリのinstallについてはnull_resourceを利用してterraformで完結しようとしたが、うまく出来なかったので、shellファイルで実行する。何か良い方法あれば教えてほしい
#!/usr/bin/env bash if [ -d lib/ ]; then rm -rf lib/ fi echo "bundle pypi packages" pip install -r requirements.txt -t lib/python find lib -type f | grep -E "(__pycache__|\.pyc|\.pyo$)" | xargs rm
pip installで lib/python を指定しているのはlambda functionからlambda layerを参照するpathを通すため。lib/packagesなどではpathが通らないので注意。 __pycache__と.pyc、pyoを削除しているが、これはpip installをしても__pycache__配下のファイルの影響で差分が発生してしまうから。
$ sh build-layer.sh $ terraform plan $ terraform apply