LoginSignup
0
0

More than 5 years have passed since last update.

ServerlessでLayerを作成する

Posted at

こんなふうに愚直に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側

template.yml
  #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変換で良いと思う。

template.yml
  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

この場合、テンプレートにはこう記載する。

template.yml
  ctrlDynamodb:
    Type: AWS::Serverless::LayerVersion
    Properties:
        Description: python modules Layer
        ContentUri: layers
        CompatibleRuntimes:
          - python3.6
          - python3.7
          - python2.7

だが、このレイヤーをインポートしてもこのままでは次のようなエラーが発生する。

error
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
template.yml
  ctrlDynamodb:
    Type: AWS::Serverless::LayerVersion
    Properties:
        Description: python modules Layer
        ContentUri: layers
        CompatibleRuntimes:
          - python3.6
          - python3.7
          - python2.7
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0