AWS Lambda LayersをServerless Frameworkでつかってみた。#reinvent

AWS Lambda Layersを用いてjqをServerlessFramework製のアプリケーションに組み込んでみました。
2018.12.30

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

はじめに

好物はインフラとフロントエンドのかじわらゆたかです。
AWS Lambda LayersをServerlesFrameworkで使う方法の紹介です。

Layer層の作成

今回はjqを含んだLayerを作成し、そのLayerをServerless Frameworkのアプリに組み込みたいと思います。

jqを含んだLayer構築のシェルはこちら。

#!/bin/bash -eu
if [ $# -ne 1 ]; then
  echo "指定された引数は$#個です。" 1>&2
  echo "実行するには1個の引数が必要です。" 1>&2
  echo "$0 [AWS CLI Profile]"
  exit 1
fi
profile=$1
mkdir bin
curl https://github.com/stedolan/jq/releases/download/jq-1.6/jq-linux64 -o  ./bin/jq -L
chmod 755 ./bin/jq
zip -r jq-layer.zip ./bin
aws lambda publish-layer-version --layer-name jq-layer --zip-file fileb://jq-layer.zip --profile ${profile}

行っていることとしてはjqのバイナリを取得し、bin配下に配置するようにzipファイルを作成し、 lambda layerにjq-layerという名前でpublishしています。 注意点としては、jqに実行権限を付与するのと、curlでjqをダウンロードするとリダイレクトするのでそのためのオプションを付与しておく必要があります。

Serverless Framework側の実装

今回はjqの導入を行ったので、確認用に以下のコードを記載しました。

handler.py

import json
import subprocess

json_file = "./commits.json"


def hello(event, context):
    commit_message = subprocess.run([
        "jq",
        ".[0] | {message: .commit.message, name: .commit.committer.name}",
        json_file
    ],
                                    stdout=subprocess.PIPE)

    message = json.loads(commit_message.stdout.decode())
    return json.dumps(message)

行っていることとしては、jqチュートリアルを動かしています。 ダウンロードしたコミットメッセージのjsonファイルcommits.jsonに対して、1件目のコミッターの名称とコミットメッセージの取得をするといった内容になります。

上記のコードを含ませたServerless FrameworkのアプリケーションをDeployしても、 jqが含まれていないといったエラーとなってしまいます。

そのため、serverless.yamlでLambda関数でLayerのARNを記載する必要があります。 AWS - Layers

Lambda LayerのARNを取得して、環境変数に設定し、デプロイするために以下のように記載を行いました。

serverless.yaml

service: serverless-with-jq 

provider:
  name: aws
  runtime: python3.7

functions:
  hello:
    handler: handler.hello
    layers:
      - ${env:LAYER}
#!/bin/bash
if [ $# -ne 1 ]; then
  echo "指定された引数は$#個です。" 1>&2
  echo "実行するには1個の引数が必要です。" 1>&2
  echo "$0  [AWS CLI Profile]"
  exit 1
fi
profile=$1
layer=`aws lambda list-layers --profile ${profile}  | jq -r '.[][]| select(.LayerName =="jq-layer") | .LatestMatchingVersion.LayerVersionArn'`
export AWS_PROFILE=${profile}
export LAYER=${layer}
sls deploy
unset AWS_PROFILE
unset LAYER

AWS CLIのlist-layersのレスポンスには最新のLayerのARNが含まれるため、それをjqを用いて取得を行い 環境変数にセットし、Serverless Frameworkのアプリケーションのデプロイを行っています。 Serverless Frameworkのアプリケーション側ではLayerの値は環境変数から取得します。

これにより、jqを含めたLayerを含ませることで正常に動くことが確認できます。

まとめ

これにより簡単なjsonの加工はjq側で行い、複雑な処理はpythonでといったLambda関数の実装をServerless Frameworkで行うことができます。