Canary Deploy — CF Workers Versions API
SSoT 参照: 通知 channel / severity 振り分けは notification-strategy.md、 rollback 手順は rollback-runbook.html、 SLO / Error Budget は slo-error-budget.html。 本 runbook は 「new version を段階的に配信して悪い変更の影響半径を絞る」手順のみ扱う。
1. 概要
Cloudflare Workers の Gradual Deployments (Versions API) を利用して、
new version を 1% → 10% → 50% → 100% と段階的にトラフィックを切り替える。
各 step で synthetic healthcheck (/healthz/ready) を probe し、
1 つでも 200 以外を返したら最後の良い traffic % まで自動 rollback する。
従来の wrangler deploy は単純な one-shot replace で、悪いコードが瞬間で 100%
に当たる。canary deploy はこのリスクを「最大でも次 step 分の影響半径」に圧縮する。
1.1 環境別の有効化状況 (2026-05-01)
| env | workflow | 状態 | 備考 |
|---|---|---|---|
| dev | .github/workflows/canary-deploy-dev.yml |
ENABLED | workflow_dispatch 手動 trigger のみ。自動 trigger 無し。 |
| stg | .github/workflows/canary-deploy-stg.yml |
ENABLED | workflow_dispatch 手動 trigger のみ。dev で動作実証してから使う。 |
| prod | .github/workflows/canary-deploy-prod.yml |
DISABLED (if: false) |
ファイルは配置済だが job が if: false で無効化。dev/stg で 5+ 回成功してから main thread が flag on。 |
2. 設計
2.0 全体フロー
flowchart LR upload[wrangler versions upload
新 version を 0% で待機] --> trigger[gh workflow run
canary-deploy-{env}.yml
+ version_id] trigger --> S1[step 1: shift to 1%] S1 --> P1{healthz probe
5 回中 1 回でも fail?} P1 -- No --> W1[wait interval] W1 --> S2[step 2: shift to 10%] S2 --> P2{probe?} P2 -- No --> W2[wait] W2 --> S3[step 3: shift to 50%] S3 --> P3{probe?} P3 -- No --> W3[wait] W3 --> S4[step 4: shift to 100%] S4 --> P4{probe?} P4 -- No --> DONE[cutover 完了
#p2-deploys に DONE 通知] P1 -- Yes --> RB[最後の良い % に rollback
#p0-alerts に @here 通知] P2 -- Yes --> RB P3 -- Yes --> RB P4 -- Yes --> RB
2.1 ステップシーケンス
デフォルト sequence は 1,10,50,100。各 step 後 10 分 wait してから probe を実行する。
| step | new % | prev % | 意図 |
|---|---|---|---|
| 1 | 1 | 99 | 影響半径を最小化した初期露出。低トラフィック時間帯でも probe が通せる程度の露出。 |
| 2 | 10 | 90 | 有意なエラー率を出すための統計的最低ライン。 |
| 3 | 50 | 50 | negative selection (新旧で挙動差を比較できる範囲)。 |
| 4 | 100 | 0 | cutover 完了。wrangler versions deploy <new>@100% で single-version 状態に戻す。 |
workflow_dispatch input steps で書き換え可能 (例: 5,25,75,100 / 10,100 など)。
step が単調増加であることだけがチェックされる。interval も同様に override 可。
2.2 各 step での判定基準
| 判定軸 | 閾値 | 動作 |
|---|---|---|
/healthz/ready probe |
5 回中 1 回でも 200 以外 | fail → 最後の良い % へ rollback |
| Sentry error rate (将来) | baseline × 3 を 5 分継続 (rollback-runbook §2 と同じ閾値) | 現状は手動監視。Sentry API 連携は Phase 2。 |
| p99 latency (将来) | 1s 超を 5 分継続 | 現状は手動監視。OTel / Honeycomb 配線後に自動化。 |
Phase 1 本 runbook の自動判定は healthz probe のみ。Sentry / latency は rollback-runbook.html §2 の人間判断ループに委ね、 canary 走行中は別タブで Sentry Issues を見ておくこと。Phase 2 で
scripts/deploy/canary-shift.shに Sentry API 連携を足す。
2.3 失敗時の自動 rollback 動作
- step N で probe FAIL を検知
--no-rollback指定がなければ、step N-1 の % までwrangler versions deployを再 apply- step N-1 が無い (= 最初の step で fail) 場合は、手動 rollback を促すメッセージを出力して exit 1
(
scripts/deploy/rollback.sh api <env>もしくはwrangler versions rollbackを別途実行する) - Discord
#p0-alerts(DISCORD_WEBHOOK_ALERTS) に@here付き P0 通知 - workflow は exit 1 で赤くなる →
notify-discord-ci.ymlが#p2-deploysにも通知
2.4 べき等性
同じ step を再 apply しても CF 側は no-op。canary が中断された場合の再実行は 以下のいずれかで安全に行える:
- 失敗 step の 前 step % が active なら、再起動して続きから走らせる (probe が早期に通って次 step に進む)
- 明らかに壊れているなら
scripts/deploy/rollback.sh api <env>で旧 version 100% に戻して仕切り直し
3. 使い方
3.1 前提: new version を upload しておく
canary は「すでに 0% で待機している new version」をシフトするだけなので、まず通常の deploy 経路と
別に wrangler versions upload で待機 version を作る。versions upload は traffic に
混ぜない (= 0% に固定された unrouted version)。
# dev: 待機 version を作る (traffic はまだ流れない)
cd parky/api
npx wrangler@4.12.0 versions upload --env dev \
--message "feat: ABC change ready for canary" \
--tag "abc-canary"
# 出力された Version ID を控える (例)
# Worker Version ID: 12345678-aaaa-bbbb-cccc-dddddddddddd
本 runbook を書いた時点では deploy-api-{dev,stg}.yml はまだ通常の wrangler deploy を
使っており、自動で versions upload はしない。canary 経路に乗せる場合は手動で upload する
か、別 PR で deploy workflow を versions upload ベースに置き換える (Phase 2)。
3.2 dev / stg で canary を起動 (手動)
# gh CLI 経由
gh workflow run canary-deploy-dev.yml \
-f version_id=12345678-aaaa-bbbb-cccc-dddddddddddd \
-f steps="1,10,50,100" \
-f interval=600
# stg
gh workflow run canary-deploy-stg.yml \
-f version_id=<new-version-uuid> \
-f steps="1,10,50,100" \
-f interval=600
あるいは GitHub UI: Actions タブ → "Canary Deploy API (CF Workers / dev)" → Run workflow → version_id 入力。
3.3 検証用走行 (no-rollback)
失敗時の rollback を抑制して、ログで挙動だけ確認したい場合:
gh workflow run canary-deploy-dev.yml \
-f version_id=<id> \
-f steps="1,100" \
-f interval=120 \
-f no_rollback=true
3.4 ローカルから直接 script を叩く (緊急時 / 動作確認時)
cd parky
export CLOUDFLARE_API_TOKEN=$(bash .claude/scripts/op-cache/op-cache.sh get-secret cloudflare/api-token)
export CLOUDFLARE_ACCOUNT_ID=5d8f6201999f8965395396c4674cbe2d
export DISCORD_WEBHOOK_ALERTS=$(bash .claude/scripts/op-cache/op-cache.sh get-secret discord/webhook-alerts)
bash scripts/deploy/canary-shift.sh dev <new-version-id> \
--steps "1,10,50,100" --interval 600
4. prod 有効化チェックリスト
prod (
canary-deploy-prod.yml) は現状if: falseで無効化済。 本番でいきなり canary 切替は危険なので、まず dev / stg で動作実証してから main thread が 別 PR で flag を on にする。以下のチェックリストをすべて埋めてから上げる。
4.1 動作実証 (必須)
- dev で
1,10,50,100を 5 回以上 成功 (100% 到達) - dev で 意図的に壊れた version を投げて、probe FAIL → 最後の良い % へ rollback が動くことを 1 回以上確認
- stg で
1,10,50,100を 3 回以上 成功 - stg で rollback 動作を 1 回以上確認
- dev/stg いずれかで Schemathesis gate (deploy-api-stg.yml) が canary 完了後も green を維持していること
4.2 ドキュメント / 通知
- 本 runbook (canary-deploy.html) の prod 手順セクションを update
- rollback-runbook.html §再発防止 checklist の "Canary / staged rollout を入れる余地" を closeout
- oncall.html に「prod canary 走行中の挙動 / 中断 / 強制 100% 化」コマンドを追記
- notification-strategy.html の P0/P1/P2 マトリクスに canary の通知を反映
- on-call 担当者への周知 (Discord
#parky-eng+ 1on1) が完了
4.3 workflow / flag 切替
-
canary-deploy-prod.ymlのif: falseをif: vars.CANARY_PROD_ENABLED == 'true'に書き換え (main thread の別 PR) - repository variables に
CANARY_PROD_ENABLED = "true"を投入 - 初回 prod canary は 業務時間内 に手動 trigger (low traffic 時間帯)
- 初回完了後 24h は手動 deploy 禁止 (regression 観察ウィンドウ)
4.4 後戻り戦略
有効化後 prod で問題が出た場合:
- repository variables の
CANARY_PROD_ENABLEDをfalseに戻すだけで即座に prod canary が無効化される (workflow 自体は残る) - active な canary がある状態で disable しても、すでに走行中の job には影響しない (= 完走 or 失敗 rollback まで動く)
- 必要なら
scripts/deploy/rollback.sh api prod --confirm --reason="canary disabled"で旧 version 100% に強制復帰
5. 必要 secret / 設定
| secret | 用途 | 取得元 |
|---|---|---|
OP_SERVICE_ACCOUNT_TOKEN |
1Password から CF API token を引く | repo secrets (既存) |
CLOUDFLARE_API_TOKEN |
1P fallback. wrangler の認証 | 1P op://p3ezteh54f3msvl4wqyw7gbiam/fckmphwmq7pccoyg6ye3vf4f34/credential |
DISCORD_WEBHOOK_ALERTS |
canary FAIL 時の P0 通知 (#p0-alerts, @here) |
repo secrets (既存) |
DISCORD_WEBHOOK_DEPLOYS |
canary START / DONE の P2 通知 (#p2-deploys) |
repo secrets (既存) |
6. ファイル一覧
scripts/deploy/canary-shift.sh— 本体ロジック (split apply + probe + rollback)scripts/deploy/health-probe.sh— probe 既存スクリプト (再利用).github/workflows/canary-deploy-dev.yml— dev workflow_dispatch.github/workflows/canary-deploy-stg.yml— stg workflow_dispatch.github/workflows/canary-deploy-prod.yml— prod (if: falseで DISABLED)
7. 関連 docs
- rollback-runbook.html — canary 失敗後 / canary 不要時の即時 revert
- synthetic-healthcheck.html —
/healthz/readydeep probe の前提 - notification-strategy.html — Discord 通知 SSoT
- incident-response.html — canary fail を P0/P1 として扱う際のトリアージ
- deployment-rollback.html — wrangler rollback / Pages rollback の通常版