Probe vs Health Check Mismatch Debugging
Baseline environment: EKS 1.32+, AWS Load Balancer Controller v2.9+, Ingress-NGINX v1.11+
1. Overview
Kubernetes Probes and Load Balancer/Ingress Controller Health Checks run independently and use different mechanisms and timings. Mismatches can cause the following outages:
- 503 Service Unavailable: Probe succeeds but ALB Health Check fails
- 502 Bad Gateway: Graceful shutdown sequence mismatch sends traffic to a terminating Pod
- Transient outages: New Pods receive traffic before being fully ready during rolling updates
- 504 Gateway Timeout: Ingress timeout mismatch with backend response time
This document clarifies the mechanism differences between K8s Probes and ALB/NLB/Ingress Health Checks, and provides diagnosis methods and recommended settings for frequent mismatch patterns.
- Probe basics: Pod Health & Lifecycle — Detailed Probe configuration
- Networking debugging: Networking Troubleshooting — Service/DNS issues (coming soon)
- High availability: EKS Resiliency Guide — PDB, Graceful Shutdown
2. Mechanism Comparison: Probe vs Health Check
2.1 Kubernetes Probes (Executed by kubelet)
Kubernetes Probes are health checks executed independently by kubelet on each node.
| Probe Type | Executor | Target | Behavior on Failure |
|---|---|---|---|
| readinessProbe | kubelet | Container | Removed from Service Endpoints (Pod still alive) |
| livenessProbe | kubelet | Container | Container is restarted (SIGTERM → SIGKILL) |
| startupProbe | kubelet | Container | Disables other probes until initialization completes; restart on failure |
Key characteristics:
- Runs inside the Pod: kubelet has direct access to the container
- Service Endpoint control: readinessProbe failure → removed from
kubectl get endpoints - Fast checks: default 1s timeout, 10s interval
2.2 AWS Load Balancer Health Checks
ALB/NLB Health Checks managed by AWS Load Balancer Controller (LBC) run independently at the AWS infrastructure level.
| Health Check Type | Executor | Target | Behavior on Failure |
|---|---|---|---|
| ALB Target Group HC | ALB | HTTP(S) endpoint | Deregistered from Target Group (independent of Pod state) |
| NLB Target Group HC | NLB | TCP or HTTP | Deregistered from Target Group |
Key characteristics:
- External execution: ALB/NLB sends HTTP/TCP requests to the Pod IP
- Independent configuration: interval, timeout, threshold configured separately from K8s probes
- Slower checks: default 5s timeout, 15–30s interval
2.3 Ingress-NGINX Health Checks
The Ingress-NGINX Controller performs health checks at the nginx upstream level.
| Health Check Type | Executor | Target | Behavior on Failure |
|---|---|---|---|
| upstream health | nginx process | HTTP backend | proxy_next_upstream behavior (retry another upstream) |
Key characteristics:
- Inside the nginx process: L7 proxy-level check
- Timeout configuration:
proxy-read-timeout,proxy-send-timeout(default 60s) - Implicit checks: no dedicated health endpoint; assessed from actual request outcomes
3. Timing Comparison Table
The following table compares default timings, executors, and failure behavior for each Health Check.
| Setting | K8s Probe | ALB Health Check | NLB Health Check | Ingress-NGINX |
|---|---|---|---|---|
| Default interval | 10s | 15s | 30s | - (actual traffic) |
| Default timeout | 1s | 5s | 6s | 60s (proxy_read_timeout) |
| Failure threshold | 3 | 2 (unhealthy) | 3 | - |
| Executor | kubelet | ALB | NLB | nginx process |
| Behavior on failure | Remove from Endpoints | TG deregister | TG deregister | Remove from upstream and retry |
| Check path | /healthz etc. | / or custom | TCP or HTTP | Actual request path |
| Configured in | Pod spec | Service annotation | Service annotation | Ingress annotation |
Key timing mismatches:
- ALB checks more slowly than K8s: 15s interval vs 10s interval
- ALB timeout is longer: 5s vs 1s → Probe may pass while ALB fails
- Path mismatch: readinessProbe
/healthz≠ ALB Health Check/