Liveness, Readiness, and Startup Probes: Health Check Configurations
Liveness restarts dead containers; readiness removes unready pods from service load balancing; startup gives slow-starting apps time to initialize before liv...
Quick Answer: Liveness restarts dead containers; readiness removes unready pods from service load balancing; startup gives slow-starting apps time to initialize before liveness kicks in — run all three in production.
Detailed Answer:
| Probe | Failure Action | Purpose | When to Use | |---|---|---|---| | Liveness | Container restarted | Detect deadlocks/hangs | App can hang without crashing | | Readiness | Pod removed from Service | Signal not ready for traffic | App has warm-up time or dependencies | | Startup | Container restarted | Protect slow-starting apps | Java, .NET apps taking >30s to start |
containers:
- name: app
image: myapp:v1
# STARTUP PROBE — checked FIRST
# Disables liveness until it passes
# Gives slow apps time to initialize
startupProbe:
httpGet:
path: /healthz
port: 8080
failureThreshold: 30 # 30 attempts × 10s = 5 min max startup
periodSeconds: 10
# After this passes, liveness takes over
# LIVENESS PROBE — checked continuously after startup passes
# Failure → container KILLED and RESTARTED
# Use for: detecting deadlocks, infinite loops, hung threads
livenessProbe:
httpGet:
path: /healthz # Should return 200 if app is alive
port: 8080
initialDelaySeconds: 0 # Startup probe handles delay
periodSeconds: 15 # Check every 15 seconds
timeoutSeconds: 5 # Fail if no response in 5s
failureThreshold: 3 # Restart after 3 consecutive failures
successThreshold: 1 # 1 success to pass (liveness always 1)
# READINESS PROBE — checked continuously
# Failure → pod REMOVED from Service endpoints (no restart)
# Use for: dependency checks, warm-up, graceful degradation
readinessProbe:
httpGet:
path: /ready # Different from /healthz — checks dependencies too
port: 8080
initialDelaySeconds: 5
periodSeconds: 10
timeoutSeconds: 3
failureThreshold: 3 # Remove from service after 3 failures
successThreshold: 1 # Re-add to service after 1 success
# PROBE TYPES — httpGet, tcpSocket, exec, grpc
# TCP Socket — for non-HTTP services
livenessProbe:
tcpSocket:
port: 5432 # Just checks TCP connection opens
periodSeconds: 10
# Exec — run a command inside container
livenessProbe:
exec:
command:
- /bin/sh
- -c
- "pg_isready -U postgres -d mydb"
periodSeconds: 10
# gRPC — for gRPC services (K8s 1.24+)
livenessProbe:
grpc:
port: 50051
periodSeconds: 10
What /healthz vs /ready Should Check:
# /healthz — liveness endpoint (is the process alive?)
# Should ONLY check if the app itself is functional
# Do NOT check external dependencies here
@app.route('/healthz')
def healthz():
# Check: can I process requests? Is my thread pool alive?
return {"status": "ok"}, 200
# Never return 500 here unless the app truly needs a restart
# /ready — readiness endpoint (am I ready to serve traffic?)
# CAN check external dependencies
@app.route('/ready')
def ready():
# Check: database connected? cache warm? config loaded?
try:
db.ping()
cache.ping()
return {"status": "ready"}, 200
except Exception as e:
return {"status": "not ready", "reason": str(e)}, 503
# This removes pod from load balancer until dependencies recover
Common Mistakes:
# MISTAKE 1: Liveness probe checks external dependencies
# If DB goes down → liveness fails → pod restarts → DB still down → infinite restart loop
livenessProbe:
exec:
command: ["check-database-connection.sh"] # WRONG for liveness
# MISTAKE 2: No startup probe on slow-starting app
# Java app takes 45s to start → liveness probe fails at 30s → restarts forever
# Fix: Add startupProbe with failureThreshold: 30, periodSeconds: 10 (5 min budget)
# MISTAKE 3: Same path for liveness and readiness
# If the path checks dependencies (right for readiness) and DB goes down:
# Liveness fails → pod restarts → doesn't help → cascading restart storm
# Fix: /healthz checks only self; /ready checks dependencies
# MISTAKE 4: initialDelaySeconds on liveness when startupProbe exists
# Redundant and confusing — let startupProbe handle the delay
Key Takeaway: Separate concerns — liveness checks "am I broken beyond recovery?" (trigger restart); readiness checks "am I ready to handle requests?" (gate traffic) — never let liveness check external dependencies or you'll create restart storms.
Finished reading?
Mark as complete to claim your +15 XP and track progress.
