一覧CL-01-2 · クラウドの基本モデル

コントロールプレーンとデータプレーン

制御操作の受付と反映を確認し、配置先だけでなく依存する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

1
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=True
2
python3 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"}
3
python3 paths.py request
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
4
python3 paths.py outage --scope control python3 paths.py control python3 paths.py request
outage 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
5
cp routing-initial.json routing.json python3 paths.py outage --scope zone --name R1-a python3 paths.py request
outage 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
6
python3 paths.py outage --scope region --name R1 python3 paths.py request
outage 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
7
python3 paths.py failover python3 paths.py request
frontends=app-c
app-c app_available=True db=db-c db_available=True status=200
successful_paths=1
8
python3 -m json.tool routing.json
{
    "frontends": [
        "app-c"
    ],
    "control_available": true,
    "down_zones": [
        "R1-a"
    ],
    "down_regions": [
        "R1"
    ]
}

演習完了