⌨️

今から始めるLambda③「Layersを使う」

2021/10/21に公開

はじめに

前回の記事ではLambdaのローカルでの実行やAWS CLIからのデプロイ方法について紹介しました。

https://zenn.dev/nekoniki/articles/10ac0c37957cc9

その中でnode_modulesを絡めたコードをデプロイすることにも言及しました。
今回はそのあたりを掘り下げつつ、Lambda Layersの扱い方を紹介していきたいと思います。

AWS Lambda Layersとは

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

公式には以下のような説明があります。

Lambda レイヤーは、追加のコードやデータを含めることができる .zip ファイルアーカイブです。

要するにLambdaの関数本体とは別に用意することができるコード、データのことです。

どういう時に使うのか

主には異なるLambda関数間で、同じ処理を使いたい場合に利用します。

例えば自作関数のfuncHogeLambda関数であるlambdaFunc1lambdaFunc2の両方で使いたい場合、funcHogeLambda Layersにすることで共有することができます。

自作関数でなくとも、node_modulesの中のライブラリのように、Lambdaを横断して使いたいものがある場合はLayersに含めます。

Layersの作成

lambda-layer-sampleというディレクトリを作成し、Axiosを用いて郵便番号から住所検索を行うコードを作成します。

その際にnode_modulespackage.jsonなどを含めたコード群はnodejs、自作のコードはlibという階層を作ってまとめます。

mkdir lambda-layer-sample
cd lambda-layer-sample
mkdir nodejs
cd nodejs

nodejs配下でaxiosnpm installします。

npm install axios

さらにaxiosを使って郵便番号検索を行うコードを作成します。
名前はgetAddressFromZipCode.jsとします。
注意点として、作成する階層はlib以下とします。

lib/getAddressFromZipCode.js
const axios = require("axios");
module.exports = async (zipcode) => {
  try {
    return await axios(`https://api.zipaddress.net/?zipcode=${zipcode}`);
  } catch (e) {
    throw e;
  }
};

ここまでできたらZIPファイルに固めます。
注意点としては、固めるのはnodejsディレクトリごとなので、lambda-layer-sample配下で以下コマンドを実行します。

zip -r9 layer.zip .

これでlayer.ziplambda-layer-sample直下に作成されました。

Layersのデプロイ

早速デプロイしていきます。
デプロイはpublish-layer-versionで行います。

ランタイムやレイヤー名などをオプションで指定した上で実行します。

aws lambda publish-layer-version --layer-name sample-layer --description "create layer" --zip-file fileb://layer.zip --compatible-runtimes nodejs10.x nodejs12.x nodejs14.x

レスポンスとしてJSONが返り、AWSLambdaのコンソールから【レイヤー】を選択すると、以下のように反映されていることが分かります。

LayersLambdaに紐づける

さっそくLayersLambdaの紐付けを行いたいと思います。

今回はtestFunction3という名称でLambdaは作成済みとします。
中身は以下とします。

const getAddressFromZipCode = require("getAddressFromZipCode");

exports.handler = async function (event, context) {
  const res = await getAddressFromZipCode(9071801);
  console.log(res);
  return context.logStreamName;
};

先ほど作成したgetAddressFromZipCoderequireしていますが、当然このLambda単体では動作しません。

先のLayersと紐づけて初めて動作するLambdaです。

LayersのARNを確認

紐付けを行うにあたってLayersのARNを確認する必要があります。

確認は以下コマンドで行います。

aws lambda list-layer-versions --layer-name sample-layer --query "LayerVersions[*].LayerVersionArn"

Layerspublish-layer-versionを行う度にバージョンが上がっていきますが、このコマンドで全てのバージョンのARNが確認できます。

紐付け

では紐付けを行いましょう。
紐付けはlambda update-function-configurationで行います。

オプションで先のLayersのARNの値などを付けます。

aws lambda update-function-configuration --function-name testFunction3 --layers "【LayersのARN】"

確認

AWSのコンソールからtestFunction3を実行してみましょう。
紐付け前はgetAddressFromZipCodeが見つからなくて動作しなかった関数が正常に動作するようになったかと思います。

補足:なぜ/libなのか

Layersを作成した際に、自作のスクリプトをnodejs/libの中に含めました。

実はそれには意味があり、AWSにおけるLambdaLayersの紐付け方が挙げられます。

実はLambdaと紐付けたLayersは、すべて/optというディレクトリ配下に格納されています。
AWS側で、この/opt以下の特定のパスを環境変数として持っています(以下リンク参照)。

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

その中にnodejs/node_modulesがあります。
ここへのパスが通っているため、Lamdaの関数からLayersで使用しているモジュールが参照できます。

さらに注目すべきはlibにもパスが通っている点です。
実運用的にはソース管理を行うかと思いますが、その際にnode_modulesignoreされてしまうケースがほとんどです。

なので自作分のコードに関してはlibに配置した上で使用しています。

まとめ

今回はLayersLambdaの関数の紐付けについて紹介しました。

API GatewayDBのトリガーと絡めたり、一通りの処理をLambdaで作ると、依存するライブラリの数もそれなりに多くなります。

それらを包括的に管理する意味でもLayersは非常に便利な機能なので、ぜひマスターしておきましょう。

今回の内容が役立てば幸いです。

Discussion