讓 K8S 知道何時該重啟服務,何時該引導流量。
Java 應用 (Spring Boot) 有時會「假死」:Process 還在跑,但記憶體耗盡或 DB 連線池卡死,HTTP 請求完全沒回應。這時 K8S 看 Process 還活著,就繼續把使用者流量往這個殭屍 Pod 送——使用者看到的就是永遠轉圈圈的畫面。
要避免這種慘劇,得幫微服務裝上「心跳探測器」:Liveness 與 Readiness Probes。
服務剛啟動時(Spring Boot 初始化 Bean 和連線池要好幾秒),不該立刻接流量。我們在 API Gateway 特地設計了 /readyz 端點:
readinessProbe:
httpGet:
path: /readyz
port: 8080
initialDelaySeconds: 10
periodSeconds: 5
只有這個端點回 200,Service 才會把流量導進這個 Pod。Readiness 失敗不會重啟 Pod,只是暫時把它從流量池拿掉——很適合「DB 暫時連不上,等等就好」的情境。
livenessProbe:
httpGet:
path: /healthz
port: 8080
initialDelaySeconds: 20
periodSeconds: 15
Liveness 連續失敗達到 failureThreshold,K8S 就霸氣判定無藥可救,直接砍掉重練。
一樣做實驗最有感。部署兩個一模一樣的 FastAPI 服務,唯一差別:
probe-good:liveness 探測 /docs(存在,回 200)probe-bad:liveness 探測 /healthz(這個端點不存在,回 404)兩分鐘後回來看:

▲ 探針實測:probe-good 安然無恙,probe-bad 已被 K8S 重啟 4 次,Events 寫得清清楚楚
probe-good 穩穩的 RESTARTS 0;probe-bad 已經被重啟 4 次,Events 裡的劇本完整上演:
Warning Unhealthy Liveness probe failed: HTTP probe failed with statuscode: 404
Normal Killing Container backend failed liveness probe, will be restarted
這就是 K8S 引以為傲的自癒能力——但也是雙面刃:如果你的 liveness 端點寫得太敏感(例如把 DB 連線檢查放進 liveness),DB 一抖動,全部 Pod 被連環處決,小故障直接放大成全站重啟。哭啊,這種案例業界真的層出不窮。
| 檢查項目 | 放 Liveness | 放 Readiness |
|---|---|---|
| Process 能回應 HTTP | ✅ | ✅ |
| 依賴的 DB / 下游服務連得上 | ❌ 千萬不要 | ✅ 可以 |
| 快取預熱完成 | ❌ | ✅ |
總結:Liveness 只檢查「我自己」,Readiness 才檢查「我和我的朋友們」。 前者失敗會處決,後者失敗只是暫時下線,語意完全不同。
還有一個補充角色 startupProbe:給啟動特別慢的服務(像我們的 Spring Boot)用,啟動期間先接管檢查,避免 liveness 在暖機階段就開殺。
還有一件事,是我真的跑過一次換版才意會過來的:readiness 不只是擋流量,它同時是滾動更新的煞車。換版的時候,K8S 會先等新 Pod 的 readiness 通過,才敢去關掉一個舊的;探針沒過,整個更新就停在那裡不動。所謂零停機更新,其實是靠這個探針撐著的。
反過來講,沒寫 readiness 的話,K8S 會當作 Pod 一啟動就能接客,換版那一瞬間流量就打進還在暖機的服務裡了。
到今天為止,K8S 篇的基礎設施全部就位:Deployment、Service、Ingress、PVC、ConfigMap/Secret、Probes。明天開始進入自動化篇——GitHub Actions 把「寫完 code 到上線」的苦工全部接走。