AWS Lambda の Custom Runtimes を利用して Elixir で作られた Lambda + API Gateway を実行してみる #reinvent

この記事は AWS Lambda Custom Runtimes芸人 Advent Calendar 2018 の 21日目 です。

はじめに

keynoteの二日目で AWS Lambda でカスタムランタイムが利用できる発表があり、 AWS Lambda での言語選択の幅に選択肢が増えたことで、多くのアプリケーション開発者を熱狂させました。

【アップデート】 もう言語で悩まない!AWS LambdaでCustom Runtimeが利用できるようになりました! #reinvent

早速ですが、 Alert Logic から ErlangElixir の AWS Lambda についての記事が上がってました。

ErlangとElixirは、多くの開発者に人気のある言語ですが、これまでAWS Lambdaではサポートされていませんでした。 これらの言語は、独自の賛否両論があります。 Alert Logic は、 Erlang ネイティブランタイムと rebar3 を使用したビルドとパッケージングの統合サポート、およびElixirネイティブランタイムによるAWS Lambda機能のサポート、およびMixを使用した統合ビルド/パッケージサポートのサポートを含むAWSラムダ機能のサポートをリリースしました。

Erlang が動作するところは以前、 Erlangを動かしてみたブログ の方で挑戦したのですが、今回は Elixir で作成された Lambda をAPI経由で実行するところまでやってみたいと思います。

AWS Lambda で Elixir を実行

AWS Lambda のカスタムランタイムとして、 aws-lambda-elixir-runtime を使用することで、 Elixir を AWS Lambda で実行させることができます。

せっかくなのでHello World的な簡易プログラムではなく、 API Gateway + Lambda + DynamoDB のオーソドックスなサーバーレスアプリケーション構成を試して見たいと思います。

構成は ErllambdaElixirExample という、サンプル実装が提供されていますので、こちらを使ってみました。

$ git clone https://github.com/alertlogic/erllambda_elixir_example.git
$ cd erllambda_elixir_example

Elixir build用のdocker imageを取得

ビルド用の docker image、 alertlogic/erllambda が提供されていますので、こちらを使用します。 Elixir の動作環境については、別途タグが打たれたものを利用します。 2018/12/20時点では、 20.3-elixir のタグが追加されていました。

$ docker pull alertlogic/erllambda:20.3-elixir

プロジェクトのビルド

以下の mix deps.get コマンドで依存するファイルを取得します。

$ docker run -it --rm -v `pwd`:/buildroot -w /buildroot -e MIX_ENV=prod alertlogic/erllambda:20.3-elixir mix deps.get

最後に mix erllambda.release コマンドを実行すれば、 Lambda にアップロードできる形式のバイナリが出力されます。

$ docker run -it --rm -v `pwd`:/buildroot -w /buildroot -e MIX_ENV=prod alertlogic/erllambda:20.3-elixir mix erllambda.release

バイナリは、 _build の下位のフォルダに配置されます。

_build/prod/rel/erllambda_elixir_example/releases/0.1.0/erllambda_elixir_example.zip

AWS Lambda のデプロイ

CloudFormation テンプレートでのデプロイ方法が提供されていますので、こちらのコマンドでデプロイします。

CloudFormation テンプレート用の S3 バケットを作成しておきます。 バケット名の erllambda-elixir-example の部分は任意の名前で構いません。

$ aws s3api create-bucket --bucket erllambda-elixir-example

CloudFormation のパッケージをアップロードするコマンドを実行します

$ aws cloudformation package \
    --template-file etc/template.yaml \
    --output-template-file packaged.yaml \
    --s3-bucket erllambda-elixir-example

パッケージをアップロードした後に CloudFormation のデプロイコマンドを実行します。

$ aws cloudformation deploy --capabilities CAPABILITY_IAM \
    --template-file packaged.yaml \
    --stack-name erllambda-elixir-example

コマンドを実行すると、ランタイムに 「独自のランタイム」 が指定された AWS Lambda がデプロイされます。

Amazon API Gateway の方にもリソースが作成されました。

AWS Lambda の実行

curlでPOSTコマンドを叩いて見ましょう。API経由でパラメータに指定された値を元に、DynamoDBへの書き込みが実施されます。

$ curl -X POST https://xxxxxxxxxx.execute-api.us-east-1.amazonaws.com/Prod/MyResource?id=0001&message=test

動きました!DynamoDBのテーブルに指定された値が入力されています。

まとめ

カスタムランタイムは用途が限定的ではありますが、標準で提供されている言語では対応しきれない処理を一つの Lambda で捌く要件が出た際に、活躍の場が出てくるのかもしれないですね。(その時は Lambda 以外を検討したほうがいいのかもしれませんが...)

参考文献