Health Checks: Liveness và Readiness Probes
STATUS: Running không có nghĩa ứng dụng thật sự hoạt động. Một process có thể còn sống nhưng treo cứng (deadlock), hoặc vừa khởi động xong vỏ container nhưng app bên trong chưa kết nối được database. Kubernetes cần cách hỏi container "mày khoẻ không? sẵn sàng chưa?" — đó là probe (đầu dò). Hiểu đúng hai loại probe là bước đầu để cluster của bạn tự phục hồi và không bao giờ gửi traffic vào pod chưa sẵn sàng.
Hai câu hỏi khác nhau
Đây là phần nhiều người nhầm. Liveness và readiness trả lời hai câu hỏi khác nhau, và hành động khác nhau:
Liveness probe ── "Container còn SỐNG (không treo) không?"
Fail → kubelet RESTART container.
Readiness probe ── "Container đã SẴN SÀNG nhận traffic chưa?"
Fail → loại pod khỏi endpoint Service (KHÔNG restart).
Tóm gọn: liveness lo việc khởi động lại cái treo; readiness lo việc che traffic khỏi cái chưa sẵn sàng. Một pod có thể "sống" nhưng "chưa sẵn sàng" (đang nạp cache) — lúc đó ta muốn nó không nhận traffic chứ không muốn restart nó.
Ba kiểu kiểm tra
Cả hai loại probe đều kiểm tra theo một trong ba cách:
httpGet— gọi một URL, mã 2xx/3xx là khoẻ. Phổ biến nhất cho web app (thường là endpoint/healthz).exec— chạy một lệnh trong container, exit code 0 là khoẻ.tcpSocket— thử mở một cổng TCP, mở được là khoẻ.
Kèm các tham số thời gian: initialDelaySeconds (chờ bao lâu trước khi dò lần đầu), periodSeconds (dò mỗi mấy giây), failureThreshold (fail mấy lần liên tiếp mới coi là hỏng).
Liveness probe: restart cái treo
Xem tận mắt. Pod sau cố tình "khoẻ" trong 20 giây đầu (có file /tmp/healthy), rồi xóa file đi để probe bắt đầu fail:
apiVersion: v1
kind: Pod
metadata:
name: liveness-demo
spec:
containers:
- name: app
image: busybox:1.36
args: ["sh", "-c", "touch /tmp/healthy; sleep 20; rm /tmp/healthy; sleep 600"]
livenessProbe:
exec:
command: ["cat", "/tmp/healthy"] # còn file → khoẻ; mất file → fail
initialDelaySeconds: 5
periodSeconds: 5
failureThreshold: 2
kubectl apply -f liveness-fail.yaml
# chờ ~45s rồi xem
kubectl describe pod liveness-demo | grep -iE "Unhealthy|Killing"
Warning Unhealthy 15s (x2 over 20s) kubelet Liveness probe failed: cat: can't open '/tmp/healthy': No such file or directory
Normal Killing 15s kubelet Container app failed liveness probe, will be restarted
Sau khi file biến mất, probe fail 2 lần liên tiếp (failureThreshold: 2), kubelet kết luận container treo và restart nó. Đếm số lần restart:
kubectl get pod liveness-demo
NAME READY STATUS RESTARTS AGE
liveness-demo 1/1 Running 1 (6s ago) 66s
RESTARTS 1 — kubelet đã tự khởi động lại container. Đây là tự chữa lành ở mức container: app treo được vực dậy mà không cần ai can thiệp. (Nếu cứ fail mãi, bạn sẽ thấy CrashLoopBackOff — kubelet restart với khoảng chờ tăng dần.)
Readiness probe: che traffic khỏi pod chưa sẵn sàng
Pod sau chạy nginx nhưng readiness probe gọi /healthz — đường dẫn nginx không có, nên luôn trả 404:
readinessProbe:
httpGet:
path: /healthz # nginx không có path này → 404 → never ready
port: 80
periodSeconds: 5
failureThreshold: 2
kubectl apply -f readiness-demo.yaml
kubectl get pod readiness-demo
NAME READY STATUS RESTARTS AGE
readiness-demo 0/1 Running 0 18s
Khác biệt cốt lõi nằm ở đây: STATUS vẫn là Running, RESTARTS vẫn 0 — Kubernetes không restart nó. Nhưng READY là 0/1. Lý do:
Warning Unhealthy ... kubelet Readiness probe failed: HTTP probe failed with statuscode: 404
Vì chưa READY, pod này bị loại khỏi danh sách endpoint của Service (nhớ endpoints ở Bài 5). Service sẽ không gửi traffic tới nó cho đến khi nó ready. Đây chính xác là điều bạn muốn khi pod đang khởi động hoặc tạm quá tải: đừng giết nó, chỉ đừng gửi khách tới khi nó chưa tiếp được.
startupProbe: cho app khởi động chậm
Có app khởi động lâu (nạp dữ liệu, migrate DB...). Nếu đặt liveness quá gấp, nó sẽ giết app trong lúc app còn đang khởi động — vòng lặp chết chóc. startupProbe giải quyết: kiểm tra riêng cho giai đoạn khởi động, và hoãn liveness/readiness cho tới khi startup xong. Dùng nó cho mọi app có thời gian khởi động khó đoán.
Vì sao điều này quan trọng
Probe không phải tùy chọn trang trí — chúng là nền của độ tin cậy:
- Không có liveness, app treo cứ thế treo mãi, không ai vực dậy.
- Không có readiness, rolling update (Bài 4) sẽ gửi traffic vào pod mới trước khi nó kịp sẵn sàng → người dùng gặp lỗi 502 trong vài giây mỗi lần deploy. Có readiness, Kubernetes chỉ chuyển traffic khi pod mới thật sự ready — đó là điều khiến "deploy không downtime" thành thật chứ không chỉ trên lý thuyết.
Một lưu ý: đừng để liveness probe phụ thuộc thứ bên ngoài (như database). Nếu DB sập, mọi pod fail liveness và bị restart hàng loạt — làm mọi thứ tệ hơn. Liveness nên chỉ hỏi "process của tôi còn đáp ứng không"; còn phụ thuộc ngoài thuộc về readiness.
Tổng kết
Probe cho Kubernetes biết pod có thật sự khoẻ không, qua httpGet/exec/tcpSocket. Liveness fail → restart container (vực dậy cái treo, tự chữa lành mức container). Readiness fail → loại pod khỏi endpoint Service mà không restart (che traffic khỏi pod chưa sẵn sàng) — chính là thứ làm rolling update không downtime trở nên thật. startupProbe bảo vệ app khởi động chậm. Quy tắc vàng: liveness chỉ hỏi về bản thân process, đừng để nó phụ thuộc dịch vụ ngoài.
Pod đã khoẻ và sẵn sàng đúng lúc. Bài 11: dạy Kubernetes biết mỗi pod cần bao nhiêu tài nguyên (requests/limits) và tự động scale theo tải với HPA.