はじめに
ServerlessFramework + AWS + Pythonでバックエンドを構築しているとき、開発規模が大きくなってくるとLambda内のPythonコードを共通化したくなることがあると思います。そんなときに使えるのがLambdaレイヤー。Lambdaレイヤーとして作ったモジュールを色々なLambdaで使い回すことができます。モジュールのサイズが大きくなりすぎてコンソールで表示されなくなった時の切り分けにも使えそうです
以前の記事の続きです
最終的な構成
/
├── serverless.yml
├── functions/
│ ├── hello/
│ │ ├── handler.py
│ │ └── requirements.txt
├── layers/
│ ├── original_module.py
├── layers-test/
│ ├── test_original_module.py
作り方
Lambdaレイヤーを定義して、Lambdaと紐付ける
serverless.ymlのルートレベルにLayer定義を追加して、functionsと紐付けます
layers:
layer-modules:
path: layers
description: layer for ingredients
CompatibleRuntimes:
- python3.8
functions:
hello:
module: functions/hello
handler: handler.hello
layers:
- Ref: LayerDashmodulesLambdaLayer # layerとの紐付け部
events:
- http:
path: /users/create
method: get
LambdaとLayerを紐づけている部分ですが、少し変わった名前になっているかと思います。この名前は.serverless/serverless-state-.jsonの中で検索してもらえると出てきます。どうやらlayersで定義している名前「layer-modules」をもとに、自動で生成されているようです(modulesは先頭大文字にならないのか...)
Lambdaレイヤー側のコード
# coding: UTF-8
class OriginalModule:
def add(self, arg1, arg2):
return arg1 + arg2
Lambdaレイヤー呼び出し側のコード
import sys
sys.path.append('/opt')
from original_module import OriginalModule
def hello(event, context):
originalModule = OriginalModule()
result = originalModule.add(3, 5)
# 〜 略 〜 #
LambdaにLayerを紐づけると、Lambda実行ディレクトリの/opt以下に生成されるようです。エラーが出る場合はrequirements.txtを置き忘れていたり名前を間違えていたり、Dockerデーモンが動いているかを確認してみてください
単体テストを追加
Layer化されているとAWSコンソールからでは修正できなくなります。そうすると気軽にトライアンドエラーできなくなるので、単体テストをしっかりやったほうがいいかと思っています
# coding: UTF-8
import unittest
import os
import sys
sys.path.append(
os.path.join(os.path.dirname(__file__),
'../layers/')
)
from original_module import OriginalModule
class TestOriginalModule(unittest.TestCase):
def test_case(self):
target = OriginalModule()
self.assertEqual(target.add(1, 2), 3)
実行するときはこんな感じです
python -m unittest test_original_module