聊聊發(fā)布的那點事,零停機(jī)是不是神話?
零停機(jī)就是用戶無感知的發(fā)布。請求不斷。連接不中斷。服務(wù)平穩(wěn)切換到新版本。重要的是用戶體驗不變。
聽起來好聽,但它不是魔法。它靠方法、流程和反復(fù)演練。

一、先聊基本原則
改動要向后兼容。流量要可控。實例要能優(yōu)雅下線。數(shù)據(jù)庫變更要可回滾。步驟要自動化并可審計。
二、常見的發(fā)布策略與取舍
1. Blue-Green(藍(lán)綠)
我會把新版本部署到綠環(huán)境。驗證無誤再切流量到綠?;貪L只需把流量切回藍(lán)。缺點是需要額外資源。
示例:切流量命令和校驗輸出如下。
$ kubectl patch svc myservice -n prod -p '{"spec":{"selector":{"app":"green"}}}'
service/myservice patched$ kubectl get endpoints myservice -n prod -o wide
NAME ENDPOINTS
myservice 10.244.1.12:8080,10.244.2.15:8080這適合能承受雙倍容量的場景。
2. Canary(金絲雀)
把少量真實流量先丟給新版本。觀察指標(biāo)后逐步放量。我建議把錯誤率和 95% 延遲作為準(zhǔn)入門檻。用服務(wù)網(wǎng)格能精細(xì)控制權(quán)重。
示例:把 Canary 配置應(yīng)用后的反饋。
$ kubectl apply -f virtualservice-canary.yaml -n prod
virtualservice.networking.istio.io/myservice configured金絲雀適合風(fēng)險較高的功能變更。
3. Rolling Update(滾動升級)
在資源有限時使用它。Kubernetes 按策略替換 Pod。關(guān)鍵是 readiness 要做得嚴(yán)一點。
更新和觀察命令如下。
$ kubectl set image deployment/myapp mycontainer=myapp:2025-09-01 -n prod
deployment.apps/myapp image updated
$ kubectl rollout status deployment/myapp -n prod
Waiting for rollout to finish: 2 of 3 updated...
deployment "myapp" successfully rolled out滾動時要保證舊實例能處理未完成的請求。
三、Probe 與優(yōu)雅下線
readiness 決定實例是否能接流量。liveness 決定容器是否需要重啟。preStop 用來給應(yīng)用清理并排盡連接。
下面是常見的配置片段(示例保留)。
readinessProbe:
httpGet:
path: /health/ready
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
lifecycle:
preStransform: translateY(
exec:
command: ["/bin/sh", "-c", "sleep 10"]preStop 常用來關(guān)閉監(jiān)聽、等待連接數(shù)降到 0。這樣能避免半條請求在替換時被中斷。
應(yīng)用配置后,用下面命令部署并查看狀態(tài)。
$ kubectl apply -f deployment.yaml -n prod
deployment.apps/myapp configured四、排干連接的操作
下線節(jié)點前先把流量排干。Kubernetes 的 drain 可以把 Pod 驅(qū)逐并遷移。
命令與示例輸出如下。
$ kubectl drain node-node01 --ignore-daemonsets --delete-local-data
node/node01 cordoned
evicting pod myapp-abcde...
pod/myapp-abcde evicted
node/node01 drained對外部負(fù)載均衡器亦同理。先從后端池移出實例。觀察活躍連接為 0 再做維護(hù)。
五、數(shù)據(jù)庫模式變更:分階段、安全為王
數(shù)據(jù)庫變更最容易翻車。原則是小步快跑,保證可回滾。步驟我常用三段走法:新增字段→雙寫回填→切讀舊字段→刪舊字段。
在線變更工具會把熱表分片拷貝再切換。gh-ost 的示例如下。
$ gh-ost \
--user="ghuser" --password="ghpass" \
--host="db-master" --database="mydb" --table="orders" \
--alter="ADD COLUMN new_flag TINYINT(1) DEFAULT 0" \
--allow-on-master --execute模擬輸出示例:
INFO Migrating table orders
INFO Ghost table created: _orders_gho
INFO Applying row-copy...
INFO Cut-over completed.工具會逐步復(fù)制行并最小化鎖定窗口。不要在高峰期做大范圍結(jié)構(gòu)變更。
六、回滾要提前演練
每次發(fā)布都要有秒級回滾方案。Kubernetes 支持 rollout undo。
命令和反饋示例:
$ kubectl rollout undo deployment/myapp -n prod
deployment.apps/myapp rolled back
$ kubectl rollout status deployment/myapp -n prod
deployment "myapp" successfully rolled out回滾前要確認(rèn)目標(biāo)鏡像、配置和 probe 都存在并可用?;貪L也要走健康檢查流程,別跳過驗證。
七、CI/CD 自動化要點(實務(wù))
把發(fā)布流程寫成 pipeline。允許人工暫停和審查。關(guān)鍵是把發(fā)布操作可審計、可回溯。
示例 GitLab CI 片段(占位):
deploy_canary:
stage: deploy
script:
- kubectl apply -f k8s/canary.yaml -n prod
- kubectl rollout status deployment/myapp-canary -n prod
when: manual手動觸發(fā)能減少誤發(fā)。自動化里也要內(nèi)置告警觸發(fā)回滾的邏輯。
八、驗證與流量測試
上線前做壓力和功能驗證。對比錯誤率、延遲、連接數(shù)這三項。
一個常用的壓力測試示例:
$ wrk -t2 -c200 -d30s http://myservice.prod/health
Running 30s test @ http://myservice.prod/health
2 threads and 200 connections
Requests/sec: 12000
Latency 25ms在 Canary 上重復(fù)同樣測試。對比指標(biāo)差異決定是否放量。
九、常見陷阱(一句話一條)
改非兼容字段會出錯。probe 配置太寬松會把未就緒實例拉入流量池。未排干連接就下線會造成錯誤。忘記清理舊指標(biāo)會誤導(dǎo)后續(xù)分析。缺回滾路徑會拉長故障恢復(fù)時間。
十、最簡單的安全發(fā)布腳本(示例)
這段腳本適合小團(tuán)隊快速發(fā)布并檢查就緒。
#!/bin/bash
set -e
DEPLOY=deployment/myapp
NAMESPACE=prod
NEW_IMAGE=myapp:2025-09-01
echo "更新鏡像..."
kubectl set image $DEPLOY mycontainer=$NEW_IMAGE -n $NAMESPACE
echo "等待 rollout..."
kubectl rollout status $DEPLOY -n $NAMESPACE
echo "檢查 readiness..."
kubectl get pods -l app=myapp -n $NAMESPACE -o jsonpath='{range .items[*]}{.metadata.name} {.status.phase} {.status.containerStatuses[0].ready}{"\n"}{end}'
echo "發(fā)布完成"輸出如下:
更新鏡像...
deployment.apps/myapp image updated
等待 rollout...
deployment "myapp" successfully rolled out
myapp-abcde Running true
myapp-fghij Running true
發(fā)布完成這只是基礎(chǔ)版。復(fù)雜場景要接入流量網(wǎng)格、灰度控制和審計系統(tǒng)。






















