Kubernetes Probes • Interactive Educational Dashboard

Kubernetes Probes

Liveness Probe, Readiness Probe, và Startup Probe không chỉ là ba nút kiểm tra sức khỏe. Chúng là cơ chế để Kubernetes quyết định pod nào được nhận traffic, container nào cần restart, và ứng dụng khởi động chậm có được “tha mạng” đủ lâu hay không.

Điều người học cần “bắt sóng”

Readiness quyết định pod có vào Service endpoints hay không
Liveness quyết định container có bị restart không
Startup bảo vệ app khởi động chậm khỏi false failure
Config sai có thể gây restart loop, mất traffic, rollout méo mó
Method gồm httpGet, tcpSocket, exec

Bản đồ tư duy

Traffic & Service routing
Readiness fail thì pod vẫn sống, nhưng bị gỡ khỏi luồng traffic.
Container restart
Liveness fail thì kubelet restart container. Cấu hình quá gắt có thể thành restart loop.
Safe startup window
Startup probe pass xong, Liveness và Readiness mới “ra sân” đầy đủ.

1. The Problem Without Probes

Probe tồn tại vì Kubernetes không tự “đọc tâm trạng” ứng dụng. Một process có thể còn sống nhưng treo logic. Một app có thể đã chết nhưng Service vẫn route traffic vào. Không có probe, người dùng trở thành QA bất đắc dĩ và thấy lỗi 500 trước cả cluster kịp hiểu chuyện gì đang xảy ra.

Before vs After
Before ProbesService vẫn route traffic
Service
Pod A
Process treo / app crash
Receiving traffic ❌
Request đi qua Service và đâm thẳng vào pod lỗi. User nhận HTTP 500.
500 Internal Server Error
Không có tín hiệu health rõ ràng, control plane vẫn tin rằng pod này “có tồn tại”, còn user thì lãnh đủ.
With ProbesKubernetes có cơ sở để quyết định
Service
Pod B
Ready + Healthy
Receiving traffic ✅
Readiness chỉ giữ pod tốt trong endpoints. Liveness restart pod hỏng thay vì để nó rỉ lỗi mãi.
200 OK
Probe biến cluster từ một “hộp đen hy vọng” thành một hệ thống phản ứng có chủ đích.

2. The Three Probes: Visual Comparison

Cả ba probe đều là health checks, nhưng mỗi probe trả lời một câu hỏi khác nhau. Nhầm vai là chuyện rất nhiều team gặp, và hậu quả thường hiện ra đúng lúc rollout hoặc lúc traffic tăng vọt.

Purpose • Action • Timing
Probe Purpose Action on Failure Action on Pass When it runs Use case thực tế
Liveness Container có còn tự hồi phục được không?
Kiểm tra app có bị deadlock, treo, hoặc stuck vô hạn không.
Kubelet đánh dấu thất bại và restart container. Nếu fail liên tục có thể thành restart loop. Container tiếp tục chạy bình thường. Sau khi container start. Nếu có Startup Probe thì Liveness thường chờ Startup Probe pass xong mới có ý nghĩa đầy đủ. Ứng dụng web bị deadlock, worker mắc kẹt, process sống nhưng không xử lý request được nữa.
Readiness Pod có sẵn sàng nhận traffic không?
Kiểm tra năng lực phục vụ hiện tại.
Pod bị remove khỏi Service endpoints. Container không nhất thiết bị restart. Pod được đưa vào load balancing và nhận traffic. Trong suốt vòng đời pod, đặc biệt quan trọng khi khởi động, warming cache, mất kết nối DB, hoặc drain traffic. App chưa load xong config/cache, hoặc downstream dependency đang lỗi nên chưa nên nhận request mới.
Startup App đã khởi động xong chưa?
Bảo vệ ứng dụng start chậm khỏi bị Liveness “xử oan”.
Kubelet coi startup thất bại là không khởi động được và có thể kill / restart container. Cho phép hệ probe bình thường tiếp quản, đặc biệt là Liveness và Readiness. Chỉ trong giai đoạn startup. Khi pass rồi, Startup Probe ngừng vai trò chính của nó. Java app, ML service load model lớn, migration boot-time, app cold start lâu.

3. Pod Lifecycle + Probe Timeline

Probe gắn chặt với Pod Lifecycle. Từ Pending tới lúc Ready, Kubernetes không chỉ chờ container chạy, mà còn chờ bằng chứng rằng ứng dụng thật sự có thể phục vụ. Timeline dưới đây cho thấy chỗ Startup Probe đứng chắn cửa, rồi nhường sân cho Readiness và Liveness.

Lifecycle → Ready
Pending
Pod được schedule lên node, image đang pull, volume/network đang chuẩn bị.
Init
Init Containers chạy trước để setup dữ liệu, config, migrations sơ bộ.
Startup Probe
Đây là cổng kiểm tra “đã boot xong chưa?”. Nếu chưa, Kubernetes tiếp tục chờ trong cửa sổ cho phép.
Liveness + Readiness
Sau khi startup ổn định, Kubernetes bắt đầu kiểm tra sống khỏe và sẵn sàng nhận traffic.
Running
Container đang chạy. Nhưng “Running” chưa chắc đã “Ready”.
Ready
Readiness pass, pod được thêm vào endpoints của Service và bắt đầu nhận request.
Điểm quan trọng: nếu Startup Probe fail liên tục tại giai đoạn startup, container bị coi là không khởi động nổi và có thể bị kill/restart. Nếu không có Startup Probe cho app start chậm, Liveness có thể “đấm nhầm đồng đội” ngay lúc app còn đang warm up.

4. Interactive Probe Simulator

Đây là phần “bấm là thấy”. Bạn có thể làm một pod fail theo từng kiểu để quan sát: Readiness fail thì pod bị rút khỏi traffic, còn Liveness fail thì container bị restart. Mọi sự kiện được ghi vào log giả lập giống tinh thần kubelet đang nói chuyện trong terminal.

Click to break things, safely
Service routing to healthy endpoints
Active endpoints: 3 / 3
pod-1
Status: Ready
Liveness: PASS
Readiness: PASS
Traffic ON
pod-2
Status: Ready
Liveness: PASS
Readiness: PASS
Traffic ON
pod-3
Status: Ready
Liveness: PASS
Readiness: PASS
Traffic ON
Realtime kubelet-ish log
tail -f /var/log/probe-sim.log

5. Configuration Deep Dive

Đây là phần dễ viết vài dòng YAML nhưng đủ sức làm cả rollout nghiêng ngả. Một probe tốt không chỉ là endpoint đúng, mà còn là các ngưỡng thời gian hợp lý với startup time, recovery time, và đặc tính tải của ứng dụng.

YAML + Semantics
apiVersion: apps/v1
kind: Deployment
metadata:
  name: probes-demo
spec:
  replicas: 3
  selector:
    matchLabels:
      app: probes-demo
  template:
    metadata:
      labels:
        app: probes-demo
    spec:
      containers:
        - name: app
          image: myorg/probes-demo:1.0

          startupProbe:
            httpGet:
              path: /startup
              port: 8080
            initialDelaySeconds: 5
            periodSeconds: 5
            failureThreshold: 24
            timeoutSeconds: 2

          readinessProbe:
            httpGet:
              path: /ready
              port: 8080
            initialDelaySeconds: 2
            periodSeconds: 5
            timeoutSeconds: 2
            failureThreshold: 2
            successThreshold: 2

          livenessProbe:
            httpGet:
              path: /healthz
              port: 8080
            initialDelaySeconds: 15
            periodSeconds: 10
            timeoutSeconds: 2
            failureThreshold: 3
initialDelaySeconds

Khoảng chờ trước khi probe bắt đầu. Đặt quá thấp thì app chưa warm up xong đã bị kết luận là fail. Kết quả: deploy xong là crash loop như tàu lượn gập ghềnh.

periodSeconds

Chu kỳ chạy probe. Quá ngắn sẽ tạo nhiều check không cần thiết, tăng noise và nguy cơ false negative. Quá dài thì phát hiện lỗi chậm như camera an ninh ngủ quên.

failureThreshold

Số lần fail liên tiếp trước khi coi là thật sự fail. Với Liveness, ngưỡng quá thấp nghĩa là một nhịp hiccup cũng đủ làm restart container. Với Startup Probe, ngưỡng này quyết định app có đủ thời gian boot không.

successThreshold

Chủ yếu quan trọng với Readiness. Dùng để tránh vừa lóe sáng một lần đã được đưa vào traffic ngay. Tăng vừa đủ giúp pod chứng minh là đã ổn định, không chỉ may mắn pass một cú.

Danger Zone: config sai thì cluster méo thế nào?

  • initialDelaySeconds quá thấp → app boot chưa xong đã bị probe fail → rollout chậm hoặc stuck.
  • periodSeconds quá ngắn + timeoutSeconds quá thấp → probe nhạy quá mức với spike CPU / GC pause / network jitter.
  • failureThreshold quá thấp cho Liveness → restart loop liên tục, làm cache lạnh mãi, latency tăng dây chuyền.
  • Readiness endpoint phụ thuộc quá nhiều downstream → chỉ một dependency chập chờn là cả service tự cắt hết pod khỏi traffic.
  • Không có Startup Probe cho app khởi động chậm → Liveness xử sai app “chưa tỉnh” thành app “đã chết”.

6. Probe Methods: httpGet vs tcpSocket vs exec

Cùng là probe nhưng cách kiểm tra khác nhau sẽ cho độ chính xác và chi phí khác nhau. Chọn sai method giống dùng nhiệt kế để đo đường truyền mạng: có số, nhưng sai câu hỏi.

Method Selection
httpGet
kubelet
/healthz

Phù hợp cho web service

Rõ nghĩa, dễ quan sát, trả được status code và đôi khi biểu đạt logic app tốt hơn chỉ mở port.

  • Dùng cho API, web server, gateway
  • Hợp với endpoint như /ready, /healthz, /startup
  • Không nên nhồi quá nhiều dependency nặng vào endpoint
tcpSocket
kubelet
port open?

Phù hợp cho dịch vụ chỉ cần kiểm tra cổng

Nhanh, đơn giản, nhưng chỉ xác nhận rằng socket có mở. Nó không nói nhiều về logic ứng dụng phía sau.

  • Dùng cho DB proxy, dịch vụ TCP thuần, broker
  • Tốt khi app không expose HTTP health endpoint
  • Không đủ nếu port mở nhưng app vẫn “đơ logic”
exec
kubelet
script

Phù hợp cho kiểm tra đặc thù

Cho phép chạy script hay lệnh tùy biến trong container. Mạnh nhưng cần cẩn thận vì phức tạp, dễ tốn tài nguyên và dễ sai môi trường.

  • Dùng khi cần check file, process, custom condition
  • Tốt cho app legacy không có HTTP endpoint
  • Tránh script nặng hoặc side effect

7. Common Mistakes & Anti-Patterns

Phần lớn tai nạn với probes không đến từ YAML thiếu dòng, mà đến từ việc hỏi sai câu hỏi bằng đúng cú pháp. Dưới đây là các lỗi phổ biến ngoài đời thật, kiểu “trông có vẻ đúng nhưng production thì nhăn mặt”.

Warnings from the trenches

Dùng cùng một endpoint cho Readiness và Liveness

Đây là lỗi kinh điển. Readiness hỏi “có nên nhận traffic không?”, còn Liveness hỏi “có nên restart không?”. Gộp chung một endpoint dễ khiến một sự cố tạm thời của dependency biến thành hàng loạt restart vô ích.

initialDelaySeconds quá thấp

App vừa thức dậy còn đang kéo config, warm cache, mở connection pool, load model, chạy JIT... probe đã gõ cửa dồn dập. Hệ quả là container chưa kịp phục vụ đã bị xem là lỗi.

Liveness quá aggressive

Một vài giây CPU spike, GC pause, I/O chậm hoặc network jitter không có nghĩa app “đã chết”. Liveness quá nhạy sẽ biến transient hiccup thành restart loop và làm hệ thống càng kém ổn định hơn.

Không dùng Startup Probe cho app khởi động chậm

Java app, app chạy migration, service load model lớn, hoặc legacy monolith cold start chậm thường cần Startup Probe. Nếu bỏ qua, Liveness có thể giết app ngay ở giai đoạn nó chỉ đơn giản là chưa boot xong.