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)

envworkflow状態備考
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 を実行する。

stepnew %prev %意図
1199影響半径を最小化した初期露出。低トラフィック時間帯でも probe が通せる程度の露出。
21090有意なエラー率を出すための統計的最低ライン。
35050negative selection (新旧で挙動差を比較できる範囲)。
41000cutover 完了。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 動作

  1. step N で probe FAIL を検知
  2. --no-rollback 指定がなければ、step N-1 の % まで wrangler versions deploy を再 apply
  3. step N-1 が無い (= 最初の step で fail) 場合は、手動 rollback を促すメッセージを出力して exit 1 (scripts/deploy/rollback.sh api <env> もしくは wrangler versions rollback を別途実行する)
  4. Discord #p0-alerts (DISCORD_WEBHOOK_ALERTS) に @here 付き P0 通知
  5. 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 [email protected] 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,1005 回以上 成功 (100% 到達)
  • dev で 意図的に壊れた version を投げて、probe FAIL → 最後の良い % へ rollback が動くことを 1 回以上確認
  • stg で 1,10,50,1003 回以上 成功
  • 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.ymlif: falseif: 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_ENABLEDfalse に戻すだけで即座に 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