ざっくり Beyond the 12 Factor App

# はじめに
PivotalのアーキテクトであるKevin Hoffmanさんがクラウドネイティブアプリ向けに [Tweleve-Factor](https://12factor.net/) をアップデートしました。
[Beyond the 12 Factor App](https://content.pivotal.io/ebooks/beyond-the-12-factor-app)
この記事ではBeyond the 12 Factor Appについて**なんとなく分かった気になる**までを目指します。



# ざっくり Beyond the 12 Factor App

## Factor 1. One Codebase, One Application
### 1つのコードに1つのアプリケーション ###
1. アプリケーションごとにバージョン管理されている1つのコードベースがあるか
1. 1つのコードベースから複数の環境(dev/stg/prd)に対してのデプロイが可能か  
`例) 環境毎に異なる値は環境変数から読み込むようにコーディングする`
1. 単一のコードベースに複数のチームが存在する場合、Conwayの法則を利用して、マイクロサービス化してコードベースの分割を検討しても良い

## Factor 2. API First
### APIから設計を開始する
1. 最初にAPIを設計することで、Web側、モバイル側、またAPIを利用したい他のチームとの調整も容易になる
1. APIファースト開発をサポートする為のツールを使用する  
`例) Swagger, Apiary`
1. CIにより結合点を継続的にテストすることで、チームそれぞれが独自のサービスに注力できる

## Factor 3. Dependency Management
### 依存関係管理
1. 依存関係が明示的に宣言・分離されているか  
` 例) マニフェストファイルに依存するライブラリを記述し、記述外のライブラリを利用して動作することの無いように起動する`
1. Developerが依存関係を宣言し、それらの依存関係が満たされていることをツールで確認すること  
`例) Maven, Gradle, NuGet, Bundler, godeps etc`
1. リリース成果物にサーバーまたはコンテナーを埋め込む形が理想

## Factor 4. Design, Build, Release, Run
### 設計、ビルド、リリース、実行
1. Design, Build, Release, Run それぞれ個別のフェーズで実施する
1. 自動テストとデプロイを行い、高い信頼性を保ちながらCIスピードを最大化する

* Design
 * 依存関係を宣言する。それぞれのライブラリがリリース時にどのようにバンドルされるかを決定する
* Build
 * コードが実行可能アーティファクトに変換される
 * 設計時に宣言された依存関係が含まれ、成果物にまとめられる
 * ビルドはCIサーバによって作成されるのが理想的
 * 1つのビルドを任意の数の環境にリリースまたは展開できるようにする
 * 1つのビルド、多数のデプロイ
* Release
  * ビルド段階の成果物と環境毎の設定と組み合わせ、実行できる形にする
  * 一意のリリースIDをもたせること  
  ` 参考) https://semver.org/lang/ja/`
  * 問題が発生した場合にそなえ、以前のリリースにロールバックできること
* Run
  * アプリケーションがコンテナに配置されてから、起動するためのプロセスを開始する
  * アプリケーションが実行されると、マネージドサービスは、実行を監視し、ログを集約し、スケールアウト／インに対応する


## Factor 5. Configuration, Credentials, and Code
### 設定を環境変数に格納する
1. 環境毎に異なる設定は環境変数に格納しているか
  * デプロイ時に異なる値をコードから分離する
        ・URLなどバッキングサービス、Webサービス、SMTPサーバ
        ・DB接続先
        ・AWSなどのサードパーティサービスへの認証情報

        正しく設定を分離できているかの確認は、 すぐにコードをGitHubに公開できるか否か
        `注) アプリケーション内部の設定についてはコードに書いてもOK`

        もしくは設定を公開するように設計されたサーバを使用する。
        `例) Spring Cloud Configuration Server`

1. 環境毎に設定群を定義していないか
  * クラウドネイティブの場合、環境毎の設定を、  
    プロパティファイル、YAML、XMLなどに定義することをアンチパターンとしています  
    `例) dev用, stg用, prd用などで用意するとスケールしづらいためNG`

1. 設定の外部化はCDパイプラインを介して各環境別にアプリケーションをデプロイする機能をサポートする

## Factor 6. Logs
### ログはイベントストリームとして扱う
1. ログを標準出力(stdout)として扱っているか
  * ログファイルに書き込んだりしていないか。ログは外部のログ解析サービスなどに送信する
  * クラウドネイティブなアプリケーションはログのルーティングや保存に関与しない
1. ログの集約、処理、保存はアプリではなく、クラウド上のサービスを使用する
  * ELKスタック（ElasticSearch、Logstash、およびKibana）、Splunk、Sumologic、またはその他の様々なツールを使用して、分析することができる
1. スケーラビリティメリットが得られる
  * 動的にアプリケーションが増えても、ログを処理するドライバがあれば処理できる

## Factor 7. Disposability
### 破棄容易性
1. 迅速に起動し、迅速に停止できるように作成する
  * クラウドインスタンスではアプリケーションの寿命は短期間

## Factor 8. Backing Services
### バックエンドサービス
1. コード内でローカルのサービスとサードパーティのサービスを区別していないか  
    ` 例) コードを変更することなく、ローカルのMySQLDBからAWS RDSなどに切り替えられること`

1. ファイルストレージもバッキングサービスとして扱う。
  * エンタープライズアプリのようにディスク上のファイルにI/Oしない

1. アプリケーションとバッキングサービスとの結合は外部設定によって行われる
  * アプリケーションを再デプロイせずに、バックサービスを切り替えることが可能であるべき

1. サーキットブレーカー：バッキングサービスが落ちている場合、通信を停止しフォールバックorフォールセーフパスを提供できる

1. バッキングサービスと疎結合にすることで柔軟な回復性をもたせることができる


## Factor 9. Environment Parity
### 環境一致
1. Time
 * コードcommit後、デプロイされるまでの時間を短くすること  
    多くの組織では開発者がコードをチェックインしてからリリースまで数週間から数ヶ月かかることがある
    時間的なギャップが生じると、人は変更の内容を忘れてしまう。
    CDサイクルを回し、時間ギャップを小さくすることで、品質を上げる

1. People
 * 人がデプロイプロセスに関与してはいけない  
    適切なビルドパイプラインが存在すれば、アプリケーションは全ての環境に自動的にデプロイされる

1. Resources
 * バッキングサービスなどローカルと本番での差異を増やすと、いいことはない。  
    クラウドネイティブアプリを構築しながら開発ライフサイクルのステップを評価する際には、環境間のギャップ全てに注意を払い、なるべく生じないようにする


## Factor 10. Administrative Processes
### 管理プロセス
1. 管理プロセスはアプリケーションから分離する
  * アドホックな機能を呼び出すために使用できるRESTfulエンドポイントを公開すること
  * メインアプリからバッチ関連のコードを切り出し別のマイクロサービスにする  
            トリガーはアプリケーション外におく

1.  管理、メンテナンスタスクを利用する場合、マネージドサービスが提供している機能で実現してないか検討する
  * 好きな言語でプログラミングして実現しようとすることは避ける  
    AWS Lambdaはいい選択


## Factor 11. Port Binding
### ポートバインディング
1. サービスをコンテナ化して公開する
  * 1つのコンテナ内で複数のアプリケーションを起動しないこと  
    公開するエンドポイントは、コードを変更せずに外部から設定できるようにすること

## Factor 12. Stateless Processes
### ステートレスプロセス
1. アプリケーションを1つのステートレスなプロセスとして実行しているか
  * スティッキーセッション(アプリケーションプロセスのメモリにセッション情報を持たせる)は使用しないこと。  
    セッション状態のデータは、有効期限を持つデータストア(MemcachedやRedis)に格納し、バッキングサービスを通じて利用する

1. プロセスの起動時に頻繁に使用されるデータをキャッシュするパターンは、破棄容易性の原則に違反する為

## Factor 13. Concurrency
### 並行性
1. 垂直スケーリングでなく、水平スケーリングを行う  
    破棄容易性とステートレスプロセスの原則を満たしている場合、水平スケーリングを最大限に活用する

## Factor 14. Telemetry
### 監視、計測
1. アプリケーションパフォーマンスモニタリング
  * アプリケーションが処理している1秒あたりのHTTPリクエストの平均数など
1. ビジネスに意味のある予測、分析をする為にイベントとデータを収集する
  * 例えば過去20分以内にiPadでユーザーに販売したウィジェットの数など
1. アプリケーションが正常動作しているかを監視する
  * アプリケーションの起動、シャットダウン、スケーリング、Webリクエストの追跡、定期的なヘルスチェックの結果など  

  監視戦略を計画するときは、どの程度の情報を集約するのか、それがどのくらいの割合で蓄積されるのか、そしてどれだけの量を保存するのかを考慮する

## Factor 15. Authentication an Authorization
### 認証／認可
1. クラウドネイティブアプリケーション全てがRBAC（Role Based Access Control ロールベースのアクセス制御）でエンドポイントを保護するのが理想  
  アプリケーションのリソースに対するすべてのリクエストは、誰がリクエストを行っているのか、およびそのコンシューマが属するロールを知っている必要があり、そのロールに応じて操作を実行する許可を与えるかどうかを決定する

# 参考リンク
[Beyond the Twelve-Factor App](https://speakerdeck.com/tayasu/beyond-the-twelve-factor-app)

[クラウド・ネイティブ・アプリケーションとマイクロサービスによる自動化　～IT運用自動化の新しい方向性｜第5回](https://www.imagazine.co.jp/%E3%82%AF%E3%83%A9%E3%82%A6%E3%83%89%E3%83%BB%E3%83%8D%E3%82%A4%E3%83%86%E3%82%A3%E3%83%96%E3%83%BB%E3%82%A2%E3%83%97%E3%83%AA%E3%82%B1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%A8%E3%83%9E%E3%82%A4/)