こんなふうに愚直にLayer代わりを作ってたわけですよ
https://qiita.com/heat_exchange/items/a38a7a5572e0c09e3422
ただどうしてもlayerを使いたい場合というのがあって、例えば
- モジュールが大容量なとき
- コードがインラインで見れない
- インポート先が一つ増えるごとにコマンドを一つ増やすのはだるい
と思っていると、Serverless でLambda Layerを作成できることを知った。
本当にLambda Layersで幸せになれるのか? 旧式のデプロイ方式からLambda Layersを活用したデプロイ方式への移行を検討する
これは試してみるほかない。
コード
先程の記事1や公式ドキュメント2を参考に書いていく。ここでは、次のようなディレクトリ構造を念頭に置く。
.
├── template.yml
├── layers
└── python
└── dynamodb.py
Layer側
#Cloudformation内の物理ID。ProertiesでlayerNameを設定しなければ、自動的にこれがLayerNameとなる
PythonModulesLayer:
Type: AWS::Serverless::LayerVersion
Properties:
#layerの説明
Description: python modules Layer
#layerのURI。S3のURIを指定しても良いが、Cloudformationなら、相対パスを記載することもできる。
ContentUri: ./layer/python
#lmbda layerの互換性。これを設定しておくことで、レイヤーの設定が楽になる。リストで指定する。
CompatibleRuntimes:
- python3.7
- python3.6
- python2.7
#Layerのライセンス情報
LicenseInfo: string
#Layerのバージョン保持設定。Retainにしておくことで、layerバージョンをアップデート後も古いバージョンは保持される
RetentionPolicy: Retain(Default)|Delete
Lambda側の設定
lambdaもserverless変換を使わないとlayerを使えないっぽい?要確認。よほどのことが無い限りlambdaの作成はServerless変換で良いと思う。
testLambda:
Type: AWS::Serverless::Function
Properties:
Handler: test.handler
Runtime: python3.7
CodeUri: tesLambda
Role:
!GetAtt testLambdaRole.Arn
#レイヤーは!Ref(または!Sub)で値を取得し、リストで列挙していく。
Layers:
- !Ref PythonModulesLayer
Timeout: 25
あと普通にlayerを使うつもりでlambdaを使っていけば良い。
つまづきどころ
Cloudformationからlambda-layerを作成するときは、pythonフォルダごとアップロードしなければならない。
やや基礎的な部分だが、自分がつまづきやすいのでメモ
例えば、layerにしたいモジュールを、次のようなディレクトリ構造で保存していたとする。
.
├── template.yml
├── layers
└── module.py
この場合、テンプレートにはこう記載する。
ctrlDynamodb:
Type: AWS::Serverless::LayerVersion
Properties:
Description: python modules Layer
ContentUri: layers
CompatibleRuntimes:
- python3.6
- python3.7
- python2.7
だが、このレイヤーをインポートしてもこのままでは次のようなエラーが発生する。
No modules named modules
ここで、lambdaの使用を確認してみる。3
ポイントは以下の2つです。
Layerのコードは /opt 以下に展開される
/opt 以下の特定のパスはあらかじめライブラリ検索パスに設定されている
例としてPython 3.7の場合を見てみます。まず sys.path を表示するだけの簡単なLambda関数を実行してみると、以下のような結果が得られます。/opt/python, /opt/python/lib/python3.7/site-packages が含まれています。
Lambda Layerの基本的な仕組みを確認する #reinvent
lambdaは標準で/opt
以下のディレクトリがインポートされるようになっているので、lambda側のディレクトリ構造を調べてみると、次のようになっている。
.
├── opt
└── module.py
本来あるべきであるディレクトリpython
が無いことがわかる。
そこで、次のようにしなければならない。
.
├── template.yml
├── layers
└── python
└── dynamodb.py
ctrlDynamodb:
Type: AWS::Serverless::LayerVersion
Properties:
Description: python modules Layer
ContentUri: layers
CompatibleRuntimes:
- python3.6
- python3.7
- python2.7