"The Twelve-Factor App"と"Beyond The Twelve-Factor App"の整理 ＆ サーバーレスの場合の情報追加

# はじめに

2011年に出された["The Twelve-Factor App"](https://12factor.net/ja/)と、2016年に出された["Beyond the Twelve-Factor App"](https://content.pivotal.io/ebooks/beyond-the-12-factor-app)を整理し、さらに2018年にAmazonのエンジニアが[サーバレスの場合の考慮点をブログ化したもの](https://aws.amazon.com/jp/blogs/compute/applying-the-twelve-factor-app-methodology-to-serverless-applications/)の情報を追加して、表の形にしました。

# 背景

"The Twelve-Factor App"は有用ですが、2011年に出されたものなので少し古くなっている感があります。 その後、2016年にPivotalの人が"Beyond the Twelve-Factor App"というのを出しています。

"Beyond the Twelve-Factor-Factor App"の方が新しく、追加情報も多いのですが、ユーザー登録を求められるサイトに置いてあるせいか、世間ではあまり語られていないようです。ブログ等で概要を語る人はいますが、ほんのさわり程度です。分量が多いためか（PDFで58ページ）、日本語訳は出されていません。

一方、AWS LambdaやAzure Functionsなどサーバーレスがホットとなってきている中で、"The Twelve-Factor App"のいくつかの項目はサーバーレスでは当てはまらないものも出てきました。 それを受けて、Amazonのエンジニアが上記のブログを書いています。が、残念ながらまだ日本語訳は出ていません。

そこで、"The Twelve-Factor App"と"Beyond the Twelve-Factor App"を比較整理し、上記のブログの記述も付け加えた表を作成してみました。

# 目的

現在の技術動向・技術潮流に沿った形でクラウドアプリケーションを開発する際の、チェックリストとして活用して頂きたい。

| No.　 | ガイドライン<br>(The Twelve-Factor App, Beyond the Twelve-Factor App) | Beyondで追加されたもの | AWSサーバーレスプラットフォーム（AWS Lambda等）の場合 |
|------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 1-1 | ・バージョン管理ツールを使ってソースコードを管理する。 |  | 【該当】 |
|  1-2 | ・アプリケーションごとにコードベース（リポジトリ）を作成する。 |  | 【該当】<br>・イベントを共有するのであれば、それらを処理するLambda関数を1つのアプリケーションとみなし、1つのリポジトリに格納する。<br>・そうでなければ、Lambda関数をイベントソースごとに分割し、それぞれ別のリポジトリに格納する。 |
| 1-3 | ・1つのコードベースから複数の環境（開発環境、ステージング環境、本番環境等）へのデプロイを行う。 |  | 【該当】 |
| 2-1 | ・依存関係を明示的に宣言する。（JavaならMavenまたはGradle、.NETならNuGet、RubyならBundlerを適切に使う） |  | 【該当】<br>・複数のLambda関数に使われるコードは、独立したライブラリとしてパッケージ化し、デプロイパッケージに組み込むようにする。 |
| 2-2 | ・アプリケーションがデプロイされる環境の何か（共有ライブラリ、Classpathなどの環境変数、システムツール等）をあてにしない。アプリケーションが必要とするライブラリ等は、アプリケーションと一緒にデプロイする。 |  | 【該当】 |
| 3-1 | ・ソースコードから、設定情報(configuration)と認証情報(credential)を分離する。（設定情報＝デプロイ環境ごとに異なる値をとりえる任意の情報。[バックエンドサービスのURL、各種のプロパティファイルに記述される情報など]）（認証情報＝IDとパスワード、証明書など認証に使われる情報。[データベースに接続するためのIDとパスワードなど]） |  | 【該当】 |
| 3-2 | ・設定情報は、設定ファイルに格納するのではなく、環境変数に格納する。または、それ用のサーバー製品（Spring Cloud Config等)を使って外部化する。 | Beyond（一部） | 【該当】<br>・AWS Lambdaでは、環境変数に設定情報を格納することができる。<br>・AWS Lambdaの環境変数は、key-valueペア形式である。<br>・API Gatewayでは、ステージ変数に設定情報を格納することができる。（ステージ変数の値を参照し、バックエンドサービスへのリクエストを切り替えたり、Lambda関数に情報を伝達して処理を切り替えたりすることができる） |
| 3-3 | ・認証情報は、プロパティファイルやXMLファイルに格納するのではなく、設定情報と分けた上で、設定情報と同様な形で外部化する。 | Beyond | 【該当】<br>・AWS Lambdaは、環境変数のkey-valueペアを暗号化することができるため、認証情報を格納することができる。 |
| 4-1 | ・バックエンドサービスを、アタッチされたリソースとして扱う。 |  | 【該当】<br>・AWS Lambdaでは、Lambda関数の実行の一部として他のサービスを実行することができないため、「バックエンドサービスを、アタッチされたリソースとして扱う」ということがデフォルトとなる。 |
| 4-2 | ・クラウドではファイルシステムが一時的なものであることを認識する。ファイルシステムをバックエンドサービスとして扱う。 |  | 【該当】 |
| 4-3 | ・ バックエンドサービスをアタッチしたりデタッチしたりすることは、アプリケーションを再デプロイせずに、自由に行えなければならない。 |  | 【該当】 |
| 5-1 | ・設計・ビルド・リリース・実行の4つのステージを厳密に分離する 。 | Beyond（設計を追加） | 【該当】 |
| 5-2 | ・ビルドは理想的には、継続的インテグレーション(CI)サーバーにより作成されるべきである。 | Beyond | 【該当】 |
| 5-3 | ・ビルドは設定情報と結合されて、「イミュータブルリリース」が作成され、複数の環境（開発環境、ステージング環境、本番環境等）にリリースされる。 |  | 【該当】 |
| 5-4 | ・ビルドとリリースとの間の関係は、1対多である。 |  | 【該当】 |
| 5-5 | ・リリースは、タイムスタンプや自動採番された番号のような、ユニークなIDでタグ付けされるべきである。リリースはビルドIDでタグ付けしてはいけない。 |  | 【非該当】 |
| 5-6 | ・アプリケーションをローカル環境で実行でき、CDパイプライン経由で複数のクラウドにデプロイできるようにすべきである。 | Beyond | 【非該当】 |
| 6-1 | ・アプリケーションをステートレスにする。 |  | 【非該当】<br>（AWS Lambdaの設計思想はもともとステートレスであり、Lambda関数はステートレスとして扱われなければならないようになっている） |
| 6-2 | ・永続する状態はすべてアプリケーションの外部に置き、バックエンドサービスから提供されるようにする。 |  | 【該当】 |
| 6-3 | ・複数のプロセス間で、リソースをシェアするようなことはしない（＝シェアード・ナッシング）。（代替手段の一つは、キャッシングサービスを提供するバックエンドサービス(Redis等)を使うことである） | Beyond | 【該当】 |
| 6-4 | ・アプリケーションの起動時に、データをキャッシュするようなことはしない。代わりに、キャッシングサービスを提供するバックエンドサービス(Redis等)を使う。 | Beyond | 【該当】 |
| 7-1 | ・（PaaSを使う場合）ポートバインディングではなく、コンテナとしてサービスを公開する。 |  | 【非該当】<br>（AWS Lambdaの場合、Lambda関数は他のサービスまたはAWS APIs for Lambdaから起動されるため、本項目は該当しない） |
| 8-1 | ・スケールアウトによりプロセスを増やして並列動作させて負荷分散する。 |  | 【非該当】<br>（AWS Lambdaはもともと、大規模な並列性とスケーラビリティを考慮して構築されている） |
| 9-1 | ・アプリケーションの起動と停止を迅速にできるようにしておく。 |  | 【停止の部分のみ非該当】<br>（・AWS Lambdaはイベントドリブンであり、アプリケーションの停止という概念は無い）<br>・Lambda関数の起動を迅速にすべきということは同じである。<br>・Lambda関数の初回起動時や修正時には、余分に時間がかかる。対処法についてはベストプラクティスを参照すること。AWS X-Rayを使うことで、関数の挙動に関する情報を得ることができる。 |
| 10-1 | ・開発環境・ステージング環境・本番環境をすべて一致させる。（データベース、ライブラリ等） |  | 【該当】<br>・開発環境・ステージング環境・本番環境をすべて一致させるということは、非サーバーレスの場合と同様。<br>・AWSサーバレスプラットフォームは、アイドル時間は課金しないので複数環境を維持する場合にコスト削減ができる。<br>・AWS Serverless Application Model (SAM)を使うことで、複数環境の設定を管理することができる。<br>（AWS CloudFormationの記法を使ってテンプレートを作成し、AWS Lambdaの環境変数とAPI Gatewayのステージ変数を使うことで、複数環境を1つのテンプレートから構築できる） |
| 10-2 | ・コードのチェックインとリリースとの間の時間的ギャップをできるだけ短く（数時間程度に）する。 |  | 【該当】 |
| 10-3 | ・CDツールを用い、デプロイはできるだけ自動化する。 |  | 【該当】 |
| 10-4 | ・（デプロイを自動化しない場合）開発者とデプロイ実施者はできるだけ同一にする。 |  | 【該当】 |
| 10-5 | ・「すべてのコミットはデプロイの候補である」という考え方のもとで開発を行う。 |  | 【該当】 |
| 11-1 | ・アプリケーションのログはstdoutまたはstderrに出力する。それ以外の出力先（特定のファイル等）をアプリケーションで指定するようなことはしない。 |  | 【該当】<br>・AWS Lambdaでは、言語の基本機能を使ってコンソールにログを出力する。 |
| 11-2 | ・出力されたログの集約・処理・蓄積は、クラウドプラットフォーム上のサービスか、または別のツールで処理する。 |  | 【該当】<br>・Lambda関数が出力したログは、Amazon CloudWatch Logsにより集約される。<br>・subscription filtersを使うことで、ログ中の特定のパターンが出現した場合に、特定のLambda関数を起動させることもできる。 |
| 12-1 | ・管理プロセスは使わないようにする。<br>（shellを使ってデータベースのマイグレーションを実施したり、手作業で管理コマンドを実行したり、cronにより時刻指定でバッチジョブを実行したりするようなことは行わないようにする） |  | 【非該当】<br>（AWS Lambdaでは、この項目は直接的には該当しない） |
| 12-2 | ・時刻指定でアプリケーションの特定機能を実行したい場合は、<br>　- RESTfulなエンドポイントを開示するか、または、<br>　- 当該機能の部分を抽出して別のマイクロサービスにして、それをクラウドプラットフォームのサービスを使って実行させる。 |  | 【該当】 |
| 13-1 | ・アプリケーションの設計にあたってはまず、他のサービスやクライアントアプリケーションから使われるAPIの設計から始める（＝API First）。 | Beyond | 【該当】<br>（ただし、下記[4]には言及無し） |
| 13-2 | ・"API First"を行う上で、[OpenAPI](https://github.com/OAI/OpenAPI-Specification)などの仕様とツールを活用する。<br>（参考文献：「スキーマ駆動Web API開発」WEB+DB PRESS Vol.108, 2018年12月22日, 技術評論社） | Beyond | 【該当】<br>（ただし、下記[4]には言及無し） |
| 14-1 | ・リモート監視を適切に行う。（クラウド上にアプリケーションをリリースすることは、宇宙にロケットを飛ばすということと同様であるということを認識する） | Beyond | 【該当】<br>（ただし、下記[4]には言及無し） |
| 14-2 | ・アプリケーションの設計段階から、リモート監視の方法を検討しておく。 | Beyond | 【該当】<br>（ただし、下記[4]には言及無し） |
| 15-1 | ・認証と認可について最初から考慮しておく。 | Beyond | 【該当】<br>（ただし、下記[4]には言及無し） |
| 15-2 | ・できるだけ、RBAC（ロールベースのアクセスコントロール）の手法を採用する。（アプリケーションのリソースへのリクエストは、誰がそのリクエストを出しているのか、その人が属するロールは何かをアプリケーションで把握した上で処理する。ロールは、アプリケーションがそのリクエストを実行するのに十分なパーミッションをリクエスト発行者が持っているかを決定するために使う） | Beyond  | 【該当】<br>（ただし、下記[4]には言及無し） |

# 参考URL

[1] [The Twelve-Factor App  （オリジナル）](https://12factor.net),  2011年		
[2] [The Twelve-Factor App （日本語訳）](https://12factor.net/ja/), 2011年		
[3] [Beyond The Twelve-Factor App](https://content.pivotal.io/ebooks/beyond-the-12-factor-app), 2016年		
[4] [Applying the Twelve-Factor App Methodology to Serverless Applications](https://aws.amazon.com/jp/blogs/compute/applying-the-twelve-factor-app-methodology-to-serverless-applications/), 2018年