Kubernetes probes: startup, readiness và liveness xử lý ba trạng thái khác nhau Cơ bản
Thời gian đọc ước tính: 8 phút
Vấn đề
Phần tiêu đề “Vấn đề”Một API cần 40 giây nạp dữ liệu khi khởi động. Kubernetes gọi /health sau vài giây, thấy lỗi.
- Nếu
/healthcũng là liveness probe, container bị restart trước khi kịp khởi tạo, rồi lặp lại mãi. - Sửa bằng cách cho
/healthtrả200ngay thì Pod nhận traffic khi chưa mở kết nối database và trả500cho người dùng. - Cuối cùng, database gián đoạn vài giây kéo mọi Pod vào vòng restart, và database hồi phục thì gặp tải khởi động của cả đội Pod cùng lúc.
Ba tình huống này là ba câu hỏi khác nhau, nên có ba probe:
| Probe | Câu hỏi | Khi fail |
|---|---|---|
| Startup | Khởi tạo xong chưa? | Kill container, áp dụng restart policy |
| Readiness | Nhận traffic được chưa? | Rút Pod khỏi EndpointSlice, không restart |
| Liveness | Process có kẹt không hồi phục được không? | Restart container sau đủ ngưỡng |
Quy tắc chọn: readiness hay liveness?
Phần tiêu đề “Quy tắc chọn: readiness hay liveness?”Hỏi một câu: restart container này có sửa được lỗi không?
- Có (deadlock, event loop kẹt, process hỏng nội bộ) → liveness.
- Không, nhưng Pod chưa/không phục vụ được (đang nạp, mất kết nối) → readiness.
- Không và không ảnh hưởng chức năng chính → không probe nào.
| Sự cố | Probe fail | Vì sao |
|---|---|---|
| Handler deadlock, event loop kẹt | Liveness | Chỉ restart mới thoát |
| Đang nạp index/cache lúc khởi động | Startup (rồi readiness) | Chờ, đừng restart |
| Connection pool của Pod này hỏng, Pod khác vẫn tốt | Readiness | Rút riêng Pod này, nó tự hồi phục |
| Database dùng chung chết | Cẩn thận, xem dưới | Restart vô ích; fail readiness cả đội = không còn endpoint |
| Dependency phụ (email, gợi ý sản phẩm) lỗi | Không probe nào | Chỉ làm giảm chức năng phụ |
Dependency dùng chung: coi chừng rút cả đội Pod
Phần tiêu đề “Dependency dùng chung: coi chừng rút cả đội Pod”Kubernetes gợi ý readiness có thể kiểm tra các backend bắt buộc. Nhưng nếu database chung chết và readiness của mọi Pod đều gọi vào nó, mọi Pod cùng not ready, Service hết endpoint và người dùng nhận lỗi từ load balancer. Thường tệ hơn một API trả lỗi có kiểm soát hoặc phục vụ dữ liệu cache.
Nguyên tắc: readiness kiểm tra những gì chính Pod này cần và có thể khác với Pod khác (đã khởi tạo, pool còn kết nối, queue nội bộ không đầy). Với dependency dùng chung, ưu tiên degraded mode, circuit breaker hoặc timeout hợp lý ở tầng request, và alert theo SLO thay vì để probe quyết định.
Liveness thì không bao giờ gọi dependency ngoài. Tài liệu Kubernetes cảnh báo liveness cấu hình sai gây cascading failure: restart dưới tải cao, request client lỗi, và tải dồn sang các Pod còn lại.
Cách hoạt động
Phần tiêu đề “Cách hoạt động”startupContainer khởi động. Startup probe chưa thành công nên liveness/readiness chưa bắt đầu kiểm tra.
Mỗi giai đoạn, từng probe có trạng thái riêng:
Đang khởi động: chỉ startup probe chạy. Liveness và readiness chờ đến khi startup thành công.
Điểm cần nhớ từ timeline:
- Có startup probe thì liveness và readiness chưa chạy cho đến khi nó pass. Sau đó nó không chạy lại.
- Readiness chạy suốt vòng đời Pod, nên Pod có thể ra/vào endpoint nhiều lần mà không restart.
- Liveness không chờ readiness; hai probe không phụ thuộc nhau.
Startup probe hay initialDelaySeconds?
Phần tiêu đề “Startup probe hay initialDelaySeconds?”Cả hai đều trì hoãn liveness.
initialDelaySecondslà hằng số: đặt 60 giây thì app khởi động trong 5 giây vẫn chờ 60 giây.- Startup probe thử mỗi
periodSecondsvà nhường chỗ cho liveness ngay khi app sẵn sàng; cửa sổ tối đa làfailureThreshold × periodSeconds(ví dụ 30 × 10 = 300 giây trong tài liệu Kubernetes).
Với app khởi động chậm hoặc thay đổi thời gian khởi động, dùng startup probe.
Các tham số hay chỉnh
Phần tiêu đề “Các tham số hay chỉnh”| Trường | Ý nghĩa | Mặc định |
|---|---|---|
periodSeconds |
Chu kỳ gọi probe | 10 |
timeoutSeconds |
Thời gian chờ mỗi lần | 1 |
failureThreshold |
Số lần fail liên tiếp để coi là fail | 3 |
successThreshold |
Số lần pass liên tiếp để coi là pass lại | 1 |
successThreshold lớn hơn 1 chỉ cho phép với readiness (liveness và startup bắt buộc bằng 1). Dùng nó để Pod không vào/ra endpoint liên tục khi dependency chập chờn.
Manifest tối giản
Phần tiêu đề “Manifest tối giản”startupProbe: httpGet: { path: /health/startup, port: 3000 } periodSeconds: 5 failureThreshold: 24 # cửa sổ khoảng 120 giâyreadinessProbe: httpGet: { path: /health/ready, port: 3000 } periodSeconds: 5 timeoutSeconds: 2 successThreshold: 2 # pass 2 lần liên tiếp mới nhận lại trafficlivenessProbe: httpGet: { path: /health/live, port: 3000 } periodSeconds: 10 failureThreshold: 3/health/live chỉ trả lời “process còn xử lý request không”, không gọi database. Với service gRPC, kubelet gọi trực tiếp gRPC health check (ổn định từ Kubernetes v1.27):
livenessProbe: grpc: port: 9090 # server phải implement gRPC Health Checking Protocol periodSeconds: 10Probe gRPC chạy trên IP của Pod, mặc định không dùng TLS, và mọi lỗi đều tính là fail.
Khi Pod bị xoá
Phần tiêu đề “Khi Pod bị xoá”Readiness không phải cơ chế drain. Khi Pod bị xoá, endpoint của nó được cập nhật với ready = false bất kể probe, nên không cần readiness probe chỉ để drain. Nhưng việc cập nhật này lan không tức thời, nên vẫn cần preStop, xử lý SIGTERM và grace period; xem SIGTERM khi deploy.
Khi nào dùng / không dùng
Phần tiêu đề “Khi nào dùng / không dùng”| Probe | Dùng khi | Có thể bỏ khi |
|---|---|---|
| Startup | Khởi động chậm hoặc không ổn định (nạp index, warm cache, migration nhẹ) | App sẵn sàng trong vài giây |
| Readiness | Pod nhận traffic qua Service | Workload không nhận traffic (worker thuần kéo từ queue) |
| Liveness | Có kiểu lỗi kẹt mà process không tự thoát | Process crash khi lỗi: restart policy đã xử lý |
Ví dụ thực tế
Phần tiêu đề “Ví dụ thực tế”Demo mô phỏng 5 trạng thái, in ba boolean cho mỗi trạng thái (khớp timeline ở trên):
npx --prefix examples ts-node examples/src/k8s-probes/probe-demo.tsỞ dependency outage kỳ vọng readiness: false, liveness: true; ở process stuck thì liveness: false. Demo chỉ mô phỏng quyết định của endpoint, không có kubelet, ngưỡng hay EndpointSlice.
Để kiểm chứng thật, thử trên cluster test:
- Gây lỗi dependency:
kubectl get endpointsliceđổi nhưng restart count không tăng. - Gây kẹt process:
kubectl describe podghi event liveness fail rồi restart.
Trade-offs
Phần tiêu đề “Trade-offs”Tách ba tín hiệu
- Startup cho khởi động chậm mà vẫn giữ liveness nghiêm sau đó.
- Readiness rút Pod khỏi traffic mà không restart.
- Liveness hồi phục process kẹt không tự thoát.
Giá phải trả và rủi ro
- Endpoint health sai gây nhận traffic quá sớm hoặc restart storm.
- Probe kiểm tra dependency quá sâu/đắt thành nguồn tải và lan lỗi.
- Không probe nào thay graceful shutdown, timeout, retry hay metrics lỗi nghiệp vụ.
Sai lầm thường gặp
Phần tiêu đề “Sai lầm thường gặp”Checklist production
Phần tiêu đề “Checklist production”- Ba endpoint tách biệt:
/startup,/ready,/live; mỗi cái rẻ và có giới hạn thời gian. - Liveness không gọi database, cache hay service khác.
- Readiness chỉ kiểm tra thứ riêng của Pod; có kế hoạch degraded mode cho dependency chung.
- Startup probe có cửa sổ đo từ thời gian khởi động thật (p99), không copy manifest mẫu.
successThresholdở readiness đủ để tránh flapping;failureThresholdở liveness đủ để qua GC pause.terminationGracePeriodSeconds,preStopvà xử lý SIGTERM đã cấu hình theo bài graceful shutdown.- Có alert cho restart count tăng và cho số endpoint sẵn sàng về 0.
- Đã thử lỗi dependency và process kẹt trên cluster test và xác nhận đúng probe fail.
Tóm tắt
Phần tiêu đề “Tóm tắt”Tự kiểm tra: (1) Vì sao liveness ping database có thể làm outage nặng hơn? (2) Startup probe hơn initialDelaySeconds ở điểm nào? (3) Database dùng chung chết, readiness nên làm gì? (4) Readiness fail có bảo đảm request đang chạy được hoàn tất không?