notebook

都内でWEB系エンジニアやってます。

lambda layerと関数を1つの設定で行う

Lambda Layerを使うときのメモ

以前Serverless FrameworkでLambdaLayerを使ってみたがその時はLayer用にディレクトリを切って設定ファイルも関数とは別であとからARNで参照させる感じだった

  • ディレクトリ構成
- プロジェクトルート
- Layer用のディレクトリ
    - serverless.yml
- 関数用のディレクトリ
    - app.js
    - serverless.yml

ARNでの参照だとarn:aws:lambda:ap-northeast-1:111111111111:layer:modules:4といったようにバージョンまで指定しないと行けないのでLayer側の中身が変わった場合コチラも手動で編集する必要がある

Serverless Frameworkに下記のようにLayerへの参照だけ指定する方法があるのでそちらを使いたい

  • before
functions:
  sample:
    handler: handler.run
    layers:
      - arn:aws:lambda:ap-northeast-1:111111111111:layer:modules:4
  • after
functions:
  sample:
    handler: handler.run
    layers:
      - {Ref: HogeLambdaLayer}

また、1つのプロジェクトでLayerと関数とを1つの設定ファイルで管理したい

という経緯で今回すこし時間をとって調べてみた

なを今回はchrome-aws-lambdaをLayerに切り出す

Layerの仕様と設定

ただ関数を定義してデプロイするのと比べるとLayerの場合

  • /opt以下に成果物が置かれる
  • Lambdaが探しに行くパスが決まっている
    • /opt/nodejs/node_modules/opt/nodejs/node8/node_modules (NODE_PATH)

という感じになっている

AWS Lambda レイヤー - AWS Lambda

docs.aws.amazon.com

Serverless Frameworkはpathに指定したディレクトリ以下のファイルをそのまま置くようになっているので成果物用のディレクトリを作成してそれに合わせてディレクトリの中身を構成してあげれば良い

dist的なものがあるのかと思って調べてみたがなさそうだった

なのでLayerで指定するpath以下のディレクトリ構成は下記のようになる

  • serverless.yml
layers:
  puppeteer:
    path: puppeteer_layer_dist/
$ pwd
project_name

$ tree puppeteer_layer_dist
puppeteer_layer_dist
`-- nodejs
    `-- node_modules
        `-- chrome-aws-lambda -> ../../../node_modules/chrome-aws-lambda/

chrome-aws-lambdaからnode_modulesへはシンボリックリンクを貼っている

mkdir -p puppeteer_layer_dist/nodejs/node_modules
cd puppeteer_layer_dist/nodejs/node_modules
ln -s  ../../../node_modules/chrome-aws-lambda/ chrome-aws-lambda

これを行うことでローカルでの実行とデプロイしてから実行するパターンの両方に対応できる

Nodeのバージョン

node10が使えるし10にしてやったろ!と試してみたところ下記の様なエラーで実行できなかった

2019-09-15T21:41:49.495Z 9d620ee6-fe56-43a8-af91-fc95f799f7dd ERROR Invoke Error
{
    "errorType": "Error",
    "errorMessage": "Failed to launch chrome!\n/tmp/chromium: error while loading shared libraries: libnss3.so: cannot open shared object file: No such file or directory\n\n\nTROUBLESHOOTING: https://github.com/GoogleChrome/puppeteer/blob/master/docs/troubleshooting.md\n",
    "stack": [
        "Error: Failed to launch chrome!",
        "/tmp/chromium: error while loading shared libraries: libnss3.so: cannot open shared object file: No such file or directory",
        "",
        "",
        "TROUBLESHOOTING: https://github.com/GoogleChrome/puppeteer/blob/master/docs/troubleshooting.md",
        "",
        "    at onClose (/var/task/node_modules/puppeteer/lib/Launcher.js:348:14)",
        "    at Interface.helper.addEventListener (/var/task/node_modules/puppeteer/lib/Launcher.js:337:50)",
        "    at Interface.emit (events.js:203:15)",
        "    at Interface.EventEmitter.emit (domain.js:448:20)",
        "    at Interface.close (readline.js:397:8)",
        "    at Socket.onend (readline.js:173:10)",
        "    at Socket.emit (events.js:203:15)",
        "    at Socket.EventEmitter.emit (domain.js:448:20)",
        "    at endReadableNT (_stream_readable.js:1145:12)",
        "    at process._tickCallback (internal/process/next_tick.js:63:19)"
    ]
}

The current Chromium Binary doesn't work for AWS nodejs10.x runtime · Issue #37 · alixaxel/chrome-aws-lambda

github.com

おそらく上記の問題に引っかかり、現段階だとchrome-aws-lambdaはnode10系だとまだ実行できない模様

このあたり不便だよなーと思いながら仕方なくnode8.10にして実行するようにした

まとめ

Serverless FrameworkでLayerを使ってPuppeteerを動かす際のメモ

  • Layer用のディレクトリ構成には気をつける
    • nodejsが必要
  • Layer用のディレクトリに対象のモジュールのシンボリックリンクを貼る
    • 運用省力化
  • chrome-aws-lambdaはnode10だとまだ動かせない(2019-09-17時点)

Lambdaをどんどん使っていきたいと思っているもののなかなかベストプラクティス的なものがないイメージあるので指摘があれば教えていただければ嬉しいです