Giao diện
Mastering Kubernetes Probes
👨🔧 Góc nhìn SRE
Module này được viết từ góc nhìn của Site Reliability Engineer (SRE) tại HPN. Mục tiêu: Giữ cho hệ thống luôn khỏe mạnh và phản ứng nhanh với các sự cố.
🧟 Vấn Đề: "Zombie Pods"
Kịch bản thực tế
Bạn có một ứng dụng Java Spring Boot chạy trên Kubernetes. Mọi thứ đang hoạt động tốt cho đến khi...
text
[SRE On-Call Alert - 3:00 AM]
🚨 500 Errors spike to 30% on /api/orders endpoint
📊 Pod CPU: 5% (LOW)
📊 Pod Memory: Normal
📊 Pod Status: "Running" ✅❓ CÁI GÌ ĐÃ XẢY RA?
Kubernetes nghĩ Pod đang "Running" vì:
- Process ID (PID) vẫn tồn tại
- Container không crash
Nhưng thực tế:
- Thread pool bị Deadlock (khóa chéo)
- Ứng dụng Frozen - không thể xử lý request
- Users nhận được 500 Internal Server Error
Đây chính là hiện tượng "Zombie Pod" - container "sống" nhưng không làm được gì. Kubernetes không có cách nào biết được điều này... trừ khi bạn cấu hình Health Probes.
🔬 Giải Pháp: Bộ Ba Probe
Kubernetes cung cấp 3 loại Probe để kiểm tra sức khỏe container:
1️⃣ Liveness Probe: "Bạn còn sống không?"
💡 Câu hỏi cốt lõi
"Container của bạn có còn hoạt động không?"
- Nếu KHÔNG → Kubernetes sẽ RESTART container
- Use case: Phát hiện Deadlock, Memory Leak, Infinite Loop
yaml
apiVersion: v1
kind: Pod
metadata:
name: java-app
spec:
containers:
- name: app
image: myapp:1.0
# 🔥 LIVENESS PROBE: Phát hiện Zombie
livenessProbe:
httpGet:
path: /actuator/health/liveness
port: 8080
# ⏱️ Chờ 30s sau khi container start
initialDelaySeconds: 30
# ⏱️ Kiểm tra mỗi 10 giây
periodSeconds: 10
# ❌ Fail 3 lần liên tiếp → RESTART
failureThreshold: 3
# ⏱️ Timeout mỗi lần check: 5s
timeoutSeconds: 5Khi nào container được restart?
text
Time 0s: Container starts
Time 30s: First liveness check (initialDelaySeconds)
Time 40s: Second check ✅ OK
Time 50s: Third check ❌ FAIL (Thread deadlock)
Time 60s: Fourth check ❌ FAIL
Time 70s: Fifth check ❌ FAIL (3 failures → failureThreshold reached)
🔄 KUBELET RESTARTS CONTAINER2️⃣ Readiness Probe: "Bạn sẵn sàng nhận traffic chưa?"
💡 Câu hỏi cốt lõi
"Container có thể xử lý request từ users không?"
- Nếu KHÔNG → Kubernetes sẽ XÓA IP khỏi Service/LoadBalancer
- Use case: Slow startup, Cache warming, Overload protection
yaml
spec:
containers:
- name: app
image: myapp:1.0
# 🛡️ READINESS PROBE: Kiểm soát traffic
readinessProbe:
httpGet:
path: /actuator/health/readiness
port: 8080
initialDelaySeconds: 10
periodSeconds: 5
failureThreshold: 3Sự khác biệt quan trọng với Liveness:
| Aspect | Liveness Probe | Readiness Probe |
|---|---|---|
| Mục đích | Container còn sống? | Container sẵn sàng? |
| Hành động khi FAIL | 🔄 RESTART container | 🚫 CUT TRAFFIC (không restart) |
| Use case | Deadlock, crash loop | Slow startup, temporary overload |
Ví dụ thực tế: Cold Start
text
Pod khởi động → Cần 60s để load cache từ Redis
Không có Readiness Probe:
├── Time 0s: Pod "Running" → Nhận traffic ngay
├── Time 0-60s: Cache chưa sẵn sàng → 500 Errors!
└── User experience: BAD 😢
Có Readiness Probe:
├── Time 0s: Pod "Running" nhưng KHÔNG nhận traffic
├── Time 0-60s: Readiness check FAIL → Pod không trong Service
├── Time 60s: Cache loaded → Readiness check PASS
└── Time 61s: Pod được thêm vào Service → Nhận traffic
└── User experience: SMOOTH ✨3️⃣ Startup Probe: "Bạn đã khởi tạo xong chưa?"
💡 Câu hỏi cốt lõi
"Container đã hoàn tất quá trình initialization chưa?"
- Nếu THÀNH CÔNG → Bật Liveness & Readiness Probe
- Use case: Legacy apps với startup time rất dài (5-10 phút)
Vấn đề với Legacy Applications:
Một số ứng dụng cũ cần nhiều phút để khởi động hoàn toàn:
- Load large ML models
- Connect to multiple databases
- Warm up JIT compiler
Nếu cấu hình Liveness Probe với initialDelaySeconds: 30 nhưng app cần 5 phút để start:
text
❌ THẢM HỌA: Liveness kill container trước khi app ready
→ Container restart → Cần 5 phút → Liveness kill → RESTART LOOP!Giải pháp: Startup Probe
yaml
spec:
containers:
- name: legacy-java-app
image: legacy:1.0
# 🐢 STARTUP PROBE: Cho apps chậm
startupProbe:
httpGet:
path: /healthz
port: 8080
# Cho phép tối đa 300s (5 phút) để app khởi động
# failureThreshold * periodSeconds = 30 * 10 = 300s
failureThreshold: 30
periodSeconds: 10
# Liveness KHÔNG chạy cho đến khi Startup PASS
livenessProbe:
httpGet:
path: /healthz
port: 8080
periodSeconds: 10
failureThreshold: 3Flow hoạt động:
text
1. Container start
2. Startup Probe chạy (Liveness & Readiness bị DISABLE)
3. Startup Probe PASS sau 4 phút → OK
4. Liveness & Readiness Probe được ENABLE
5. Hệ thống hoạt động bình thường🏭 HPN Standard Configuration
📋 QUY CHUẨN HPN
Tất cả ứng dụng Production tại HPN BẮT BUỘC phải có Health Probes config đúng chuẩn.
Các tham số quan trọng
| Tham số | Mô tả | HPN Recommended |
|---|---|---|
initialDelaySeconds | Thời gian chờ trước lần check đầu tiên | 30-60s cho apps thông thường |
periodSeconds | Khoảng cách giữa các lần check | 10s (đủ nhạy, không quá aggressive) |
timeoutSeconds | Timeout cho mỗi lần probe | 5s (fail fast) |
failureThreshold | Số lần fail liên tiếp trước khi action | 3 (tránh false positive) |
successThreshold | Số lần success để coi là recovered | 1 (mặc định) |
Template chuẩn cho Java/Spring Boot
yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: hpn-java-service
spec:
replicas: 3
template:
spec:
containers:
- name: app
image: hpn-registry/java-service:1.2.3
ports:
- containerPort: 8080
# 📊 Resources (REQUIRED - Module 2)
resources:
requests:
memory: "512Mi"
cpu: "500m"
limits:
memory: "1Gi"
cpu: "1000m"
# 🔬 STARTUP PROBE (cho apps cần warm-up)
startupProbe:
httpGet:
path: /actuator/health/liveness
port: 8080
failureThreshold: 30
periodSeconds: 10
# 💓 LIVENESS PROBE
livenessProbe:
httpGet:
path: /actuator/health/liveness
port: 8080
initialDelaySeconds: 0 # Startup probe đã handle
periodSeconds: 10
failureThreshold: 3
timeoutSeconds: 5
# 🛡️ READINESS PROBE
readinessProbe:
httpGet:
path: /actuator/health/readiness
port: 8080
initialDelaySeconds: 10
periodSeconds: 5
failureThreshold: 3
timeoutSeconds: 5☠️ Lỗi Phổ Biến: Probe Check External Dependencies
🚨 SAI LẦM NGHIÊM TRỌNG NHẤT
ĐỪNG BAO GIỜ để Liveness Probe kiểm tra external dependencies như Database, Redis, hay External APIs!
Kịch bản thảm họa
Cấu hình SAI:
yaml
# ❌ WRONG: Liveness check database connection
livenessProbe:
httpGet:
path: /health # Endpoint này check DB connection
port: 8080Điều gì xảy ra khi Database gặp sự cố?
Tại sao điều này sai?
| Database down 30s | Với cấu hình SAI | Nên xảy ra |
|---|---|---|
| Kết quả | ALL PODS RESTART | Pods vẫn chạy, trả lỗi "DB unavailable" |
| Recovery time | 2-5 phút (cold start) | 0s (instant khi DB recover) |
| User impact | 100% downtime | Graceful degradation |
Cấu hình ĐÚNG
yaml
# ✅ CORRECT: Liveness chỉ check internal state
livenessProbe:
httpGet:
# Endpoint này KHÔNG check DB
# Chỉ kiểm tra: App có respond được không?
path: /actuator/health/liveness
port: 8080
# ✅ Readiness CÓ THỂ check dependency (optional)
readinessProbe:
httpGet:
# Endpoint này có thể check DB, Redis, etc.
# Nếu DB down → Pod không nhận traffic
# Nhưng KHÔNG BỊ RESTART!
path: /actuator/health/readiness
port: 8080Spring Boot Actuator ví dụ:
java
// application.yml
management:
endpoint:
health:
probes:
enabled: true
group:
liveness:
include: livenessState # Internal only!
readiness:
include: readinessState, db, redis # External deps OK here🎯 Probe Types: HTTP vs TCP vs Exec
Kubernetes hỗ trợ 3 cách để thực hiện health check:
HTTP GET (Phổ biến nhất)
yaml
livenessProbe:
httpGet:
path: /healthz
port: 8080
httpHeaders: # Optional: Custom headers
- name: X-Custom-Header
value: Probe- ✅ Ưu điểm: Kiểm tra chi tiết, flexible
- ⚠️ Yêu cầu: App phải có HTTP endpoint
TCP Socket
yaml
livenessProbe:
tcpSocket:
port: 3306 # MySQL port- ✅ Ưu điểm: Đơn giản, không cần code
- ⚠️ Hạn chế: Chỉ biết port mở, không biết app healthy
Exec Command
yaml
livenessProbe:
exec:
command:
- cat
- /tmp/healthy- ✅ Ưu điểm: Linh hoạt, chạy bất kỳ script nào
- ⚠️ Hạn chế: Tốn resource, slow hơn HTTP
📊 Tổng Kết
| Probe | Câu hỏi | Action khi FAIL | Check gì? |
|---|---|---|---|
| Liveness | Còn sống? | 🔄 RESTART | Internal state ONLY |
| Readiness | Sẵn sàng? | 🚫 Remove from LB | Có thể check dependencies |
| Startup | Đã init xong? | ⏳ Keep waiting | One-time initialization |
⚠️ GHI NHỚ
- LUÔN cấu hình
initialDelaySecondsphù hợp với thời gian boot của app - KHÔNG để Liveness check external dependencies
- SỬ DỤNG Startup Probe cho legacy apps chậm
- READINESS là bạn của graceful degradation
🔗 Liên kết
- Trước đó: Module 8: Security Context (Hardening)
- Tiếp theo: Module 10: HPA & Metrics Server
- Tham khảo: Resources & QoS (Module 2)