Serverless Frameworkを使ってみる
先日、社内システムの一部を再検討するときに、API Gateway + LambdaでServerlessマイクロサービスを選択肢に入れておこうという話をしました。で、言い出しっぺでほっとくのもあれなので、ちょっと自前で検証しておこうというのがこのエントリです。Lambda触ってみたかったですし。
本当だったら開発フローや近隣プロジェクトの開発者へのドキュメントやライブラリ公開まで含めた継続的デプロイまで整備してからリファレンスアーキテクチャ的な形のものを発信したかったんですけど、思ったより検証範囲が大きくなりすぎるので、Serverless frameworkを使ってデプロイしてみたところでエントリ的には一旦区切ります。もう何番煎じかわからないので、細かい設定などは書かずに、やりたいことと参考のリファレンスを整理していこうと思います。
その後の経過については別エントリであげる予定。
先に現状のリポジトリをご査収ください。
Serverless framework is 何?
Serverlessアーキテクチャを作るためのフレームワークとツール類をまとめたものです。AWSだけを対象にしたものではなく、Azureなどの各種クラウド環境に対応しています。LambdaのキックイベントはAPI Gatewayに限らず、S3の更新やCloudWatchあたりを設定することができます。今回私はPythonを使ってプロジェクトを作成しました。AWS関連のエントリではいつも大変お世話になってるクラメソさんのブログを読めば一通り使うことができます。
デプロイ時の定義は serverless.yml
という設定ファイルに記述され、記述に基づいたアプリケーションの構成をCloudFormationで作って後はよしなにしてくれます。Elastic Beanstalkと同じく、後からCloudFormationとかの構成の設定をみて勉強するという使い方もありかもしれません。
ちなみに、デフォルトだとイベント設定されていないので、そのままデプロイしてもAPI GatewayにAPIは作成されません。また、デフォルトのリージョンはus-east-1です。東京リージョンにデプロイするときは serverless.yml
にリージョンをちゃんと指定しておきましょう。
ちなみに、細かい話ですがデプロイしたLambdaファンクションの反映にはコンソールで10〜20秒くらいラグがありました。そんなもんなんですかね?テンプレートで出力されたプロジェクトをテスト的にデプロイしてキックするだけならLambdaの無料枠を超えることもないでしょうから、CloudFormation設定を確保するS3の利用料くらいですみます。
ドキュメント
充実しているのでここから探しましょう。
まずはGuideから読んでいけばいいと思います。最初に動かすまでは、Resource,Variables,Packaging,IAMあたりは必要に応じて読むくらいの心持ちで、大丈夫かと。
ただし、Workflowは読んで置くべきです。
開発時の変更ケースに沿ったデプロイの流れやstageやサービスレベルでのアカウント管理についての注意事項、Serverless Architectureの設計上の勘所あたりが書いてあってとても有用です。
Pythonに関する自分用リンク
まだなんとなくな理解の部分
- stageって何?
- CloudFormationちゃんと使ったことない
- version のピン打ちができるけど、CIとかかけるんだったらやっといた方がいいかも
- Lambdaに置けるエラー処理は結局どうやるのが良さげなのか 関数エラー (Python) - AWS Lambda
- Lambdaファンクションの粒度 Step Functions使ったService層的なものの導入は必要になりそう
シンプルなレスポンスを返すマイクロサービスを作る
で、ここからが本題。実際に開発の場に持ち込むためには以下が足りないんですよ。
- ローカル実行時のDynamoDBの取り扱い
- テスト
どちらもない状態でチーム開発するのはしんどいですよね。というわけでこの辺りを整備してみます。
ローカル実行用にDynamoDBを使いたい
AWS上に作られているDynamoDBのテーブルにアクセスするのは簡単です。公式にもサンプルがあって、その通りに書けばとりあえずはデータのCRUDは試すことができます。
スキーマレスだからserverless.ymlにIDしか定義してなくてデータ突っ込んでるの強引だなあ、とか諸々思うところはあるのですが、それは今議論するところではないのでそっとしておきます。
で、CloudFormationがよしなにテーブル作ってくれたりするのはいいのですが、そのままでは一度でもデプロイしてしまうとローカル実行でもこのDynamoDBテーブルを使うようです。チームで使ったりする場合はちょっと不便。開発者の個別の実行は、AWSが用意しているDynamoDB ローカルを使ってあげるようにしたいですね。
で、見つけたのがこのプラグインです。
で、私のソースは以下のQiita記事を参考に書いているので、 event[isOffline]
を参照してデータソースを切り分けているのですが、
これは別のserverless-offline使う前提の名残です。なぜか私の環境ではpython3.6がunsupportedと出てるのでちょっと保留中です。ぶっちゃけserverless-offline自体はいらないんじゃないか、とも考え中。
Lambdaファンクションにテストを書きたい
初めはdoctestを使って書こうかと思ってたんですが、Lambdaファンクションのハンドラーになる関数だと、DynamoDBとかリソース使い出すとserverless.ymlのコンテキスト渡しづらくなってしんどいんですね。ファンクションの中で適切に分割されたpythonの関数であれば、doctestで十分にかけると思いますが。
というわけで、ハンドラーレベルのテストはServerless Frameworkのローカル実行機能を前提にbats使ってみることにしました。E2Eテストとユニットテストの2段階というイメージです。
リポジトリにもbotsを使ったテストを書いてます。が、一応、テストが書けたけど、シェルスクリプト力の不足でアサーションが非常に弱い状態。誰かまさかり投げて。。。
一旦のまとめ
というわけで、Serverless Frameworkを使ってチームでマイクロサービスを開発する上での方向性とか基盤の整理みたいなものの試行錯誤をしてみました。その一応の成果が先のリポジトリであります。いくつかいけてないところはありますが、そこはこれから洗練させる余地はあると思いますので、まずはこの辺で開発者視点は区切っておこうというのが今回のエントリの主旨です。
で、次はサービスのマネージャ視点になります。サービスは作って終わりではなく、他のサービスやアプリケーションの開発者に提供しなければならないリソースを整備することが必要になりますね、APIドキュメントとかライブラリとか。これらをデプロイに応じて自動で整備をする、というところをやっていきたいと思います。