一覧SE-08-1 · リリースと変更

デプロイとリリースの切り替え

段階配置、一括の経路切替え、一部への公開、機能フラグを、それぞれ何を変更する操作か説明します。

説明

新しいプログラムを配置することと、利用者へ新しい動作を公開することは分けられます。少しずつ配置先を置き換える方法、別の一式を用意して経路を切り替える方法、一部の要求だけを新しい版へ送る方法があります。

四つの配置先A〜DへPythonファイルを置き、要求JSONを各配置先の別プロセスで処理する実行環境を使います。A・Bがblue、C・Dがgreenです。旧版の送料は一律500円、新版はフラグを有効にすると3000円以上が無料になります。配置・経路・フラグを変え、返る版と金額を確認します。

段階配置、一括の経路切替え、一部への公開、機能フラグを、それぞれ何を変更する操作か説明します。

1旧版二台へ要求を送る

初期状態にし、商品代3000円の要求を4件送ります。blueのA・Bが交互に処理します。

python3 control.py initA〜Dと経路・フラグを初期化する python3 control.py probe --count 4 --amount 3000同じ金額で4件の処理結果を見る

すべてv1で合計3500円です。配置先のファイルを実行し、返ったJSONのstatus・version・totalを並べています。

2一台だけ新版へ置き換える

Aだけをv2へ変更します。機能フラグはまだ無効です。

python3 control.py deploy --slot A --version v2Aのプログラムだけを新版へ替える python3 control.py probe --count 4混在中の応答を確認する --amount 3000

Aはv2、Bはv1ですが、どちらも合計3500円です。段階的な置換中は新旧の版が混在するため、同じ入力や共有データを両方が扱える必要があります。

3残る一台も新版へ

Bもv2へ変更します。

python3 control.py deploy --slot B --version v2残るBを新版へ替える python3 control.py probe --count 4 --amount 3000

すべてv2になりましたが、合計は3500円のままです。配置が終わったことと、新しい送料規則を公開したことは同じではありません。

4フラグで新しい動作を公開

新しい送料規則を有効にします。プログラムの配置は変更しません。

python3 control.py flag --enabled yes新しい送料規則を有効にする python3 control.py probe --count 4 --amount 3000

v2のまま合計3000円へ変わりました。機能フラグは、配置済みのコードがどの動作を選ぶかを制御します。フラグを戻せば済む範囲と、データ変更を伴って戻せない範囲は別に検討します。

5別の一式へ配置して待機させる

初期状態へ戻し、greenのC・Dへv2を配置します。フラグを有効にしても、要求の経路はまだblueです。

python3 control.py init python3 control.py deploy --slot C --version v2待機側Cへ配置する python3 control.py deploy --slot D --version v2待機側Dへ配置する python3 control.py flag --enabled yes python3 control.py probe --count 4まだblueが応答することを確認する --amount 3000

応答はA・Bのv1で3500円です。greenへ配置しても、そこへ要求を送るまでは利用者向けの応答は変わりません。二つの一式を持つ分の資源も必要です。

6経路をgreenへ一括で切り替える

現在の経路をgreenへ変更します。

python3 control.py route --pool green要求の送付先をgreenへ切り替える python3 control.py probe --count 4 --amount 3000

C・Dのv2が合計3000円を返します。このように別の一式を用意して経路を切り替える方式がblue-greenです。この例では、コードをコピーし直さず経路をblueへ戻すこともできます。

7起動確認だけでは見つからない失敗

初期状態へ戻し、3000円以上の新規則で失敗する版をC・Dへ配置します。healthは起動可能かを返します。

python3 control.py init python3 control.py deploy --slot C --version v2-bad特定入力で失敗する版を配置する python3 control.py deploy --slot D --version v2-bad python3 control.py flag --enabled yes python3 control.py health --slot CCの起動確認 python3 control.py health --slot DDの起動確認

どちらもready=trueです。しかしhealthは3000円の料金計算を通っていません。起動できることだけで、利用時の処理も正しいとは判断できません。

8一部の要求だけを新版へ送る

canaryを20%へ設定し、10件送ります。この固定の振分けでは、番号を10で割った余りが0・1の要求がgreenへ進みます。

python3 control.py route --canary 20一部だけgreenへ振り分ける python3 control.py probe --count 1010件の成功・失敗と送付先を確認する --amount 3000

10件中2件がgreenへ進んでstatus=500、残り8件はblueのv1で成功します。少数の要求を先に新しい版へ送ることで、全体へ広げる前に対象の失敗を観測できます。

9割合を戻して影響を止める

canaryを0%へ戻します。配置済みの失敗する版は残っていますが、要求を送らなくなります。

python3 control.py route --canary 0新しい版への要求を止める python3 control.py probe --count 10 --amount 3000

10件ともblueで成功します。影響を止める操作と、問題のあるプログラムを修正・再配置する作業を分けられます。実際の公開判断では、エラー率だけでなく遅延や結果の正しさも観測します。

まとめ

段階配置では新旧が混在し、blue-greenでは用意した別の一式へ経路を切り替えます。

機能フラグは配置済みコードの動作を切り替えます。配置・経路・動作の制御は別の操作です。

canaryで一部の要求を観測し、問題があれば割合を戻せます。起動確認だけで利用時の正しさは分かりません。

操作履歴と解説を振り返れます。

Python 3 / シェル

1
python3 control.py init python3 control.py probe --count 4 --amount 3000
initialized: blue=A,B green=C,D active=blue flag=off
request=0 slot=A status=200 version=v1 total=3500
request=1 slot=B status=200 version=v1 total=3500
request=2 slot=A status=200 version=v1 total=3500
request=3 slot=B status=200 version=v1 total=3500
requests=4 failed=0
2
python3 control.py deploy --slot A --version v2 python3 control.py probe --count 4 --amount 3000
deployed A=v2
request=0 slot=A status=200 version=v2 total=3500
request=1 slot=B status=200 version=v1 total=3500
request=2 slot=A status=200 version=v2 total=3500
request=3 slot=B status=200 version=v1 total=3500
requests=4 failed=0
3
python3 control.py deploy --slot B --version v2 python3 control.py probe --count 4 --amount 3000
deployed B=v2
request=0 slot=A status=200 version=v2 total=3500
request=1 slot=B status=200 version=v2 total=3500
request=2 slot=A status=200 version=v2 total=3500
request=3 slot=B status=200 version=v2 total=3500
requests=4 failed=0
4
python3 control.py flag --enabled yes python3 control.py probe --count 4 --amount 3000
new_shipping=True
request=0 slot=A status=200 version=v2 total=3000
request=1 slot=B status=200 version=v2 total=3000
request=2 slot=A status=200 version=v2 total=3000
request=3 slot=B status=200 version=v2 total=3000
requests=4 failed=0
5
python3 control.py init python3 control.py deploy --slot C --version v2 python3 control.py deploy --slot D --version v2 python3 control.py flag --enabled yes python3 control.py probe --count 4 --amount 3000
initialized: blue=A,B green=C,D active=blue flag=off
deployed C=v2
deployed D=v2
new_shipping=True
request=0 slot=A status=200 version=v1 total=3500
request=1 slot=B status=200 version=v1 total=3500
request=2 slot=A status=200 version=v1 total=3500
request=3 slot=B status=200 version=v1 total=3500
requests=4 failed=0
6
python3 control.py route --pool green python3 control.py probe --count 4 --amount 3000
active=green canary=0%
request=0 slot=C status=200 version=v2 total=3000
request=1 slot=D status=200 version=v2 total=3000
request=2 slot=C status=200 version=v2 total=3000
request=3 slot=D status=200 version=v2 total=3000
requests=4 failed=0
7
python3 control.py init python3 control.py deploy --slot C --version v2-bad python3 control.py deploy --slot D --version v2-bad python3 control.py flag --enabled yes python3 control.py health --slot C python3 control.py health --slot D
initialized: blue=A,B green=C,D active=blue flag=off
deployed C=v2-bad
deployed D=v2-bad
new_shipping=True
C {"ready": true, "version": "v2-bad"}
D {"ready": true, "version": "v2-bad"}
8
python3 control.py route --canary 20 python3 control.py probe --count 10 --amount 3000
active=blue canary=20%
request=0 slot=C status=500 version=v2-bad error=new rule failed
request=1 slot=D status=500 version=v2-bad error=new rule failed
request=2 slot=A status=200 version=v1 total=3500
request=3 slot=B status=200 version=v1 total=3500
request=4 slot=A status=200 version=v1 total=3500
request=5 slot=B status=200 version=v1 total=3500
request=6 slot=A status=200 version=v1 total=3500
request=7 slot=B status=200 version=v1 total=3500
request=8 slot=A status=200 version=v1 total=3500
request=9 slot=B status=200 version=v1 total=3500
requests=10 failed=2
9
python3 control.py route --canary 0 python3 control.py probe --count 10 --amount 3000
active=blue canary=0%
request=0 slot=A status=200 version=v1 total=3500
request=1 slot=B status=200 version=v1 total=3500
request=2 slot=A status=200 version=v1 total=3500
request=3 slot=B status=200 version=v1 total=3500
request=4 slot=A status=200 version=v1 total=3500
request=5 slot=B status=200 version=v1 total=3500
request=6 slot=A status=200 version=v1 total=3500
request=7 slot=B status=200 version=v1 total=3500
request=8 slot=A status=200 version=v1 total=3500
request=9 slot=B status=200 version=v1 total=3500
requests=10 failed=0

演習完了