Serverless Framework のコンセプトについて

前回記事

Serverless Framework を利用するにあたり、コンセプトの理解が不可欠であると感じたのでまとめます。

基本的には以下のドキュメントを読んで要約し、思うところを徒然に書いていきます。

www.serverless.com

コンセプト

以下、公式ドキュメントでは "プロパティ" と書かれている部分を yaml ファイルの "フィールド" という意味で言い換えている場合があります。特に意図があるわけではないので適宜読み替えてください。

考え方

  • Serverless Framework は AWS Lambda 関数と Lambda 周りのインフラリソース開発のために利用できる
  • 構造化、自動化やベストプラクティスを提供するCLI(serverless のこと)を利用し、Functions と Events で構成される洗練されたサーバレスアーキテクチャの構築に集中できる

ここでは Lambda と書かれていますが、他のクラウドでも利用可能です。

www.serverless.com

特徴

  • コードとインフラの両方を管理する
  • 複数の言語をサポートする(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 が利用できるのですね。どうなんでしょう、売り文句程度に捉えていいんですかね?他フレームワークとの使い分けや共存はここら辺が参考になりそうです(※まだ読んでないですが)。

dev.classmethod.jp

qiita.com

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 を使用する場合、以下のように設定をオブジェクトとしてエクスポートする必要がある
serverless.js
'use strict';

module.exports = {
  service: 'users',
  functions: {
    usersCreate: {
      events: [
        {
          httpApi: 'POST /users/create',
        },
      ],
    },
    // ...
  },
  resources: {},
};
serverless.ts
// 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 プロパティがあり、複数のプラグインを適用できる
serverless.yml
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 のトップレベルプロパティについて見ていこうと思います。