ほぼ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