漸進式部署與版本:用 wrangler versions 做金絲雀放量與一鍵 rollback | Cloudflare 完整教學

2026/08/14
漸進式部署與版本:用 wrangler versions 做金絲雀放量與一鍵 rollback | Cloudflare 完整教學

上一篇我們把環境管理Secrets 講透,結尾埋了一個大伏筆:Cloudflare 有一套「上傳新版本卻不立即全量上線」的安全發布機制。這一篇,我們就把它一次講透。你會弄懂 版本(Version)部署(Deployment) 的本質差異,學會用 wrangler versions upload 把新版本上傳到「候補區」、用 wrangler versions deploy 按百分比做金絲雀(canary)放量——先切 10% 流量、搭配 observability 監控錯誤率,確認無誤才逐步升到 100%。出問題時,一行 wrangler rollback 一鍵回滾。讀完,你就能做到真正的「零停機、可觀察、可回滾」發布。

前言

上一篇《環境管理與 Secrets》,我們用 env.staging / env.production 把測試與正式分流,也把 vars 與 Secrets 的差異、wrangler secret put 全套操作講清楚了。文章結尾我們留了一句話:CI/CD 那節提到的 wrangler versions secret put,還有反覆帶到的「先觀察、再放大」節奏,背後藏著 Cloudflare 更強大的一套發布機制——版本(Versions)與漸進式部署(Gradual Deployment)。這一篇就是那個伏筆的兌現。

先想像一個場景:你改好了 Worker 的新版本,信心滿滿執行 wrangler deploy。指令一下,新程式碼瞬間 100% 接管所有真實流量。如果新版本有個只在生產環境才會觸發的 bug(某個 edge case、某個下游 API 的異常回應),那麼所有使用者會同時遇到它。你在監控噴出紅字時才發現,但傷害已經全面發生。

漸進式部署(Gradual Deployment) 就是為了消除這種「一步到位、全有全無」的風險。它讓你把新版本先推給一小撮流量(比如 10%),在真實生產環境裡觀察一段時間,確認錯誤率、延遲都正常,才逐步把百分比拉高到 100%。這種「先讓一小群白老鼠試」的策略,業界稱為金絲雀部署(Canary Deployment)——名字源自礦工帶金絲雀下礦坑偵測毒氣的典故。

先給兩句話定義:

  • 版本(Version) 是 Worker 程式碼的一份不可變快照。每次 wrangler versions upload 就產生一個新版本,它有獨立的 Version ID、可標 tag 與 message,但上傳本身不影響線上流量
  • 部署(Deployment)決定「實際服務哪些版本、各分配多少流量」的動作。它像一張路由表:「95% 流量走版本 A、5% 走版本 B」。漸進式部署就是「一個部署同時服務兩個版本,各給不同百分比」。

打個比方:如果發布新版本像是餐廳換新菜單,傳統的 wrangler deploy 就是「今天中午起,全店所有桌子一律只供應新菜單」——萬一新菜難吃或食材有問題,全部客人一起遭殃。而漸進式部署則是「先只給靠窗那 10% 的桌子試新菜,廚房和外場緊盯這幾桌的反應(observability),客人吃得開心、沒人客訴,才慢慢擴大到 50%、最後全店」。而 wrangler versions upload 就是「新菜已經備料、試做完成,擺在後廚待命」——但還沒端上任何一桌。rollback 則是「新菜出事了,一聲令下,全店立刻換回昨天那份沒問題的舊菜單」。

理解了這個比方,本篇所有細節你都能對上號。讀完你會掌握:

  • 版本 vs 部署——兩者的本質差異,以及「上傳」與「上線」為什麼要解耦
  • 金絲雀放量流程——versions uploadversions deploy 10% → 監控 → 逐步升到 100% 的完整節奏
  • 狀態查詢與回滾——deployments listversions list 查狀態,wrangler rollback 一鍵回滾
  • 進階技巧——version overrides 測試特定版本、version affinity 解決 sticky session、搭配 observability 監控

核心概念

版本 vs 部署:上傳與上線的解耦

這是整篇文章的地基,務必先建牢。傳統心智模型裡,「部署」是一個動作:把程式碼推上去、它就開始服務流量,一氣呵成。但 Cloudflare Workers 的版本系統把這件事拆成兩半:

概念說明對應指令
Version(版本)程式碼的不可變快照,有 ID、tag、message,上傳後不影響流量wrangler versions upload
Deployment(部署)決定「哪些版本服務流量、各分多少百分比」的路由設定wrangler versions deploy
Gradual Deployment(漸進部署)一個部署同時服務兩個版本,各分不同百分比流量wrangler versions deploy A@10% B@90%

關鍵洞察是:上傳(upload)與上線(deploy)被解耦了。 你可以:

  • 半夜把新版本上傳好,隔天尖峰前才推上線
  • 先上傳、跑完自動化煙霧測試,確認沒問題才放量
  • 上傳一個「熱備」版本,萬一出事可以秒切過去

相較之下,wrangler deploy 是「上傳 + 立即 100% 上線」的一步到位版本——它其實等同於「versions upload 後緊接著 versions deploy 100%」的懶人包。適合開發、staging,或你很有把握的小改動;但要對生產環境做有風險的變更時,拆開的兩步驟才給你「中間觀察」的空間。

金絲雀放量流程示意

漸進式部署的標準節奏長這樣,把它記成一條流水線:

① upload 新版本 (0% 流量,只是候補)
        │
        ▼
② deploy 新版@10% + 舊版@90%   ← 金絲雀:只讓一小撮流量試
        │
        ▼
③ 監控 10-30 分鐘 (錯誤率?延遲?)  ← observability / wrangler tail
        │
   ┌────┴────┐
   ▼         ▼
 正常       噴錯
   │         │
   ▼         ▼
④ 升到 50%   → rollback 一鍵切回舊版
   │
   ▼
⑤ 升到 100% (新版全面接管)

每一步的核心是「放一點、看一下、再放多一點」。10% 這個起點不是硬性規定,你可以用 5%、1%,取決於你想讓多少真實使用者當白老鼠。重點是:每次拉高百分比之間,都要留出足夠的觀察窗口,讓監控數據有機會反映問題。

運作原理:流量怎麼被切分

當你執行 wrangler versions deploy A@10% B@90%,Cloudflare 的邊緣網路會在每個進來的請求上「擲骰子」——大約 10% 的請求路由到版本 A、90% 到版本 B。這個分配是按請求(per-request) 隨機的,預設不保證同一個使用者每次都打到同一版本(這會帶來「版本親和性」問題,稍後會談)。

有兩個限制要記住:

  • 一個部署最多同時服務兩個版本。 你不能一次做 A@33% B@33% C@34% 的三方分流;漸進部署永遠是「新版 + 舊版」兩者之間的百分比拉鋸。
  • 百分比加總必須是 100%。 A@10% B@90% 合法;A@10% B@80% 會被拒絕。

關鍵術語

  • Version ID:每個版本的唯一識別碼(如 095f00a7-...),versions deploy / rollback 都靠它指定目標。
  • Tag / Message:上傳版本時可附加的標籤(如 v2.1.0)與說明訊息,方便日後在版本列表裡辨識。
  • Canary(金絲雀):先讓一小撮流量試用新版本的策略,用來提早偵測問題。
  • Version Affinity(版本親和性):把同一使用者「釘選」在同一版本的機制,靠 version_metadata binding 實現。
  • Rollback(回滾):建立一個新部署,把 100% 流量立即切回指定的舊版本。

實作範例

概念齊了,直接動手走一遍完整的金絲雀放量流程。以下指令都用 npx wrangler,確保跑的是專案本地安裝的版本(漸進式部署需要 Wrangler 3.40.0 以上)。

1. 上傳新版本(不立即上線)

第一步,把新程式碼上傳成一個新版本。注意這一步不會改變任何線上流量:

# 上傳新版本(不影響現有流量),加上 tag 與說明
npx wrangler versions upload --tag v2.1.0 --message "重構快取邏輯,新增 rate limiting"

執行後,Wrangler 會回傳這個新版本的 Version ID,長這樣:

Uploaded my-worker (5.23 sec)
Worker Version ID: 095f00a7-4c2b-4f9e-8a1d-2b3c4d5e6f70
To deploy this version, use:
  npx wrangler versions deploy

把這個 Version ID 記下來(或稍後用 versions list 查),下一步要用。此時線上依然跑著版本,新版本安靜地待在「候補區」。

2. 查看版本列表,取得新舊 Version ID

放量前,先看看目前有哪些版本、誰是現役、誰是新上傳的:

# 列出最近 10 個版本
npx wrangler versions list

輸出大致如下(最新的在最上面):

Version ID                            Tag     Author            Created
095f00a7-4c2b-4f9e-8a1d-2b3c4d5e6f70  v2.1.0  ben@example.com   2026-08-14 10:23:45
1a88955c-3b1a-4e8d-9c2f-1a2b3c4d5e6f  v2.0.0  ben@example.com   2026-08-01 09:15:22

這裡:

  • 新版本(要放量的目標)= 095f00a7-...(v2.1.0)
  • 舊版本(目前的穩定版)= 1a88955c-...(v2.0.0)

在 CI 裡可以用 --json 搭配 jq 自動抓出這兩個 ID:

# 自動取得最新兩個版本 ID(CI 常用)
VERSIONS=$(npx wrangler versions list --json)
NEW_ID=$(echo "$VERSIONS" | jq -r '.[0].id')
OLD_ID=$(echo "$VERSIONS" | jq -r '.[1].id')
echo "新版本: $NEW_ID / 舊版本: $OLD_ID"

3. 以 10% 流量啟動金絲雀放量

核心來了。用 wrangler versions deploy 把新版本以 10% 流量推上線,舊版本保留 90%:

# 金絲雀:新版 10%、舊版 90%
npx wrangler versions deploy 095f00a7@10% 1a88955c@90% --message "開始金絲雀放量 v2.1.0"

也可以不帶參數,讓 Wrangler 互動式引導你分配百分比(適合手動操作、不熟 ID 時):

# 互動式:CLI 會列出版本讓你選、並問你各分多少流量
npx wrangler versions deploy

執行後,你的生產流量就進入「10% 新 / 90% 舊」的分流狀態。此刻起,約十分之一的真實使用者正在幫你試用 v2.1.0。

4. 監控:盯緊那 10% 有沒有噴錯

放量而不監控,等於沒放量。 這一步是金絲雀策略的靈魂。最直接的方式是用 wrangler tail 即時串流生產日誌,只看錯誤:

# 即時監看生產環境的錯誤日誌
npx wrangler tail --env production --status error

# 也可搜尋特定關鍵字(例如新版本可能出現的例外)
npx wrangler tail --env production --search "TypeError"

更完整的做法是在 wrangler.jsonc 開啟 observability,到 Cloudflare Dashboard 看按版本細分的指標(這是漸進部署最有價值的搭配):

{
  "observability": {
    "enabled": true,
    "head_sampling_rate": 1
  }
}

開啟後,Dashboard → Workers & Pages → 你的 Worker → Observability 可以看到:請求量、錯誤率、CPU 時間、P50/P99 延遲,而且可以按版本(ScriptVersion)分組——你能直接對比「v2.1.0 那 10% 流量的錯誤率」是否明顯高於「v2.0.0 那 90%」。這正是判斷「該繼續放量還是該回滾」的依據。

5. 逐步放大到 100%

觀察一段時間(通常 10-30 分鐘,重大變更可拉更長),確認新版本錯誤率、延遲都正常,就逐步拉高百分比:

# 升到 50/50
npx wrangler versions deploy 095f00a7@50% 1a88955c@50% --message "v2.1.0 放量至 50%"

# 再觀察一輪,確認無誤後,新版本全面接管
npx wrangler versions deploy 095f00a7@100% --message "v2.1.0 全量上線"

注意最後一步只指定一個版本 @100%——當某個版本吃下全部流量,舊版本就自動退場,漸進部署結束、回到單一版本服務的狀態。

6. 查看部署狀態與歷史

隨時可以查目前的部署狀態,以及過去的部署歷史:

# 查看目前生產部署的狀態(現在哪些版本、各多少流量)
npx wrangler deployments status

# 列出最近 10 次部署歷史(含每次的版本與流量分配)
npx wrangler deployments list

deployments list 是事後 review 與追蹤「什麼時候放量、什麼時候回滾」的完整帳本。

7. 一鍵回滾(rollback)

如果放量到一半發現新版本有問題,立刻回滾wrangler rollback 會建立一個新部署,把 100% 流量瞬間切回指定的穩定版本:

# 回滾到上一個版本(不帶參數,適合剛出事想立刻退回)
npx wrangler rollback

# 精準回滾到指定的穩定版本,並註明原因
npx wrangler rollback 1a88955c --message "緊急回滾:v2.1.0 發現記憶體洩漏"

回滾有三個重點:

  • 不是刪掉壞版本,而是用一次新部署把流量全導回好版本——壞版本仍在版本列表裡,可追溯。
  • 回滾本身也記錄成一筆部署歷史,你能在 deployments list 看到這次回滾。
  • 回滾只切流量、不動資料——它無法回滾你已寫入資料庫的資料或 schema 變更(這點下一節詳談)。

8. 進階:version overrides 測試特定版本

漸進部署期間,你可能想「不影響正式流量,只讓自己這一台瀏覽器打到新版本」做手動驗證。這時可以用 version overrides——透過 wrangler dev 連到指定版本,或在請求端帶特定標頭把自己路由到某版本:

# 本地開發時,針對特定版本做煙霧測試(遠端模式連到 preview)
npx wrangler dev --remote

# 上傳版本時同時附帶該版本專屬的 secrets(版本層級機密)
npx wrangler versions upload --tag v2.1.0 --secrets-file secrets.json

搭配上一篇提到的 wrangler versions secret put,你可以為特定版本設定機密,讓新版本用新金鑰、舊版本用舊金鑰,在漸進放量期間平順切換,而不會互相干擾。

9. 進階:version affinity 解決 sticky session

前面提過,流量分配是按請求隨機的——同一使用者可能一下打到新版、一下打到舊版。若新舊版本行為不相容,使用者就會遇到怪異的忽好忽壞。解法是版本親和性(Version Affinity),把同一使用者釘選在同一版本。

先在 wrangler.jsonc 加上 version_metadata binding:

{
  "version_metadata": {
    "binding": "CF_VERSION_METADATA"
  }
}

然後在 Worker 程式裡讀取「當前跑的是哪個版本」,並用 cookie 把使用者釘住:

export interface Env {
  CF_VERSION_METADATA: { id: string; tag: string };
}

export default {
  async fetch(request: Request, env: Env): Promise<Response> {
    // 讀取目前這個請求跑在哪個版本
    const versionId = env.CF_VERSION_METADATA.id;
    const versionTag = env.CF_VERSION_METADATA.tag;

    // 可把 versionId 寫進 cookie,後續請求靠它導回同一版本(sticky session)
    const headers = new Headers();
    headers.append("Set-Cookie", `cf_version=${versionId}; Path=/; HttpOnly`);

    return new Response(`目前版本:${versionTag}`, { headers });
  },
};

不過更根本的建議是:盡量讓新舊版本保持相容,讓「打到哪一版都不會出錯」——這樣就算不做 affinity 也安全。Version Affinity 是「新版有破壞性變更、又非漸進放量不可」時的救急手段。

常見錯誤與最佳實踐

坑一:放量卻不監控,等於沒放量。

金絲雀部署的整個意義,就是「在傷害擴大前,從那一小撮流量提早發現問題」。如果你切了 10% 就跑去忙別的、完全不看數據,那這 10% 白老鼠的犧牲就毫無價值——等你發現時可能早已升到 100%。正確做法:每次放量後,務必用 wrangler tail --status error 即時監看,或在 wrangler.jsonc 開啟 observability,到 Dashboard 看按版本細分的錯誤率與延遲,對比新舊版本的差異。沒有監控數據支撐,就不要拉高百分比。

坑二:新舊版本狀態不相容,rollback 也救不回來。

這是最隱蔽也最致命的坑。漸進部署期間,新舊版本同時在跑。如果新版本改了資料庫 schema(例如新增了一個 NOT NULL 欄位)、或寫入了舊版本讀不懂的資料格式,那麼:漸進期間,舊版本可能因讀到新格式而崩潰;更糟的是,就算你 rollback 把流量切回舊版,已經被新版寫壞/寫成新格式的資料仍在那裡——因為 rollback 只切流量、不動資料。正確做法:確保新舊版本的資料格式向前/向後相容;schema 變更採「先加後用」的漸進策略(先部署能同時處理新舊格式的中間版本,資料遷移完成後才部署只用新格式的版本);把資料庫 migration 與程式碼部署解耦,別綁在同一次放量裡。

坑三:忘記 rollback 流程,出事時手忙腳亂。

很多團隊平時不演練回滾,真出事時才發現「不知道該回滾到哪個版本」「找不到上一個穩定版的 ID」。正確做法:放量前就先用 wrangler versions list 記下「上一個穩定版的 Version ID」;把 wrangler rollback <ID> --message "..." 寫進團隊的 runbook;甚至在 CI 裡準備一個「一鍵回滾」的 workflow。回滾應該是「肌肉記憶」,而不是事故現場才臨時查手冊。

坑四:同一使用者被路由到不同版本,行為不一致。

如前所述,預設的流量分配是按請求隨機的。若新版改了回應格式或協定,使用者會遇到忽好忽壞。正確做法:優先讓新舊版本相容;若真有破壞性變更,用 version_metadata binding 搭配 cookie 實現 version affinity,把使用者釘在同一版本。

坑五:誤把 wrangler deploy 當成漸進部署。

wrangler deploy 是「上傳 + 立即 100% 上線」,沒有任何中間觀察窗口——它會覆蓋掉你正在進行的漸進部署,把某個版本直接推成 100%。正確做法:要做漸進放量,全程用 versions upload + versions deploy 這一套;wrangler deploy 留給開發、staging,或你很有把握、風險極低的小改動。

坑六:用 versions upload 卻忘了 Routes / Cron 不會自動更新。

有個容易忽略的細節:wrangler versions upload 不會自動更新 Routes 和 Cron 觸發器(這點和 wrangler deploy 不同,後者會自動更新)。正確做法:若這次變更也動到路由或排程,放量後要額外執行 wrangler triggers deploy 來同步 Routes 與 Cron。

最佳實踐小結: 記六條——放量必監控(搭配 observability 看按版本細分的指標);確保新舊版本資料相容、schema 變更用漸進策略;放量前先記下穩定版 ID、演練好 rollback 流程;必要時用 version affinity 釘住使用者;漸進放量全程用 versions 指令、別混用 wrangler deploy;別忘了 triggers deploy 同步路由與 Cron。守住這六條,你的每一次發布都能做到「零停機、可觀察、可回滾」。

小結

上一篇《環境管理與 Secrets》,我們用 env.staging / env.production 把測試與正式分流,把 vars 與 Secrets 的差異、wrangler secret put 全套操作講清楚,也在結尾埋下「上傳卻不立即上線」的伏筆。這一篇,我們把那套機制——版本(Versions)與漸進式部署(Gradual Deployment)——完整拆開:

  • 版本 vs 部署——版本是程式碼的不可變快照(versions upload,不影響流量);部署是決定「哪些版本服務、各分多少流量」的路由設定(versions deploy)。核心是上傳與上線解耦
  • 金絲雀放量流程——versions upload 上傳到候補區 → versions deploy 10% 讓一小撮流量試 → 搭配 observability / wrangler tail 監控錯誤率 → 逐步升到 50%100%
  • 狀態查詢與回滾——versions list / deployments status / deployments list 查狀態;wrangler rollback <ID> 一鍵把流量切回穩定版(只切流量、不動資料)。
  • 進階技巧——version overrides 測試特定版本、versions secret put 綁版本層級機密、version_metadata binding 實現 version affinity 解決 sticky session。

到這裡,你已經能手動完成一整套「安全發布」流程:上傳、放量、監控、回滾。但你可能已經注意到——這些步驟每次發布都要手動敲一遍指令,既繁瑣又容易出錯。有沒有辦法讓「push 程式碼 → 自動測試 → 自動漸進部署」變成一條無人值守的流水線?這正是持續整合與持續部署(CI/CD) 要解決的事。下一篇《CI/CD 自動化部署》,我們就把 wrangler-action、GitHub Actions 工作流,以及「把金絲雀放量寫進 CI」的完整自動化流程一次講透。

想先查閱官方對版本與漸進式部署的完整說明,可以隨時參考 Cloudflare 官方 Versions & Deployments 文件。漸進式部署這一課已就緒,我們下一篇《CI/CD 自動化部署》見。

BenZ Software Developer

熱愛技術的軟體開發者,在這裡分享程式開發經驗與學習筆記。

本週主打

AI 自動化入門包

你每天手動在做的那些煩事,其實 AI 可以自己跑。這份給你 10 個照著做就會的自動化工作流 + 50 個複製即用的提示詞,不用會寫程式。

看看這個產品 →