Chapter 02

[PG] 12 Factor

at yasu
at yasu
2022.01.16に更新

一度は読むべし的な文章: The twelve-factor app

そして Beyond The Twelve-factor App (日本語はこちら 「The Twelve-Factor App」を15項目に見直した「Beyond the Twelve-Factor App」を読んだ -- kakakakakku.hatenablog.com)を読むのもお勧めします。

数多くのアプリケーションの開発・運用・スケールに立ち会った人がまとめた文章です。それは、アプリケーション開発における理想的な手法・プラクティスを見出すための事が記述されています。

以下、抜粋した文章です。

1. コードベース:バージョン管理されている一つのコードベースと複数のデプロイ。

アプリケーションのコードは、常に1対1の関係である。同じコードを共有する複数のアプリケーションは、ライブラリに分解し、そのライブラリを依存関係管理ツールで組み込むようにする。

ただし、デプロイは複数存在する。production/staging/development。

see : I. コードベース -- 12factor.net

2. 依存関係:ライブラリ等の依存関係を明示的に宣言し分離する。

ほとんどのプログラミング言語はライブラリを配布するためのパッケージ管理システムがある。それを使うべし。

see : II. 依存関係 -- 12factor.net

3. 設定:設定を環境変数に格納する。

アプリケーションの設定はデプロイ間(Production/Staging/Develop,...) で異なる唯一のものです。DB/memcachedなどのバックエンドサービスのリソース設定や、S3/Twitterなどの外部サービスの認証、デプロイされたホスト名など。

これらの設定は環境変数に格納する。環境変数は言語やOSに依存しないためである。

see : III. 設定 -- 12factor.net

4. バックエンドサービス

バックエンドサービスとはアプリケーションが通常の動作の中でネットワーク越しに利用する全てのサービスを言う。

コード上、ローカルサービスとサードパーティーサービスを区別しない。それは、例えばメールを送る Postfix と、SMTPサービスのPostmark といった関係である。これらの関係は、コードの変更をしなくても、設定を変更すれば切り替えができるようにするべきである。

see : IV. バックエンドサービス -- 12factor.net

5. ビルド/リリース/実行:3つのステージを厳密に分離する

ビルドステージ・リリースステージ・実行ステージ(ランタイムとも呼ばれる)の3種類がある。これらを厳密に分離する。

see : V. ビルド、リリース、実行 -- 12factor.net

6. プロセス:アプリケーションを一つ・複数のステートレスなプロセスとして実行する

永続化が必要なデータは、全てバックエンドサービスに送らなければならない。典型的にはデータベースのことである。

see : V. ビルド、リリース、実行 -- 12factor.net

7. ポートバインディング:ポートバインディングを通じてサービスを公開

例えば Tomcat を実行した時は http://localhost:5000/ で公開される。webアプリケーションは、そのポートにバインドするHTTPDサービスとして公開をする。(ポートにバインドとは、ここでは80/443にアクセスに来た通信を、Tomcatの5000に転送する事である。)

このようにすることで、あるアプリケーションが、他のアプリケーションのバックエンドサービスになりえる利点がある。

see : VII. ポートバインディング -- 12factor.net

8. 並行性

Unixのプロセス管理をするのではなく、管理された状態でアプリケーションのコードを書く事によって、スケールアウトがしやすくなる。

例えば systemd や supervisord などでプロセスを起動して動かす場合にしても、pid管理はそれらが持つものであり、アプリケーションは自身の役割に徹するべきである。

というにんしきをした。

see : VIII. 並行性 -- 12factor.net

9. 破棄容易性:高速な起動とグレイスフルシャットダウンで堅牢性を最大化する

破棄容易とは、即座に起動・終了することができる事である。堅牢性とは、予期しないエラーや障害などでデータ破損を守る(壊れにくい)事をさす認識である。

起動時間を最短にすることで、リリース作業やスケールアップがやりやすくなる。グレイスフルシャットダウンをすることにより、処理中のリクエストが終了するまで待ち、安全にシャットダウンをすることができる。

see : IX. 廃棄容易性 -- 12factor.net

10. 開発・本番一致:開発・ステージング・本番環境をできるだけ一致させた状態を保つ

継続的デプロイをしやすいように、本番・ステージング・開発環境のそれぞれのギャップを小さく保たせる。

例えば Rails だと ActiveRecord により、MySQL/Postgresqlのギャップを埋めてくれる。しかしこれをしてしまうと、開発環境で Postgresql を動かし、本番では MySQL となったときに、開発環境では動くが本番では動かないというエラーを発生させる要因になる。

Homebrew/apt-get などのパッケージングシステムの使用をする方法がある。他にも、Chef/Puppet などの宣言的プロビジョニングと Vagrant の使用を組み合わせることで、開発者は本番環境に限りなく近いローカル環境を作成する方法がある。

see : X. 開発/本番一致 -- 12factor.net

11. ログ:イベントストリームとして扱う

アプリケーションの実行ログをファイルに書き出すのは、出力フォーマットの一つにすぎない。ログは、すべての実行中のプロセスとバックエンドサービスの出力ストリームから収集されたイベントが、集約されて時刻順に並ばれたストリームである。

アプリケーションは出力ストリームの送り先やストレージについて一切関知しない。

see : XI. ログ -- 12factor.net

12. 管理プロセス:

アプリケーションのために、一回のみ管理・メンテナンス用タスクを実行するときがある。例えば、DBのメンテナンスで使うDB:migrate 等。

一回のみの管理プロセスは、アプリケーションが通常の長時間実行させるプロセスと全く同じ環境で実行するべきです。これらは、リリースに対して実行され、そのリリースに対して実行させる全てのプロセスと同じ設定を使う。そして管理用のコードは、同期の問題を避ける目的で、アプリケーションのコードと一緒にデプロイさせるべきです。

see : XII. 管理プロセス -- 12factor.net