Serverless Frameworkを使ってみた

プライベートで簡単なWebサービスを作る必要があったので、インフラ費用を抑えるためにサーバーレス構成で開発してみました。

普段の仕事ではアプリケーションサーバー + RDBMS 構成で開発しています。サーバーレス構成での開発に以前から興味はあったのですが、どういう形で開発するのか知識がほぼなかったため、まず技術選定からはじめました。

普段からAWSを使っているので、AWSを利用することは決めていました。
あとはインフラ費用を安く抑えたかったので、費用が高くなる非マネージドサービスはできるだけ使いたくなかった。なのでデータ保存にはRDBMSは使わずにDynamoDBを使うことに決定。
KVSは使ったことないんですが、まあMapみたいに扱えるデータストアやろうし使えるやろ、くらいの認識でした。

次にHTTPリクエストを処理する部分にはAPI Gatewayとlambdaを使うことになるだろうなと思ってました。
ここの作り方をどうするのがいいのか調べたところ、Management Consoleで手動で設定する方法か、Serverless Framework を使ってデプロイするのかの2つの手法が見つかりました。
Serverless Frameworkはまあまあ昔からあるサービスで、だいぶ前に試しに使ってみたことがあります。
競合サービスが増えてるのかなと思ったんですが、今でもそんなに増えてないっぽいですね。

Serverless Frameworkは API Gatewayのルーティング設定とHTTPリクエストを処理するlambda functionのデプロイをラップするのがメインの機能です。
Cloud FormationというAWSのサービスを使ってデプロイしているようです。

手動でAPI Gateway と lambda を設定する手順をちらっと見たところ、面倒そうなのであまりやりたくないなと思いました。
Serverless Framework なら YAMLファイルに設定を記述できるのでその点はGood。リスクとしては機能のラップが不完全だと、学習コストが増えてしまう可能性があること。その点を考慮してドキュメントを眺めましたが、S3へのアセット配置するpluginがあること、DynamoDBアクセスのサンプルも用意されていて今回の要件は満たせそうだと感じました。

結局、手動で Management Consoleからルーティング設定するのは避けたいというところを重視して、今回は Serverless Frameworkを利用することにしました。

lambda functionの言語には、今はいろいろな言語を使えるようですが、一番問題を起こしにくいだろうという理由で JavaScript で書くことにしました。

公式のドキュメントを読みながらコーディングを進めたところ、難しくない処理だったこともあり、そんなに詰まらずに完成させることができました。

参考にした資料:

構成図
構成図

感想

以下、Serverless Framework、サーバーレス構成で開発してみた感想です。

  • ルーティング定義をserverless.yml で設定できるのは助かる。手動でやると大変そう。なので Serverless Framework を使ったほうが良いと思いました。
  • Serverless Framework が提供する主な機能はルーティング設定と AWSへのデプロイの部分の薄いラッパー。クラス構造を提供したりはしないので、クラス設計は自前でする必要がある。
  • Serverless Framework 用の IAM ユーザー権限設定で手こずった。
    AWS Credentials に、IAM UserにAdministratorAccess権限を付与しろって書いてあって嫌だなーと思いながら作業してたら、直後にIAMユーザーの権限を制限したかったら このgist にある権限を与えるのでもいけるで、と書かれてて最初からそれを書かんかい!となった。
    それで権限を与え直してみたら、gistに書かれた権限ではいくつか足りなくて deployに失敗。失敗するたびにその権限を足して実行して成功するまで繰り返した。
  • HTML, 画像などのアセットファイルはS3に置きましたが、これには Serverless S3 Sync プラグインを使いました。
  • serverless.yml でDynamoDBのスキーマ定義ができるのは便利。
  • DynamoDBはキー情報のみスキーマ定義してフィールドには自由に値をセットできます。保存、ロード処理はKVS初心者でも迷うことなく実装できましたので、使い方は簡単です。ただ、自由に値をセットできてしまうので、必要な情報が登録されていることを保証するためにRDBMSの制約のようなものは使えません。今回よりも規模の大きな開発をする際は、正しい情報が保存されることを保証するデータストア層を実装する必要があると感じました。
  • S3を静的ホスティングで公開して、S3に置かれたHTMLから API Gatewayにajaxでアクセスするという構成にしました。
    S3のドメインとAPI Gatewayのドメインが違うために cors 設定を serverless.yml に設定する必要があり面倒だなと思いました。が、開発後にAPI Gateway をS3のプロキシとして使う方法があることを知りました。これを使えば cors設定が不要になるので、次に開発するときはこの機能を使おうと思います。
  • 今回の開発ではプログラムを修正するととりあえず serverless deploy して動作確認する、という流れで開発をしたのですが、デプロイ後にプログラムエラーに気づいて修正 -> 再デプロイ という作業が何度も発生してしまい、効率が悪いと感じました。1回のデプロイに30秒ほどかかるのですが、何度も行うと待ち時間が多くなります。特にsyntax errorがあってもデプロイできてしまい、ログでsyntax errorに気づくことがあり、これは辛かったです。やはりローカルでテストできる仕組みは作っておかないといけないなと思いました。
  • 今回の開発では lambda function は1ファイルにすべて記述しましたが、より大規模な開発ではlambda functionのリクエストハンドラー処理とは別にビジネスロジック層は別ファイルに定義して、単体でテストできるようにしておくべきだと感じました。
    このあたりの仕組は Serverless Frameworkは何も機能を提供しないので、自前で構成を実装しないといけない。バックエンドサーバー+RDBMSでの開発と同様にプレゼンテーション層、アプリケーション層、データストア層、ビジネスロジック層に分けるのが良いかと考えてます。ここを整えればサーバーレス構成でも開発しやすさがだいぶ改善できる気がする。
  • 言語もJavaScriptではなく、型が使える言語にして、型でデータ構造をガードする仕組みは欲しい。TypeScript か Kotlinがいいかな。ややこしい制限がなければKotlinを使いたいですね。
  • このサービスはだいたい1万人程度が使う予定で、一人10回程度アクセスするとして、lambda と DynamoDB の利用料がおそらく2〜3USDに収まる見積もりです。サーバーを立てるのに比べるとかなりお安く済みますね。

まとめ

  • サーバーレス構成での開発は、サーバーを立てての開発に比べてインフラ費用を抑えられるので、使えるケースでは利用を検討する価値があると感じます。
  • サーバーレス構成で大規模なモノリスサービスを開発するのは負担が大きそうなので、個々のサービスの規模を小さく分割して、サービスを連携させる必要がありそうだと感じます。このように設計方針を変更しないといけない点が、サーバーレス構成の開発を採用する上でのネックになりそうです。ただ、マイクロサービスの設計スキルを上げればこの問題は解消できると思われますので、投資する価値のある学習コストと言えそうです。

マイクロサービスの設計スキルを上げるには実際にそういう構成のシステムを設計するのが良いと思いますので、機会があれば採用を検討したいですね。

関連記事

最近の記事 おすすめ記事
  1. 新人さん向けの品質についての読書会

  1. リモートワークで最適なデスク環境できました。

  2. 10年後の仕事について考える

  3. 今週のコーディング素振り (2018/3/14)

カテゴリー

アーカイブ

検索


TOP
TOP