前言
上一篇我們介紹了灰度發布和藍綠部署的概念,並用 Nginx Ingress 的 Canary Annotation 實作了基於 Header 和權重的流量分配。這篇要繼續介紹基於 Cookie 的流量路由,以及如何完整走完從灰度驗證到下線舊版本的整個上線流程。
基於權重的流量分配
最簡單的灰度策略就是按比例分配流量。修改 Canary Ingress 的 annotation,只保留 weight 設定:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: gray-release-canary
annotations:
nginx.ingress.kubernetes.io/canary: "true"
nginx.ingress.kubernetes.io/canary-weight: "50"
spec:
ingressClassName: nginx
rules:
- host: www.example.com
http:
paths:
- path: /
backend:
service:
name: new-nginx
port:
number: 80
pathType: ImplementationSpecific
驗證結果:
for i in $(seq 1 10); do curl -H "Host: www.example.com" http://YOUR_INGRESS_IP; done
# 大約 50% old、50% new
實際生產中,你可以從 canary-weight: "5" 開始,觀察一段時間沒問題再逐步調到 25、50、100。
基於 Cookie 的流量分配
Cookie 路由特別適合 A/B 測試場景。舉個例子:你想讓特定地區的使用者先體驗新版本,就可以在後端根據使用者地理位置設定 Cookie,然後讓 Ingress 根據 Cookie 決定路由。
設定方式
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: gray-release-canary
annotations:
nginx.ingress.kubernetes.io/canary: "true"
nginx.ingress.kubernetes.io/canary-by-cookie: "users_from_target_region"
spec:
ingressClassName: nginx
rules:
- host: www.example.com
http:
paths:
- path: /
backend:
service:
name: new-nginx
port:
number: 80
pathType: ImplementationSpecific
注意:當同時設定了 canary-by-cookie 和 canary-weight 時,Cookie 規則的優先順序更高。只有在 Cookie 沒有被設定為 "always" 或 "never" 的情況下,weight 才會生效。
驗證
# Cookie 設為 always → 100% 走新版本
for i in $(seq 1 10); do curl -H "Host: www.example.com" -b "users_from_target_region=always" http://YOUR_INGRESS_IP; done
# 全部輸出 new
# Cookie 設為 never → 100% 走舊版本
for i in $(seq 1 10); do curl -H "Host: www.example.com" -b "users_from_target_region=never" http://YOUR_INGRESS_IP; done
# 全部輸出 old
這個機制的運作方式:
- Cookie 值為
always:一定走新版本 - Cookie 值為
never:一定走舊版本 - 其他值或沒有 Cookie:根據其他 Canary 規則(weight 等)決定
完整上線流程:下線舊版本
當新版本經過充分的灰度驗證,確認穩定後,就可以進行正式的版本切換了。整個流程分三步:
步驟 1:將舊版 Service 指向新版 Pod
修改舊版 Service 的 selector,讓它指向新版本的 Pod:
# 修改 old-nginx Service
spec:
selector:
run: new-nginx # 從 old-nginx 改成 new-nginx
步驟 2:刪除 Canary Ingress
kubectl delete ingress gray-release-canary
步驟 3:清理舊版資源
# 刪除舊版 Deployment
kubectl delete deployment old-nginx
# 刪除新版 Service(因為流量已經走 old-nginx Service 了)
kubectl delete svc new-nginx
驗證最終狀態
kubectl get svc,pod,ingress
# 確認只剩下:
# - old-nginx Service(指向 new-nginx Pod)
# - new-nginx Pod
# - gray-release Ingress
for i in $(seq 1 10); do curl -H "Host: www.example.com" http://YOUR_INGRESS_IP; done
# 全部輸出 new
至此,舊版本已經完全下線,線上只跑新版本的服務。
Canary 規則完整對照表
| Annotation | 優先順序 | 值 | 行為 |
|---|---|---|---|
canary-by-header |
最高 | "always" / "never" | 強制走或不走新版本 |
canary-by-header-value |
最高 | 自訂值 | Header 值符合才走新版本 |
canary-by-cookie |
次高 | "always" / "never" | 根據 Cookie 決定路由 |
canary-weight |
最低 | 0~100 | 按比例分配流量 |
實務建議
- 漸進式提高權重:5% → 25% → 50% → 100%,每個階段觀察至少一個業務週期
- 搭配監控:在灰度期間密切關注錯誤率、延遲、CPU/記憶體指標
- 準備回滾方案:隨時可以把 weight 調回 0,或切換 Service 的 selector
- Header 規則用於內部測試:讓 QA 團隊透過特定 Header 提前驗證
- Cookie 規則用於使用者分群:按地區、帳號類型等維度進行 A/B 測試
小結
兩篇文章完整走完了用 Nginx Ingress 實現灰度發布和藍綠部署的整個流程:從概念理解、Canary Annotation 的四種規則、Header/Weight/Cookie 三種路由策略的實作,到最後的正式上線和舊版清理。這套方案不需要額外的服務網格或部署工具,只要你的叢集有 Nginx Ingress Controller 就能直接用,非常適合快速落地。

發佈留言