🎓 レベル:発展 | 重要度:A(必須)
📎 前提:モデルレジストリとモデルのライフサイクル | 関連:本番モデルの監視
要点(BLUF)
- 新モデルをいきなり全トラフィックに出すのは危険です。シャドー → カナリア → A-Bテストと段階を踏み、本番影響を抑えて安全に切り替えます。
- 3つは答える問いが違います:シャドーは「壊れず動くか(技術的健全性)」、カナリアは「少数で問題ないか(段階的安全確認)」、A-Bテストは「本当に良くなったか(ビジネス効果の統計的検証)」。
- カナリアには自動ロールバック判定を組み込みます。エラー率・遅延・主要メトリクスがしきい値を超えたら自動で前版に戻す(モデルレジストリとモデルのライフサイクル)。A-Bテストの統計的評価(有意差・検定力)は因果推論分野へ wikilink します。
1. なぜ段階を踏むのか
オフライン評価で良くても、本番では未知の入力・負荷・統合不具合が待っています。一気に切り替えると、問題が起きたとき全ユーザーが被害を受けます。リリース戦略は「影響範囲を絞りながら、技術→安全→効果の順に確かめる」リスク管理です。
2. 3つの戦略
flowchart LR S["シャドー:影で並走"] -->|"技術的に健全"| C["カナリア:少数に先行"] C -->|"少数で問題なし"| AB["A-Bテスト:効果測定"] AB -->|"有意に改善"| FULL["全面展開"] C -.->|"異常検知"| RB["自動ロールバック"] AB -.->|"改善せず/悪化"| RB
| 戦略 | やり方 | 答える問い | ユーザー影響 |
|---|---|---|---|
| シャドー | 本番入力を新モデルにも流すが応答は使わない | 壊れず動くか・遅延は許容内か | なし(影で並走) |
| カナリア | 少数(例5%)に新モデルを適用し段階拡大 | 少数で問題が出ないか | 少数のみ |
| A-Bテスト | トラフィックを分割し指標を統計比較 | 本当に良くなったか | 半数程度 |
3. シャドーとカナリアの違い
- シャドー:新モデルの予測を捨てる。本番応答は旧モデル。新モデルの遅延・エラー・予測分布だけ観測する。ユーザーは一切影響を受けない。学習/推論スキューの検出にも有効。
- カナリア:新モデルの予測を実際に使うが、対象は少数。問題があれば被害は少数に限定され、自動ロールバックで即座に戻せる。
4. 動く最小例:カナリアの自動ロールバック判定
カナリア中の指標(エラー率・遅延・主要メトリクス)を監視し、ガード条件を割ったら自動でロールバック判定を出す最小ロジックです。
def canary_decision(baseline, canary, guards):
"""baseline/canary: 観測指標の辞書。guards: 許容条件。
戻り値: ('promote'|'hold'|'rollback', 理由のリスト)"""
reasons = []
# エラー率:ベースライン比でguard倍を超えたら危険
if canary["error_rate"] > baseline["error_rate"] * guards["error_ratio_max"]:
reasons.append(f"エラー率悪化 {canary['error_rate']:.3f} "
f"> {baseline['error_rate']*guards['error_ratio_max']:.3f}")
# 遅延:絶対上限
if canary["p99_latency_ms"] > guards["p99_latency_max"]:
reasons.append(f"p99遅延超過 {canary['p99_latency_ms']} "
f"> {guards['p99_latency_max']}")
# 主要メトリクス:ベースラインを下回ったら悪化
if canary["conversion"] < baseline["conversion"] - guards["metric_drop_max"]:
reasons.append(f"主要指標低下 {canary['conversion']:.3f} "
f"< {baseline['conversion']-guards['metric_drop_max']:.3f}")
if reasons:
return "rollback", reasons
return "promote", ["全ガード条件を満たした"]
baseline = {"error_rate": 0.010, "p99_latency_ms": 80, "conversion": 0.120}
guards = {"error_ratio_max": 2.0, "p99_latency_max": 150, "metric_drop_max": 0.005}
# ケース1:健全なカナリア
good = {"error_rate": 0.012, "p99_latency_ms": 90, "conversion": 0.123}
print("ケース1:", canary_decision(baseline, good, guards))
# ケース2:エラー率・遅延・主要指標がすべて悪化したカナリア
bad = {"error_rate": 0.030, "p99_latency_ms": 180, "conversion": 0.110}
print("ケース2:", canary_decision(baseline, bad, guards))
出力:
ケース1: ('promote', ['全ガード条件を満たした'])
ケース2: ('rollback', ['エラー率悪化 0.030 > 0.020', 'p99遅延超過 180 > 150', '主要指標低下 0.110 < 0.115'])
出力の意味:ケース1はエラー率・遅延・主要指標すべてが許容内なので「promote(拡大)」。ケース2はエラー率がベースラインの2倍超、p99遅延が上限超過、主要指標もベースライン-0.005の床を下回ったので「rollback」と3つの理由つきで判定されました。人間の判断を待たず、定義したガード条件で自動的に止める——これがカナリアを安全にする核です。効果の有無(A-Bテスト)はこの先、統計的に検証します。
5. 運用の勘所
- ガード条件を事前にコード化する:エラー率・遅延・主要指標の許容を、リリース前に数値で決める。
- 自動ロールバックを既定にする:異常時に人間の承認を待たない。被害を最小化する。
- A-Bテストは統計設計を守る:サンプルサイズ・検定力・多重比較を踏まえる(効果測定の理論は因果推論分野へ)。
- 段階を飛ばさない:シャドーで技術的健全性を確認せずカナリアに進むと、避けられた障害を本番で踏む。
なぜそうするのか
リリースを段階化するのは、「確実性が低いほど影響範囲を小さく」という原則です。新モデルが本番でどう振る舞うかは、出してみるまで完全には分かりません。だから最初は影響ゼロ(シャドー)で技術を確かめ、次に少数(カナリア)で安全を確かめ、最後に効果(A-Bテスト)を統計的に確かめる。各段階で「問題なし」を確認してから影響範囲を広げることで、避けられる障害を本番全体に波及させずに済みます。
⚠️ よくある落とし穴
- シャドーを飛ばす:技術的健全性(遅延・エラー・スキュー)を確認せずユーザーに当てる。
- カナリアにロールバック条件がない:問題が出ても気づくのが遅れ、被害が拡大する。
- A-Bテストの結果を早期に覗いて止める:ピーキング問題で偽陽性。統計設計を守る(因果推論分野)。
- オフライン精度の改善=ビジネス改善と思い込む:精度が上がっても主要指標が改善するとは限らない。A-Bで確かめる。
対応 lab
- なし(概念ノート)。カナリア判定ロジックは本文 §4 に同梱。サービング基盤は オンライン推論サービング の lab。
関連ノート
- モデルレジストリとモデルのライフサイクル(ロールバック先の管理)
- オンライン推論サービング(切り替える対象の基盤)
- 本番モデルの監視(カナリアの指標を観測)
- 学習推論スキューの防止(シャドーで検出)
- 第4章 デプロイとサービング 目次
- MLOps・AI基盤 全体目次