目次
- 目次
- はじめに
- 1. 一つのリポジトリに一つのアプリケーション
- 2. 依存関係は明示的にファイルとして宣言し、それだけでアプリケーションを動かせるようにする
- 3. ソースコードと設定を分離し、設定環境変数に格納する
- 4. バックエンドサービスは簡単に交換可能にできるように実装する。
- 5. ビルド、リリース、実行の3つのステージを厳密に分離し、順番に実行する。
- 6. アプリケーションを1つもしくは複数のステートレスなプロセスとして実行するようにする。
- 7. それぞれのアプリはWebサーバーを内包し、ポートバインディングで外部にサービスを公開する
- 8. 垂直スケール(CPU, メモリ増強)ではなく、水平スケール(インスタンス数の増加)で過負荷に対応する。
- 9. サービスは即座に起動・終了することができるようにし、簡単に廃棄できるようにしておく。
- 10. 開発環境と本番環境をできるだけ一致させる
- 11. ログは標準出力に出力し、本番環境では実行環境がそれらをまとめて最終出力形態に出力するようにする。
- 12. 管理プロセスはアプリケーションの初期化処理などに組み込み、自動化する
- 参考資料
- MyEnigma Supporters
はじめに
Twelve-Factor Appは、2012年にHerokuのエンジニアが提案した、
モダンなWebアプリケーションのために重要な12の項目をまとめたものです。
www.slideshare.net
こちらの12の項目は、使うプログラミング言語によらず、
現在でも言及されることが多い普遍的なアドバイスが多いため、
かなり自分でも勉強になったので、まとめておきたいと思います。
元の英語のドキュメントの直訳だとかなりわかりにくかったので、
自分なりに意訳しています。
1. 一つのリポジトリに一つのアプリケーション
一つのリポジトリで管理されているコードベースは一つのアプリケーション用にする。
複数のリポジトリで一つのアプリケーションや、
一つのリポジトリで複数のアプリケーションは、
ソフトの依存の増大やプロセスの自動化の難しさから避けたほうが良い。
2. 依存関係は明示的にファイルとして宣言し、それだけでアプリケーションを動かせるようにする
アプリケーションの依存関係(ライブラリの名前やバージョンなど)は、
明示的にファイルで宣言し、それを使ってライブラリをインストールするようにします。
例えば、Pythonではrequirements.txt, RubyだとGemFile, JavaだとMavenのpom.xmlなどです。
加えて、デプロイ先の環境になにかソフトウェアやアプリが存在していることを仮定せずに、
その宣言したライブラリのみで動くことが理想的です。
3. ソースコードと設定を分離し、設定環境変数に格納する
各デプロイ環境の設定は、ソースコードやファイルに保存し利用するのではなく、
環境変数に入れて、アプリは利用するようにする。
環境変数であれば、OSの差も生まれにくいため。
または設定をサーブする外部サービスで管理するのも良い。
4. バックエンドサービスは簡単に交換可能にできるように実装する。
バックエンドサービス(DBや、メッセージブローカー、外部APIサービスなど)への接続は、
交換可能であるように実装し、ハードコードではなく、設定で簡単に変更できるようにする。
これにより、ローカルのサービスから、クラウドのサービスに簡単に切り替えたり、
外部サービスがダウンした時に切り替えやすくなる。
5. ビルド、リリース、実行の3つのステージを厳密に分離し、順番に実行する。
リリース後や、実行中にソフトを変更したり、
環境の差を埋めるリリース作業の前に、各環境毎にビルドしたり、
実行毎に、リリースの時にすべき環境設定をしたり、
はしないようにする。
また、実行ステージはできるだけ可変部分を持たずに、シンプルにする。
これにより、現場で問題が起きても、現場の人が対応しやすくするためである。
一方、ビルドのプロセスなどは、エンジニアの目の前で問題が発生するため、
多少複雑でも問題ない。
6. アプリケーションを1つもしくは複数のステートレスなプロセスとして実行するようにする。
アプリケーションは、1つもしくは複数のステートレスでシェアードナッシングな
プロセスとして実行するようにし、複数にリクエストで引き継ぐような処理はしないようにする。
永続的に必要なデータは、かならずDBや外部サービスに保存し、
それ以外は失われても良いようにする。
また、アプリケーションは特権ユーザ(su)ではなく、
アプリケーションそれぞれに分けられた通常ユーザで実行すると良い。
7. それぞれのアプリはWebサーバーを内包し、ポートバインディングで外部にサービスを公開する
これにより、サーバーを毎でなく、各ポート毎にサービスを公開することができます。
加えて、自分のサービスそのものが、他のサービスのバックエンドにもなりやすくなります。
8. 垂直スケール(CPU, メモリ増強)ではなく、水平スケール(インスタンス数の増加)で過負荷に対応する。
垂直スケールは、サーバーやサービスの再起動が必要だが、
水平スケールはインスタンスを増やすだけなので、簡単に過負荷に対応できる。
そのようなスケール方法を検討したほうが良い。
また、このサービスはデーモン化はすべきではなく、
systemdなどのOSのサービスマネージャに管理させるべき。
9. サービスは即座に起動・終了することができるようにし、簡単に廃棄できるようにしておく。
起動を早くすることにより、過負荷時のインスタンス数増加を即座に実行できる。
できれば数秒で起動できると良い。
終了はSIGTERMを受け取った時に、グレースフル(処理中の内容を処理してから)に終了したほうが良い。
10. 開発環境と本番環境をできるだけ一致させる
本番環境だけ発生する問題をできるだけ早く見つけるため。
外部サービスも本番環境と同じものを使えると良い。
11. ログは標準出力に出力し、本番環境では実行環境がそれらをまとめて最終出力形態に出力するようにする。
ログはアプリケーションが直接ファイルなどに出力するようにするのではなく、
実行環境(プロセス管理ツール)がまとめて複数のログを最終出力するようにする。
アプリケーションの中でログのローテーションなどは行うべきではない。
12. 管理プロセスはアプリケーションの初期化処理などに組み込み、自動化する
管理プロセス(DBのマイグレーションや、バッチ処理など)を手動で実行しているとミスが発生します。
参考資料
MyEnigma Supporters
もしこの記事が参考になり、
ブログをサポートしたいと思われた方は、
こちらからよろしくお願いします。