11.1 自癒:Liveness 與 Readiness 探針#
機器會壞、程式會僵死。自癒不是「祈禱不掛」,而是「掛了自動有人收屍並補上」。
三種探針,分工明確#
| 探針 | 問題 | 失敗動作 | 比喻 |
|---|---|---|---|
| Liveness | 還活著嗎? | 重啟容器 | 心跳停了叫救護車 |
| Readiness | 能接客嗎? | 從 Service 摘除 | 廚師還沒備菜,先別接單 |
| Startup | 啟動完了嗎? | 啟動期內不判 liveness 死刑 | 給慢啟動應用的寬限期 |
三者缺一不可:沒 liveness,死鎖容器永遠佔位;沒 readiness,9.4 節滾動更新會把流量導入未就緒 Pod;沒 startup,Java 大應用啟動慢會被誤殺。
flowchart TD
S[容器啟動] --> ST{Startup<br/>成功?}
ST -->|否 超時| KILL[重啟容器]
ST -->|是| LOOP[進入穩態]
LOOP --> L{Liveness OK?}
L -->|否| KILL
L -->|是| R{Readiness OK?}
R -->|否| CUT[摘除 不接流量]
R -->|是| SERVE[正常服務]
CUT -.恢復.-> LOOP可直接 apply 的完整範例#
# probe.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: order
spec:
replicas: 3
selector:
matchLabels: { app: order }
template:
metadata:
labels: { app: order }
spec:
containers:
- name: order
image: taobao/order:v2
ports: [{ containerPort: 8080 }]
startupProbe: # 啟動慢的 Java 應用,給足 2 分鐘
httpGet: { path: /health, port: 8080 }
failureThreshold: 24
periodSeconds: 5
livenessProbe: # 死鎖就重啟
httpGet: { path: /health, port: 8080 }
initialDelaySeconds: 10
periodSeconds: 10
failureThreshold: 3
timeoutSeconds: 2
readinessProbe: # 依賴(DB/Redis)沒好就別接流量
httpGet: { path: /ready, port: 8080 }
periodSeconds: 5
failureThreshold: 2
successThreshold: 1
kubectl apply -f probe.yaml
kubectl describe pod <pod> | grep -A 8 Liveness
kubectl get events --sort-by=.lastTimestamp | grep -i probe
# 模擬故障:進入容器殺主進程或讓 /ready 返回 500,觀察摘除與重啟
探針三種手法:httpGet(Web 服務首選)、tcpSocket(資料庫類)、exec(執行腳本判活)。
自癒完整鏈路#
flowchart LR
P[kubelet 探針失敗] --> A1[liveness 失敗<br/>重啟容器]
P --> A2[readiness 失敗<br/>摘除 Endpoints]
A2 --> S[Service 自動跳過壞 Pod]
N[Node 心跳丟失] --> C[Controller<br/>異地重建 Pod]注意分工:kubelet 管單 Pod 生死,Controller 管跨 Node 補位(呼應 9.2 節),9.4 節的滾動更新靠 readiness 保證不斷服。
調參血淚談#
initialDelaySeconds別拍腦袋:太小誤殺,太大帶病上崗,配合 startupProbe 更穩。/health與/ready要分開:活著 ≠ 可服務(如下游 DB 斷了,活但不接單)。- 探針本身要輕:探針接口查全表,等於每 5 秒一次小 DDoS。
本章小結#
- Liveness 管重啟,Readiness 管摘除,Startup 管寬限期。
- 健康與就緒必須分開檢查,對應不同的失敗動作。
- kubelet + Controller 兩級自癒,構成 K8s 的「免疫系統」。
- 調參核心:給足啟動寬限、探針輕量、閾值留餘地。
- 活下來之後,下一步是「忙時自動加人」:HPA。
想一想#
- Liveness 與 Readiness 失敗後的動作有何不同?為什麼不能合併成一種探針?
- 沒有 Startup 探針時,啟動慢的 Java 應用會遭遇什麼?畫出誤殺時序。
- readiness 接口依賴下游 DB:如果 DB 掛了,該讓 readiness 失敗嗎?為什麼?