サーバレス開発ライブラリ Zappa の紹介

こんにちは。1月に入社してから初投稿になります。
システムデザイン部開発ユニットの前原です。

入社してから初めてaws環境を触り始めて、APIやワーカー作成を担当してきました。
今回はawsでのAPI開発に使い始めたZappaというPython用ライブラリの紹介をします。

前提:

  • Lambda + API Gatewayの組み合わせを使用したAPI開発の話となります
  • ZappaはFlask (Python用の軽量Webフレームワーク) との組み合わせで使っていますが、特にFlask自体の解説はしていません

 

今まで試した方法

  1. apex: Lambdaのデプロイを支援してくれるライブラリ
    https://github.com/apex/apex
    – 言語やWebフレームワークは問わない
    – 社内ですでに使われていたこともあり、2-3ヶ月くらいこれを使った
  2. chalice: Lambda + API Gatewayの使用を前提とし、Flaskベースに拡張されたServerless frameworkライブラリ
    – aws謹製
    https://github.com/aws/chalice
    – Python + Flaskに限定される
    – 新しいプロジェクトで一度使用を検討し、数人で1-数日程度試した程度
  3. Zappa: Lambda + API Gateway + Python + (Flask ot Bottle or Django, etc. *) の組み合わせでのServerless frameworkライブラリ
    https://github.com/Miserlou/Zappa
    * よく知りませんが、Pyramidなど他のWebフレームワークにも対応しているようです

 

各ライブラリの比較

apexの良かった点

デプロイ時のフック処理がコマンドで実行できて柔軟だった

apexで不便だった点

– あくまでもLambdaのデプロイ支援ライブラリであるため、API Gatewayの作成や設定、Lambdaと他リソースの連携には関与しなかった

– dev, prodなどのステージ分けしようと思うと、Lambda, API Gateway個別にステージ分けのための設定を作り、手動管理する必要があった

cf. /2016/11/25/apex-tutorial-building-development-friendly-apis-with-aws-lambda-and-api-gateway/

chaliceの良かった点

Lambda + API Gateway + Flaskの組み合わせに限定されるが、Flaskに慣れていれば学習コストが低そうだった

chaliceで不便だった点

– Flaskがラップされているため、デバッグ実行 app.run(debug=True) (ファイル変更を監視してdevサーバーを再起動してくれるしくみ) も使えなくなっており、ググっても良い方法が見つからなかった

* https://github.com/aws/chalice/blob/master/CHANGELOG.rst によると1.3.0から対応した模様 (Add support for automatically reloading the local dev server when files are modified)

– 調べた限りLambda + API Gatewayに完全に特化しているようで、他リソースとの連携は用意されていないらしかった

Zappaの良かった点

– 使い始めるための学習コストが低い

– 数コマンドでデプロイできる

– zappa init

– zappa deploy

– zappa update

– Lambdaに紐づくAPI Gatewayが自動で作成され、Lambda実行権限の付与も自動で行ってくれる
apexを使用していたときはAPI Gatewayの設定が煩雑で面倒だった

– ステージ分けが簡単
zappa_settings.json に別々のステージ設定を書くだけで良い

– あったら便利な細かい機能が充実している

– zappa tail はCloudWatch Logsを開く必要がなくログを監視できるので地味に便利

– from zappa.async import task でインポートする @task デコレータを関数につけると、別プロセスのLambdaを呼び出して非同期実行してくれるしくみが簡便で良い

– “keep_warm”: true (zappa_settings.json内) と書くだけで、Lambdaを4分ごとに定期呼び出しして、コールドスタートを起きにくくしてくれる

– “events” (zappa_settings.json) を使うと、このイベントのときにこの関数を呼び出してほしいという処理が簡単にできる

– DynamoDB Streamsのイベントにより他DBへの同期関数を呼び出す

– 定期実行イベントによりちょっとしたバッチ処理を行う

– ラップされ具合がchaliceよりも少ないため、上記のデバッグ実行などFlaskで用意されたしくみはそのまま使える

Zappaで不便だった点

– ドキュメントがGithubのREADME程度で、あまり充実していない。ググっても情報は多くない

– API Gatewayの上限数と相性が悪い

– ステージを分けるとLambda, API Gatewayともステージごとに作成されるが、API Gatewayのアカウントあたりの上限数が60個であり、組織かつマイクロサービス志向で開発している場合はステージごとに作成されてしまうと上限数に達しやすい

* 現に、マーケットエンタープライズではすでにAPI数が上限に近かったため、別途対策が必要になった

=> API GatewayをZappaの管理から外すことになった

=> Zappaが自動で行っていた設定を手動で再現するのはなかなか大変だった

– いくつかわかりにくい動作がありハマった

– DynamoDB Streamsのeventsで “enabled”: true をつけずにデプロイしてしまうと、zappa update でも更新されず、変更方法が見つからなかったのでDynamoDB StreamsをGUIから設定し直す必要があった

zappa_settings.json

– “events” を zappa_settings.json 内で使用している状態で zappa undeploy を実行するとエラー終了する

– example として載っているソースコードが誤解を生むような気がする
https://github.com/Miserlou/Zappa/blob/master/example/app.py

とあるので関数 lambda_handler は非Zappa環境でのLambdaのように、引数 event, context が渡ってくるものかと思ったら、何も渡ってこなかった
* zappa_settings.json の events で呼び出された場合のみ渡る?

 

最後に、上で述べた内容を使ったサンプルを載せておきます。

app.py

zappa_settings.json