Serverless Framework を利用するにあたり、コンセプトの理解が不可欠であると感じたのでまとめます。
基本的には以下のドキュメントを読んで要約し、思うところを徒然に書いていきます。
コンセプト
以下、公式ドキュメントでは "プロパティ" と書かれている部分を yaml ファイルの "フィールド" という意味で言い換えている場合があります。特に意図があるわけではないので適宜読み替えてください。
考え方
- Serverless Framework は AWS Lambda 関数と Lambda 周りのインフラリソース開発のために利用できる
- 構造化、自動化やベストプラクティスを提供するCLI(
serverless
のこと)を利用し、Functions と Events で構成される洗練されたサーバレスアーキテクチャの構築に集中できる
ここでは Lambda と書かれていますが、他のクラウドでも利用可能です。
特徴
- コードとインフラの両方を管理する
- 複数の言語をサポートする(Node.js, Python, Javaなど)
つまり、「Lambda を中心としたサーバレスアーキテクチャ開発のために利用でき、インフラとコードをまとめて管理するためのフレームワークである」ということです。
逆に言うと、Lambda(や他クラウドの FaaS) を伴わない開発の場合、特に Serverless Framework を採用する動機はないということでしょうかね。functions
フィールドを指定しないとエラーになるとかそんなコントロールもあるのかしら。
Functions
- コードは Lambda で実行される
- 各関数はマイクロサービスのように独立した単位で実行・デプロイされる
- 以下のような単一の処理を実行するためのコードをデプロイするために利用することが多い
- ユーザ情報の保存
- データベースのファイルを処理
- スケジュールタスクの実行
「マイクロサービスのような」と書いてありますが、これは単に 「Lambda 関数は独立した単位でデプロイされる」という以上の意味はないですかね?もしくは、Serverless Framework の "サービス" は文字通りサービス毎に構築するのがベストプラクティスということでしょうか。そうした場合、現実問題としてサービスをまたぐDBも普通にあると思うのでどのサービスが主となり管理するかなど設計上の問題も出てきそうですね。
Events
- 関数は以下のイベントによってトリガーされる
- API Gateway URL へのリクエスト
- S3 バケットへのアップロード
- CloudWatch スケジュール
- SNS トピックのメッセージ
- CloudWatch アラート
- etc...
- Lambda にイベントを設定すると Serverless Framework は自動的にそのイベントに必要なリソースを作成し、それをリッスンするように設定する
例えば、Lambda 関数のみを serverless.yml
に定義していたとしても、functions.<function name>.events
フィールドに http アクセスの記載があった場合は API Gateway も作成されるということです。
Resources
- Resource は以下のような AWS コンポーネントである
- DynamoDB テーブル
- S3 バケット
- SNS トピック
- CloudFormation で定義できる全てのリソースは Serverless Framework でサポートされる
- Serverless Framework は Lambda 関数とそのイベントだけでなく、AWS リソースもデプロイできる
おっと、「CloudFormation で定義できるすべてのリソースが管理可能である」との文言が。また、 Lambda 関数とそのイベントだけでなく、AWS リソースもデプロイできる」ともありますね。
基本的には FaaS 利用に特化したほうがいい気がしますが、その他の用途でも Serverless Framework が利用できるのですね。どうなんでしょう、売り文句程度に捉えていいんですかね?他フレームワークとの使い分けや共存はここら辺が参考になりそうです(※まだ読んでないですが)。
Services
- Service とは Framework の管理単位
- 一つのアプリケーションに対して複数のサービスを持つことができるが、Service は一つのプロジェクトファイルとして考えよ
- Service は
serverless.yml
ファイルで構成され、関数・イベント・AWS リソースを以下のように定義する - 設定ファイル内のすべてが一度にデプロイされる
service: users functions: # Your "Functions" usersCreate: events: # The "Events" that trigger this function - httpApi: 'POST /users/create' usersDelete: events: - httpApi: 'DELETE /users/delete' resources: # The "Resources" your "Functions" use. Raw AWS CloudFormation goes in here.
「serverless.yml
と管理単位である Service は1対1(というよりファイルがサービスそのもの)であり、関連する関数やリソースは全て1ファイル内に書く。ファイル内に複数の関数を定義することができる。」ということですかね。
また、resources
フィールドは素の CloudFormation を記述するようです。
設定形式
serverless.yaml
形式ではなく、serverless.json
,serverless.js
,serverless.ts
で記載することもできる- JavaScript, TypeScript を使用する場合、以下のように設定をオブジェクトとしてエクスポートする必要がある
'use strict'; module.exports = { service: 'users', functions: { usersCreate: { events: [ { httpApi: 'POST /users/create', }, ], }, // ... }, resources: {}, };
// Requiring @types/serverless in your project package.json import type { Serverless } from 'serverless/aws'; const serverlessConfiguration: Serverless = { service: 'users', functions: { usersCreate: { events: [ { httpApi: 'POST /users/create', }, ], }, // ... }, resources: {}, }; module.exports = serverlessConfiguration;
動的に serverless.yml
を作成したい場合に便利そうですね。一方でコードの管理(というか保守)が大変そうなので個人的には静的ファイルで管理したいです。コードを Git 管理するときも最終的な差分が目に見えてわかりやすいので、動的に吐くにしても静的ファイルに一旦落としてから serverless deploy
したい。ここら辺は好みですかね?
プラグイン
- プラグインを利用し機能の上書き・拡張が可能
plugins
プロパティがあり、複数のプラグインを適用できる
plugins: - serverless-offline - serverless-secrets
直近で StepFunction を作りたいので、プラグインにはお世話になりそうです。
まとめ
今回見てきた概念の関係をまとめるとこんな感じですかね?
Service:サービス単位、アプリケーションに関連する関数・イベント・リソースをこの中に入れる
- Function:Lambda 関数
- Event:Lambda トリガーのためのイベント(API Gateway や Cloudwatch、SNS など)
- Resource:DynamoDB, S3 などの Lambda で処理するデータリソース。CloudFormation の記法で記述する。
yaml 形式だけでなく json, JavaScript, TypeScript でも記述可能
- 拡張機能利用のためのプラグインが利用可能
コンセプトがあらかたわかったので次回は serverless.yml
のトップレベルプロパティについて見ていこうと思います。