Overview
12 月の re:invent で Lambda のパッケージングフォーマットにコンテナイメージがサポートされたので、少し遅くなりましたが、デプロイまで試してみました。
今回はランタイムに Go を使用してます。
このエントリは以下のドキュメントを参考にしてます。
コンテナイメージを ECR にアップロードする
別エントリで書きましたのでそちらを参考にしてください。
Go の実装
以下の PR で Go の実装をしました。
ハマったところ
- Lambda Handler を実装しないと
Runtime.InvalidEntrypoint
で落ちます- 何を当たり前のことを...w
- https://hub.docker.com/r/amazon/aws-lambda-go は使えません。
- このイメージ には実行に必要な Lambda Runtime Interface Entrypoint が入ってませんでした。
結論としては Lambda Runtime Interface が入ったコンテナイメージを用意します。
以下のドキュメントが参考になります。
Go のドキュメントは以下になります。
自分の PullRequest では軽量な alpine ベースでイメージを作成しました。
デプロイ
Lambda を動かすための専用イメージを作成し、ECR にアップロードしたら AWS のコンソールから Lambda を作成するときに、アップロードしたイメージをデプロイするイメージとして選択します。
おまけ
API Gateway との連携
コンテナをベースにしてデプロイした Lambda を API Gateway と連携します。
すぐ動かしたい時は API タイプを HTTPタイプ
に指定します。
デザインとしては以下のようになります。
この状態でテストすると以下のように成功します。
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 を追加したら動作させることができました。
# 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 でのデプロイが完了したら次にこれをやりたいと思っています。