emahiro/b.log

Drastically Repeat Yourself !!!!

コンテナで Lambda を動かす

Overview

12 月の re:invent で Lambda のパッケージングフォーマットにコンテナイメージがサポートされたので、少し遅くなりましたが、デプロイまで試してみました。

今回はランタイムに Go を使用してます。

このエントリは以下のドキュメントを参考にしてます。

aws.amazon.com

コンテナイメージを ECR にアップロードする

別エントリで書きましたのでそちらを参考にしてください。

ema-hiro.hatenablog.com

Go の実装

以下の PR で Go の実装をしました。

github.com

ハマったところ

  • Lambda Handler を実装しないと Runtime.InvalidEntrypoint で落ちます
    • 何を当たり前のことを...w
  • https://hub.docker.com/r/amazon/aws-lambda-go は使えません。
    • このイメージ には実行に必要な Lambda Runtime Interface Entrypoint が入ってませんでした。

f:id:ema_hiro:20210103033351p:plain

結論としては Lambda Runtime Interface が入ったコンテナイメージを用意します。
以下のドキュメントが参考になります。

docs.aws.amazon.com

Go のドキュメントは以下になります。

docs.aws.amazon.com

自分の PullRequest では軽量な alpine ベースでイメージを作成しました。

デプロイ

Lambda を動かすための専用イメージを作成し、ECR にアップロードしたら AWS のコンソールから Lambda を作成するときに、アップロードしたイメージをデプロイするイメージとして選択します。

f:id:ema_hiro:20210103033643p:plain

おまけ

API Gateway との連携

コンテナをベースにしてデプロイした Lambda を API Gateway と連携します。

まず、トリガーに API Gateway を選択する。

f:id:ema_hiro:20210103033756p:plain

すぐ動かしたい時は API タイプを HTTPタイプ に指定します。

f:id:ema_hiro:20210103033759p:plain

デザインとしては以下のようになります。

f:id:ema_hiro:20210103033847p:plain

この状態でテストすると以下のように成功します。

f:id:ema_hiro:20210103033950p:plain

curl でも叩いてみると以下のように成功します。

$ curl -XGET -i https://$ApiGatewayID.amazonaws.com/default/emahiro-lambda-test

HTTP/2 200
date: Sat, 02 Jan 2021 17:26:59 GMT
content-type: application/json
content-length: 7
apigw-requestid: $RequestID
 
Hello !

ローカルでのテスト方法

手元でコンテナイメージを作成する以上、ローカルでテストしたいですよね。
普通にイメージを作成しただけでは、Local で AWS Lambda を動かそうとするとLambda の設定が未設定なので Local で動作確認することはできません。この辺は結局 Image をアップロードして Lambda を作らないと開発できないってあたりが今までと同じでめんどくさいなと思ったところです。

$ docker run -v --name emahiro-lambda-go-sample:latest -d -p 8080:80 emahiro-lambda-go-sample:latest
2021/01/02 17:38:46 expected AWS Lambda environment variables [_LAMBDA_SERVER_PORT AWS_LAMBDA_RUNTIME_API] are not defined

ただ、いちいちデプロイしないとテストできないのは面倒くさいので、ローカルで Lambda をエミュレートする方法がないか調べたところ公式のドキュメントに To test locally without adding RIE to the image という項目があり、この通りにローカルに Runtime Interface Entrypoint の mock を追加したら動作させることができました。

docs.aws.amazon.com

# RIE(Runtime Interface Entrypoint) のエミュレーターを追加します。
$ mkdir -p ~/.aws-lambda-rie && curl -Lo ~/.aws-lambda-rie/aws-lambda-rie \
https://github.com/aws/aws-lambda-runtime-interface-emulator/releases/latest/download/aws-lambda-rie \
&& chmod +x ~/.aws-lambda-rie/aws-lambda-rie
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   164  100   164    0     0    398      0 --:--:-- --:--:-- --:--:--   397
100   640  100   640    0     0    888      0 --:--:-- --:--:-- --:--:--   888
100 7964k  100 7964k    0     0  2365k      0  0:00:03  0:00:03 --:--:-- 3919k
 
# /aws-lambda-rie をエントリーポイントとして Lambda のコンテナイメージを指定してコンテナを起動します。
$ docker run -d -v ~/.aws-lambda-rie:/aws-lambda --entrypoint /aws-lambda/aws-lambda-rie -p 9000:8080 emahiro-lambda-go-sample:latest /main
 
$ curl -XPOST "http://localhost:9000/2015-03-31/functions/function/invocations" -d '{}'
"Hello !"

/2015-03-31 ってなんなんですかね笑

まとめ

イメージ作成とECRのPush周りでつまづきましたが、結構簡単に Lambda をコンテナ上で動作させることができました。

個人的にいいなと思った点は今まで Lambda の動作確認をする場合、開発環境を開発者で共有しながら検証することが必要でした。
普段は Serverless Framework を使うことが多かったので、新しい Handler を yaml に追加したり、別のサービス名でデプロイし直したりしながら、チーム開発において個々人の実装の検証をしていました。
ただ、書いてる通り、結構管理が煩雑になりますし、検証終わった後にゴミ Lambda が残り続けることになるのであまり好きな方法ではありませんでした。

コンテナイメージを使うと、エミュレーターを使って手元で簡単に Lambda の動作を検証できます。
とはいえ、AWS のリソースを使ってる場合は結局デプロイが必要なので、若干片手落ち感ある気がします。。。

AWS さんは AWS のサービスリソースが丸っと入ったエミュレーター作ってくれたりしませんかね笑

今回はざっと動かすところまでやってみたので、実際にサービスで利用するにあたって以下のような観点をもう少し深掘りしてみようと思います。

  • デプロイ自動化。
    • 特にコンテナイメージは毎回 pull ではなく、Lambda の関数を作るときにイメージを指定することしかまだわかってないので、できればデプロイフローで最新のimageを指定してデプロイする、と言ったことをやりたいです。
  • Lambda の設定管理まわり
    • 自己文書化周り -> SAML の記法とか覚えないとですね。
  • Lambda Authorizer を使った安全なリクエストのやり方
    • これは Lambda 側の話かもしれないですが。
  • Serverless framework を使っての実装
    • Lambda on Container でのデプロイが完了したら次にこれをやりたいと思っています。