Help us understand the problem. What is going on with this article?

Lambda Layers をnode.js(SAM)で試してみる

More than 1 year has passed since last update.

re:Invent2018で「Lambda Layers」なるものが発表されました。
これで、私が抱えていた「複数のLambda Functionで共有するものをどうやって同期・更新していくか問題」と「ちょっとしたFunctionで試したいときに外部ライブラリが使えない問題」を解決できるはずです。

参考文献

Lambda Layersとは

Lambda Layers, 複数の関数で共用されるコードやデータをセンタライズし管理するものです

https://aws.amazon.com/jp/blogs/news/new-for-aws-lambda-use-any-programming-language-and-share-common-components/

まずはLayer

Layerに moment.js を入れて、Lambda Functionから参照するというのをやってみます。

LayerはFunctionと同じようにzipファイルをアップロードするという形式のようです。
そのzipファイルはドキュメントによると以下のような構成ということです。

Node.js – nodejs/node_modules, nodejs/node8/node_modules (NODE_PATH)
Example AWS X-Ray SDK for Node.js

xray-sdk.zip
└ nodejs/node_modules/aws-xray-sdk

https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/configuration-layers.html

これに合わせて、ローカルで準備します。

$ mkdir -p layer/nodejs
$ cd layer/nodejs
$ npm init -y
$ npm install moment
$ cd ../..
$ zip -r ../layer.zip ./
  adding: nodejs/ (stored 0%)
  adding: nodejs/node_modules/ (stored 0%)
  adding: nodejs/node_modules/moment/ (stored 0%)
  adding: nodejs/node_modules/moment/CHANGELOG.md (deflated 71%)
  adding: nodejs/node_modules/moment/ender.js (deflated 5%)
(以下略)

出来上がったzipファイルを適当なS3Bucketにアップロードします。

$ cd ..
$ aws s3 cp ./layer.zip s3://<BUCKET>/

これをデプロイ(Layerもデプロイっていうのかな?)するためのSAMテンプレートを作成します。

layer-sam.yaml
AWSTemplateFormatVersion: '2010-09-09'
Transform: 'AWS::Serverless-2016-10-31'
Resources:
  SharedLayer:
    Type: AWS::Serverless::LayerVersion
    Properties:
      LayerName: SharedLayer
      Description: include moment
      ContentUri: 's3://<BUCKET>/layer.zip'
      CompatibleRuntimes:
        - nodejs6.10
        - nodejs8.10
      LicenseInfo: 'Available under the MIT-0 license.'
      RetentionPolicy: Retain
Outputs:
  LayerVersionArn:
    Value: !Ref SharedLayer

aws cloudformation deployコマンドでデプロイします。

aws cloudformation deploy \
  --stack-name shared-layer \
  --template-file layer-sam.yaml

作成されたLayerのArnは後で使うので確認しておきます。

$ aws cloudformation describe-stacks --stack-name shared-layer --query "Stacks[].Outputs"
[
    [
        {
            "OutputKey": "LayerVersionArn",
            "OutputValue": "arn:aws:lambda:us-west-2:xxxxxxxxxxxx:layer:SharedLayer:1"
        }
    ]
]

Layerを参照するFunction

Layerにあるmomentを利用するFunctionを作成します。

functions/Func1/index.js
const moment = require('moment');
exports.handler = async (event) => {
    return {
        moment: moment().format()
    };
}; 

Func1をdeployするためのtemplateファイルをfunctionsディレクトリに作成します。

functions/app-sam.yaml
AWSTemplateFormatVersion: "2010-09-09"
Transform: AWS::Serverless-2016-10-31
Resources:
  Func1:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: Func1
      Handler: index.handler
      MemorySize: 128
      Runtime: nodejs8.10
      Timeout: 300
      Layers:
        - "arn:aws:lambda:us-west-2:xxxxxxxxxxxx:layer:SharedLayer:1"

Layersプロパティに先程のCloudFormationで作成したLayerのArnを指定します。

$ aws cloudformation package \
  --template-file app-sam.yaml \
  --s3-bucket <BUCKET> \
  --output-template-file app-output_sam.yaml

app-output_sam.yamlが出来上がっているのでデプロイします。

aws --region us-west-2 cloudformation deploy \
  --stack-name layer-functions \
  --template-file app-output_sam.yaml \
  --capabilities CAPABILITY_IAM

ではFunctionを実行してみましょう。

$ aws lambda invoke --function-name Func1 output.txt
$ cat output.txt
{"moment":"2018-12-02T14:49:29+00:00"}

これで、Lambda Functionのアップロードファイルに含まれていないライブラリが呼べることが確認できました。

ちょっとしたLambda Functionで外部ライブラリ使えない問題

ちょっとしたお試しでLambda FunctionをManagementConsoleから作ったときに、
これまでは外部ライブラリを呼ぶことができませんでした。
Layersを使えばそれもできるはず!と試してみました。

image.png

Layersを選択すると「レイヤーの追加」ができるのでクリックする。

image.png

先ほど作成したLayerがあるので選択して接続する。

以下のコードを入力して実行してみる。

const moment = require('moment');
exports.handler = async (event) => {
    console.log(moment().format());
    return {};
};

きちんとログに出ていれば成功!

image.png

課題

CodeBuild(それ以外のCIでもいいけど)でFunctionをテストするときに、Layerに依存しているFunctionを確実に実行時と同じLayerを適用してテストするにはどうしたもんか。。。

Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away