🍣

localstackを使ったlambdaのdeployについて

2023/11/29に公開

初めに

localstackにpython lambdaのdeployを試みた。
いろいろと詰まる部分があったので整理しておきます。

結論

  • lambda layer は proである必要がある(https://docs.localstack.cloud/user-guide/aws/lambda/#lambda-layers-pro)
  • インストールしたパッケージをhandlerのコードと同じディレクトリに直置きすればlayerを使わずに済む
  • pythonの依存関係をインストールする場合は実行時のインタープリタのバージョンと合わせたpipを使うこと

localstackのlambda layer

以下の様なコマンドでlayerのpublishができる

mkdir python
pip install -r requirements.txt -t python
zip -r my-layer.zip python
awslocal lambda publish-layer-version \
    --layer-name my-layer \
    --zip-file fileb://my-layer.zip

以下の様なコマンドでlayerを使うlambdaがdeployできる

zip -r /tmp/func.zip ./src/*
function_name=my-func
role=arn:aws:iam::000000000000:role/lambda-role
awslocal lambda create-function \
    --function-name ${function_name} \
    --runtime python3.9 \
    --handler index.handler \
    --zip-file fileb:///tmp/func.zip \
    --role ${role} \
    --architectures arm64 \
    --layers arn:aws:lambda:ap-northeast-1:000000000000:layer:my-layer:1

しかし実際にlambdaのコンテナにはいってpythonを実行するとrequirements.txtでインストールしたはずのパッケージがないというエラーが起きる。

deployの時点では成功するのが罠。
localstack proでないとlayerがつかえない。

layerを使わずにパッケージ込みのlambdaをdeployする

ではどうするかというと、lambdaのhandlerのコードと同じところにパッケージを展開してやり、zip化してやればよい。
具体的には以下の様なコードでdeployする。

mkdir /tmp/lambda_src
pip install -r requirements.txt -t /tmp/lambda_src
(cp ./src/* /tmp/lambda_src && cd /tmp/lambda_src && zip -r /tmp/func.zip ./*)
function_name=my-func
role=arn:aws:iam::000000000000:role/lambda-role
awslocal lambda create-function \
    --function-name ${function_name} \
    --runtime python3.9 \
    --handler index.handler \
    --zip-file fileb:///tmp/func.zip \
    --role ${role} \
    --architectures arm64 \
    --layers arn:aws:lambda:ap-northeast-1:000000000000:layer:my-layer:1

pip install -t でインストール先のディレクトリを指定。
(実際にはpipだけではダメな場合あり。次に説明)
cp でhandlerのコードを同じディレクトリにコピー。
同じディレクトリに移動してzipファイル作成。

依存関係インストール時のpythonのインタプリタのバージョンを合わせる

前述の通りに実施しても、
"ModuleNotFoundError: No module named 'psycopg2._psycopg'"
という様なエラーが出ることがある。これはpythonのバージョンの差異による問題。

例えば、python3.9のlambdaの実行環境に対してpython3.10でpip installしてパッケージを準備すると、psycopg2/_psycopg のファイルが存在せず、import時にエラーとなる。これを回避するためには

python3.9 -m pip install ...
の様にpython3のバージョンを指定してpipを実行すればよい。

最後に

awslocal lambda create-function の処理が通ってしまったので、layerが使えるはずだと勘違いしてだいぶ時間を食ってしまいました。awslocalで新しいコマンドを実行する時は、community対応しているかどうかを最初に確認する必要がありますね。

Discussion