Python
Node.js
AWS
lambda
aws-sdk

Lambda Layers で最新の AWS SDK を使用する

Lambda Layersとは

AWS re:Invent 2018で Lambda Layers(以下、Layer) が発表されました。
以前は実行に必要な全てのライブラリを1つのパッケージとしてzip化してデプロイする必要がありました。
Layer では複数の関数で利用されるような一般的なコンポーネントを
1つのzipファイルとしてアップロードして利用することができます。
関数のコードは変更する必要はなく、レイヤー内のライブラリーを参照することができます。

新機能 – AWS Lambda :あらゆるプログラム言語への対応と一般的なコンポーネントの共有
https://aws.amazon.com/jp/blogs/news/new-for-aws-lambda-use-any-programming-language-and-share-common-components/

本記事ではPythonを例に Lambda Layerで 最新のAWS SDKを利用する方法を記載します。

LayerにAWS SDKを置くと何がよいのか

Lambdaの実行環境には AWS SDK for JavaScript および Python(Boto3)が含まれています。
以下のドキュメントによれば 2018/12/3時点では各SDKのバージョンは以下の通りです。

  • AWS SDK for JavaScript – 2.290.0
  • SDK for Python (Boto 3) – 3-1.7.74 botocore-1.10.74

Lambda Execution Environment and Available Libraries
https://docs.aws.amazon.com/lambda/latest/dg/current-supported-versions.html

これが何を意味するかですが、
AWSのUpdateにより新しく追加されたAPI使用するためには最新のSDKをデプロイパッケージに含める必要がありました。
例えば少し前に追加されたCloudWatchのget-metric-widget-imageを最新のSDKをデプロイせずに実行すると
以下のようなエラーが返されます。

image.png

Layer によりAWS SDKを外出しすることにより、スリムなデプロイパッケージを維持しつつも最新のAPIを使用できます。
特にNode.js、Python、Rubyの場合はデプロイパッケージが3MB未満であれば、
コンソールでコードを確認できるメリットがあります。

AWS SDKのLayerを作成する

実際にやってみます。

Layerの作成

まずローカルでLayerのパッケージ(ZIP)を作成します。
外部ライブラリをLayerに含めるには、ランタイム毎に定められたパスのいずれかに配置する必要があります。

  • Pythonの場合: python/ or python/lib/python3.7/site-packages/ (site directories)
  • Node.jsの場合: nodejs/node_modules or nodejs/node8/node_modules (NODE_PATH)

その他のランタイムも以下のドキュメントに記載があります。
Including Library Dependencies in a Layer
https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/configuration-layers.html#configuration-layers-path

Pythonの場合、以下のようにLayerパッケージを作成することができます。

$ mkdir python
$ pip install -t ./python boto3
$ zip -r boto3-1.9.57.zip python

次にコンソールでLayerを作成します。
メニューから Layers を選択し、レイヤーの作成をクリックします。

image.png

作成したzipファイルを直接アップロードするか、S3上のパスを記載します。(関数のデプロイと一緒です)
あとはLayerの名前、説明、互換性のあるランタイム、オプションでラインセンス情報を記載し、
作成を選択するだけです。

image.png

Layerを追加することができました。簡単ですね。

image.png

LayerをLambda関数に組み込む

Lambda関数から作成したLayerを利用する設定を行います。
デザイナーで関数名の下にあるLayersを選択し、参照されるレイヤーからレイヤーの追加をクリックします。

image.png

LayerのARNを入力するか、リストから選択し、接続を押下するだけです。

image.png

レイヤーを追加したら変更を保存します。

image.png

以上で設定は完了です。

動作確認

以下のような超簡易コードで確認してみます。

lambda_function.py
import boto3

def lambda_handler(event, context):
    print(boto3.__version__)

Before(Layer追加前)

1.7.74 です。ドキュメント通り。

START RequestId: f3e23a03-f6f5-11e8-9531-21cb32e1956a Version: $LATEST
1.7.74
END RequestId: f3e23a03-f6f5-11e8-9531-21cb32e1956a
REPORT RequestId: f3e23a03-f6f5-11e8-9531-21cb32e1956a  Duration: 0.32 ms   Billed Duration: 100 ms     Memory Size: 128 MB Max Memory Used: 27 MB  

After(Layer追加後)

1.9.57になっています。

START RequestId: c0ec808c-f6f7-11e8-8692-87076a4ebc4a Version: $LATEST
1.9.57
END RequestId: c0ec808c-f6f7-11e8-8692-87076a4ebc4a
REPORT RequestId: c0ec808c-f6f7-11e8-8692-87076a4ebc4a  Duration: 0.35 ms   Billed Duration: 100 ms     Memory Size: 128 MB Max Memory Used: 34 MB  

注意点など

  • 1つの関数から参照できるLayerは最大5つまでです
    • 更に展開されたパッケージサイズが250MBを超えることができません
  • LayerのZIPファイルは同じパスに展開されるため、上書きに注意が必要です
    • レイヤーのマージ順序を使用することである程度制御できます
  • Layerのバージョンを更新した場合、Lambda側でも参照するバージョンを変更する必要があります
  • 外部パートナーが提供するLayerを使用することもできます

以上です。
参考になれば幸いです。