コントロールプレーンとデータプレーン
制御操作の受付と反映を確認し、配置先だけでなく依存するDBまで含めて障害の影響を説明します。
説明
資源の作成や台数変更を扱う制御系をcontrol plane、アプリの要求処理など本来の機能を提供する側をdata planeと呼びます。管理APIが応答できることと、利用者の要求が成功することは、それぞれ確認が必要です。
二つのregionに配置したアプリとDBの固定構成を使います。台数変更の要求と反映の記録を読み、制御系・zone・regionの停止条件を順に変えて、どの経路が使えるかを計算します。構成図と通信結果を同じ画面でたどります。
制御操作の受付と反映を確認し、配置先だけでなく依存するDBまで含めて障害の影響を説明します。
1アプリとDBの配置
regionは地理的な配置範囲、zoneはその内部で障害範囲を分ける配置単位です。この演習ではR1・R2という識別子を使います。
cat topology.txt通常経路と切替え先の構成を読む
python3 paths.py inventory資源ごとのregion・zone・依存先を表示するR1のアプリは別zoneに2台ありますが、両方ともR1-aのdb-aへ依存しています。アプリだけを複数zoneへ置いても、DBの配置が一つなら共通の停止要因が残ります。
2台数変更の受付と反映
管理操作と利用者要求の記録を時刻順に表示します。acceptedは要求の受付、convergedは要求した状態への反映完了です。
python3 paths.py events制御系とデータ系の固定記録を読む09:00の台数変更は受け付けられましたが、反映は09:02です。その間の09:01には既存のapp-aが応答しています。受付、反映、アプリ応答を同じ出来事として扱わず、それぞれの記録を確認します。
3通常時の要求経路
現在の振分け先からDBまでの経路を確認します。成功にはアプリと依存先DBの両方が必要というモデルです。
python3 paths.py request現在の配置条件で要求の成否を計算するapp-aとapp-bの両方でstatus=200、successful_paths=2です。DBまで含む二つの経路が利用できます。
4制御系だけが停止した場合
制御系を停止条件へ入れ、管理操作と既存の要求経路を確認します。
python3 paths.py outage --scope control制御系だけを停止条件にする
python3 paths.py control管理操作の可否を確認する
python3 paths.py request既存の要求経路を確認する管理操作はunavailableですが、既存経路は2本とも成功します。この構成では既存の要求処理が制御系の呼出しへ依存していないためです。あらゆるサービスで同じ結果になるという意味ではありません。
5DBのあるzoneが停止した場合
条件を初期状態へ戻してから、R1-aだけを停止させます。
cp routing-initial.json routing.json制御系停止の条件を初期状態へ戻す
python3 paths.py outage --scope zone --name R1-aDBを含むzoneを停止条件にする
python3 paths.py requestDB依存を含めて要求の成否を計算するapp-b自身は利用可能でも、db-aへ到達できず503になります。アプリを複数zoneへ配置した事実だけでは、サービス全体がzone障害へ耐えられるとは判断できません。
6region全体の停止
R1全体を停止条件に加えます。別regionの資源があっても、自動的にそこへ要求が切り替わる構成にはしていません。
python3 paths.py outage --scope region --name R1R1の全zoneを停止条件にする
python3 paths.py request元の振分け先での結果を確認する通常の振分け先はどちらもR1なので、成功経路は0です。別regionに資源を用意することと、障害時に切り替えて使えることは別の条件です。
7別regionの経路へ切り替える
振分け先をR2のapp-cへ変更します。R2のDBはdb-cで、R1の停止条件に含まれていません。
python3 paths.py failover振分け先をapp-cへ変更する
python3 paths.py request切替え後のアプリとDBの経路を確認するapp-cとdb-cは利用可能で、成功経路が1になります。この計算は配置と依存先の可否を調べた結果であり、DBの内容が最新かどうかは別に確認が必要です。
8切替え後の設定を確認
残っている停止条件と、現在の振分け先を読みます。
python3 -m json.tool routing.json現在の経路と停止条件を整形表示するR1とR1-aは停止条件のままで、frontendsだけがapp-cになっています。元のregionが復旧したから成功したのではなく、依存先を含む別経路へ切り替えたために成功しました。
まとめ
管理操作の受付、状態の反映、利用者要求の成功を別々に確認します。
障害範囲はアプリの配置だけでなくDBなどの依存先まで含めて調べます。
別regionへの配置に加え、経路切替えとデータの更新状態の確認が必要です。
操作履歴と解説を振り返れます。
シェル / Python 3
cat topology.txt
python3 paths.py inventory通常の振分け先
app-a [R1 / R1-a] ──┐
├── db-a [R1 / R1-a]
app-b [R1 / R1-b] ──┘
切替え先
app-c [R2 / R2-a] ───── db-c [R2 / R2-a]
region: 地理的な配置範囲。zone: region内で障害範囲を分ける配置単位。
この例のR1・R2、zone名は配置モデルの識別子。
R2のデータ更新状況・名前解決・認証などは、この経路モデルの外で別に確認する。
id=app-a region=R1 zone=R1-a kind=app active=True replica=db-a
id=app-b region=R1 zone=R1-b kind=app active=True replica=db-a
id=db-a region=R1 zone=R1-a kind=db active=True
id=app-c region=R2 zone=R2-a kind=app active=True replica=db-c
id=db-c region=R2 zone=R2-a kind=db active=Truepython3 paths.py events{"accepted": true, "converged": false, "operation": "set_replicas", "plane": "control", "requested": 2, "target": "app", "time": "09:00"}
{"operation": "GET /orders", "plane": "data", "status": 200, "target": "app-a", "time": "09:01"}
{"accepted": true, "converged": true, "operation": "reconcile", "plane": "control", "requested": 2, "target": "app-b", "time": "09:02"}
{"operation": "GET /orders", "plane": "data", "status": 200, "target": "app-b", "time": "09:03"}python3 paths.py requestapp-a app_available=True db=db-a db_available=True status=200 app-b app_available=True db=db-a db_available=True status=200 successful_paths=2
python3 paths.py outage --scope control
python3 paths.py control
python3 paths.py requestoutage control management_status=unavailable app-a app_available=True db=db-a db_available=True status=200 app-b app_available=True db=db-a db_available=True status=200 successful_paths=2
cp routing-initial.json routing.json
python3 paths.py outage --scope zone --name R1-a
python3 paths.py requestoutage zone R1-a app-a app_available=False db=db-a db_available=False status=503 app-b app_available=True db=db-a db_available=False status=503 successful_paths=0
python3 paths.py outage --scope region --name R1
python3 paths.py requestoutage region R1 app-a app_available=False db=db-a db_available=False status=503 app-b app_available=False db=db-a db_available=False status=503 successful_paths=0
python3 paths.py failover
python3 paths.py requestfrontends=app-c app-c app_available=True db=db-c db_available=True status=200 successful_paths=1
python3 -m json.tool routing.json{
"frontends": [
"app-c"
],
"control_available": true,
"down_zones": [
"R1-a"
],
"down_regions": [
"R1"
]
}演習完了