Probe antipatterns
4 min read
Pod lifecycle overview · Checklist and references
Probe Antipatterns and Pitfalls
Antipattern 1: Including External Dependencies in a Liveness Probe
Problem:
livenessProbe:
httpGet:
path: /health # Includes database and Redis connection checks
port: 8080
Consequences:
- A database failure causes all Pods to restart simultaneously → Cascading Failure
- Even transient network delays cause Pods to restart.
Correct configuration:
# Liveness: Application health only
livenessProbe:
httpGet:
path: /healthz # Check internal health only
port: 8080
# Readiness: Include external dependencies
readinessProbe:
httpGet:
path: /ready # Check the database, Redis, and other dependencies
port: 8080
Antipattern 2: A High initialDelaySeconds Without a Startup Probe
Problem:
livenessProbe:
httpGet:
path: /healthz
port: 8080
initialDelaySeconds: 120 # Wait 2 minutes
periodSeconds: 10
Consequences:
- Even if the application starts in 30 seconds, it has no health checks for another 90 seconds.
- If the process exits outright (a crash), the kubelet restarts the container regardless of the liveness initialDelay; only a process that hangs without exiting goes undetected for up to 2 minutes until the initialDelay elapses.
Correct configuration:
# Protect startup with a Startup Probe
startupProbe:
httpGet:
path: /healthz
port: 8080
failureThreshold: 12 # Wait up to 120 seconds
periodSeconds: 10
# Liveness activates immediately after Startup succeeds
livenessProbe:
httpGet:
path: /healthz
port: 8080
initialDelaySeconds: 0 # Start immediately after Startup succeeds
periodSeconds: 10
Antipattern 3: Sharing an Endpoint That Checks External Dependencies for Liveness and Readiness
Problem:
livenessProbe:
httpGet:
path: /health
port: 8080
readinessProbe:
httpGet:
path: /health # Same endpoint
port: 8080
Consequences:
- If
/healthchecks external dependencies, Liveness failures cause unnecessary restarts. - Sharing an endpoint that checks only internal health is fine, but the unclear separation of responsibilities makes debugging difficult.
Correct configuration:
livenessProbe:
httpGet:
path: /healthz # Internal health only
port: 8080
readinessProbe:
httpGet:
path: /ready # Include external dependencies
port: 8080
Antipattern 4: An Overly Aggressive failureThreshold
Problem:
livenessProbe:
httpGet:
path: /healthz
port: 8080
periodSeconds: 5
failureThreshold: 1 # Restart after just 1 failure
Consequences:
- Transient network delays, GC pauses, and similar events cause unnecessary restarts.
- Restart loops can occur.
Correct configuration:
livenessProbe:
httpGet:
path: /healthz
port: 8080
periodSeconds: 10
failureThreshold: 3 # Detect failure after ~30s (3 x 10s) of consecutive failures, then restart
timeoutSeconds: 5
Antipattern 5: An Excessively Long timeoutSeconds
Problem:
livenessProbe:
httpGet:
path: /healthz
port: 8080
timeoutSeconds: 30 # Wait 30 seconds
periodSeconds: 10
Consequences:
- A healthy probe returns quickly, but a slow or hung target can take up to 30 seconds to time out, slowing failure detection by that much.
Correct configuration:
livenessProbe:
httpGet:
path: /healthz
port: 8080
timeoutSeconds: 5 # A response is required within 5 seconds
periodSeconds: 10
failureThreshold: 3