12 Factor App
IaCのデプロイパイプラインを考えるにあたり、12 Factor Appに基づいたデプロイにするために、12 Factor Appについて調べたことを自分なりに解釈、まとめたものを備忘録として書きます。
12 Factor Appとは
現代では、ソフトウェアは一般にサービスとして提供され、Webアプリケーション や Software as a Service と呼ばれる。Twelve-Factor Appは、次のようなSoftware as a Serviceを作り上げるための方法論である。
- セットアップ自動化のために 宣言的な フォーマットを使い、プロジェクトに新しく加わった開発者が要する時間とコストを最小化する。
- 下層のOSへの依存関係を明確化し、実行環境間での移植性を最大化する。
- モダンな クラウドプラットフォーム上へのデプロイに適しており、サーバー管理やシステム管理を不要なものにする。
- 開発環境と本番環境の差異を最小限にし、アジリティを最大化する。継続的デプロイを可能にする。
- ツール、アーキテクチャ、開発プラクティスを大幅に変更することなくスケールアップできる。
1.コードベース
バージョン管理されている1つのコードベース(GitHubレポジトリ)とアプリケーションは常に1対1の関係であるとする。
- 複数のコードベースがある場合、それはアプリケーションではなく分散システムである
- 同じコードを共有する複数のアプリケーションがある場合は、共通コードをライブラリに分解し、そのライブラリを依存関係管理ツールで組み込む
2.依存関係
依存関係を明示的に宣言し分離する
- システム全体にインストールされるパッケージが暗黙的に存在することに決して依存しない。依存関係宣言マニフェストで完全かつ厳密に宣言すること。
- 実行時には依存関係分離ツール(Golangでいう go modulesのようなもので、依存関係のリストアップや、インストール、アップデートをサポートするツール)を使って、取り囲んでいるシステムから暗黙の依存関係が漏れ出ないことを保証する。
3.設定
設定を環境変数に格納すること。コードから厳密に分離すること。
- データベース、バックエンドサービスなどのリソースへの認証情報
- 外部サービスの認証情報
- デプロイごとの値
認証情報を漏洩させることなく、コードベースを今すぐにでもオープンソースにすることができるなら、本項目は達成できていると言える。
4.バックエンドサービス
バックエンドサービスをアタッチされたリソースとして扱う
- データストアやメッセージキューイングシステム、キャッシュシステム、サードパーティによって提供、管理されるサービスなど
- ローカルサービスとサードパーティサービスは区別しない
5.ビルド、リリース、実行
ビルドステージと実行ステージは厳密に分離する
いつでもインスタンス化できる3つのステージに分離する
- ビルドステージ
コードレポジトリを実行可能な"塊"(ビルド)へ変える。依存関係を取得して、DockerHubやMavenなどのレジストリにアーティファクトとして保存する。 - リリースステージ
コードをビルドしたあとに現在のデプロイ環境の設定と結合するステージ。実行環境の中ですぐにでも実行可能な状態にする。 - 実行ステージ
Ansible, TerraformのようなIaCツールを用いてコードよりプロビジョニングするステージ。
それぞれのステージのパイプラインは、いつでも削除したり、再構築したりできるような状態でなければならない。
6.プロセス
アプリケーションを1つ、もしくは複数のステートレスなプロセスとして実行する
永続化する必要のあるすべてのデータは、ステートフルなバックエンドサービス(データベース)に格納しなければいけない。
7.ポートバインディング
ポートバインディングを通してサービスを公開する
12Factorアプリケーションは完全に自己完結しており、実行環境にポートバインディングすることで、あるアプリケーションが他のアプリケーションにとってのバックエンドサービスになれる。
8.並行性
プロセスモデルによってスケールアウトする
- プロセスは第一級市民(生成、代入、演算などの基本的な操作を制限なしに使用できる)である。
- 個々のワークロードの種類をプロセスタイプに割り当てることで、アプリケーションが多様なワークロードを扱えるように設計することができる。(HTTPリクエストはWebプロセスによって処理し、時間のかかるバックグラウンドタスクはワーカープロセスによって処理する)
- 個々のプロセスがプロセス内部で多重化することを禁止しているわけでは無いが、個々の VMはそれほど垂直にスケールできないため、複数の物理マシンで動作する複数のプロセスへと拡大できる必要がある。
- スケールアウトが必要になった時にこのプロセスモデルは真価を発揮する。
9.廃棄容易性
高速な起動とグレースフルシャットダウンで堅牢性を最大化する
- 12 Factor Appのプロセスは即座に起動、終了することができる。つまり、素早い柔軟なスケールと、コードや設定の変更の素早いデプロイを容易にし、本番デプロイの堅牢性を高める。
- 予期しない、グレースフルではない停止に対しても、うまく処理できるように設計されるべきである。
グレースフルシャットダウン:安全に(リクエストを完全に処理してから)シャットダウンすること。
10.開発/本番一致
開発、ステージング、本番環境をできるだけ一致させた状態を保つ
- CD(継続的デプロイ)しやすいように、開発、ステージング、本番環境をできるだけ一致させた状態を保つ。
- ギャップには3つの領域がある。
- 時間のギャップ:開発者が編集したコードが本番に反映されるまでに数日〜数ヶ月かかる。
→数時間後、もしくは数分後にはデプロイされる。 - 人材のギャップ:開発者が書いたコードを、インフラエンジニアがデプロイする。
→コードを書いた開発者がデプロイに深く関わり、本番環境での挙動をモニタリングする。 - ツールのギャップ:本番と開発環境で用いるツールが異なる。
→できるだけ一致させた状態を保つ。
- 時間のギャップ:開発者が編集したコードが本番に反映されるまでに数日〜数ヶ月かかる。
これらができていないと、継続的デプロイを妨げる摩擦が生まれる。
11.ログ
ログをイベントストリームとして扱う
- ログは、すべての実行中のプロセスとバックエンドサービスの出力ストリームから収集されたイベントが、集約されて時刻順に並べられたストリームである。
- 12 Factor Appでは、アプリケーションの出力ストリームの送り先やストレージについて一切関知しない。イベントストリーム(標準出力)にバッファリングせずに書き出し、ツールで1箇所に集約する。
12. 管理プロセス
管理タスクを1回限りのプロセスとして実行する。
- 管理タスクは、1回限りの管理プロセス(メンテナンス用のタスクなど)として実行する。
- また、同期の問題を避けるために管理コードもアプリケーションコードと一緒にデプロイされるべきである。
参考サイト:
Discussion