| Tested on | Rocky Linux 10.2 (Red Quartz) workstation |
|---|---|
| Package | kubectl 1.36.3 |
| Applies to | Any host with kubectl configured; Kubernetes 1.27+ cluster with Linux worker nodes |
| Cert prep | CKA · CKAD · CKS |
| Lab environment | Multi-node kubeadm cluster with containerd — install Kubernetes with kubeadm |
| Privilege | Normal user (no sudo required on the workstation) |
| Scope | Liveness, readiness, and startup probes; HTTP, TCP, exec, and gRPC probe types; timing fields; probe failure effects; controlled readiness and liveness demos; decision tables; and common misconfiguration mistakes. Does not cover full Pod troubleshooting runbooks, Service YAML, application health-endpoint development, load balancer health checks, readiness gates, lifecycle hooks, or PodDisruptionBudgets. |
Probes are how the kubelet checks container health. This walkthrough configures HTTP probes on a web Deployment in probe-lab, then shows shorter TCP, exec, and gRPC examples so you can match the probe type to what your application actually exposes.
How Kubernetes Probes Work
A probe is a diagnostic performed periodically by the kubelet against a container. An exec probe runs a command inside the container, while HTTP, TCP, and gRPC probes make network requests to the Pod. HTTP and gRPC probes target the Pod IP, TCP checks originate from the node, and exec commands run inside the container.
| Probe | Main purpose | Result of repeated failure |
|---|---|---|
| Liveness | Detect an unhealthy running container | Container is restarted |
| Readiness | Decide whether the Pod can receive traffic | Pod becomes NotReady |
| Startup | Protect slow-starting containers | Container is restarted |
Kubernetes supports HTTP GET, TCP socket, exec, and gRPC probes. Built-in gRPC probes have been stable since Kubernetes v1.27. Native gRPC probes are a Kubernetes feature and do not need a special container-runtime capability.
Liveness vs Readiness vs Startup
Use the probes for different failure modes:
- Readiness — temporary inability to serve requests. Traffic should pause, but a restart may not help.
- Liveness — the process is alive but stuck. Restart only when that restart can recover the application.
- Startup — initialization takes longer than normal liveness timing allows.
When a startup probe is defined, liveness and readiness checks do not run until startup succeeds.
A Pod can show phase Running while the Ready condition is false. kubectl get pods may display 0/1 in the READY column even though STATUS is Running. Phase and readiness are separate signals — see Kubernetes Pods and Pod lifecycle for conditions and STATUS meanings.
Configure Kubernetes Probe Types
HTTP Probe
This Deployment uses nginx with a ConfigMap that returns HTTP 200 on /startup, /ready, and /health. Each probe targets a different path on the named port http.
Save probe-nginx.conf:
server {
listen 80;
root /usr/share/nginx/html;
default_type text/plain;
location = /startup {
try_files /startup-ok =503;
}
location = /ready {
try_files /ready-ok =503;
}
location = /health {
try_files /health-ok =500;
}
}Create the ConfigMap and Deployment:
kubectl create namespace probe-labkubectl create configmap probe-nginx-conf -n probe-lab --from-file=default.conf=probe-nginx.confSave web-probes.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: web
namespace: probe-lab
spec:
replicas: 1
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
containers:
- name: nginx
image: nginx:1.27.0
command: ["/bin/sh", "-c"]
args:
- |
printf 'startup ok\n' > /usr/share/nginx/html/startup-ok
printf 'ready ok\n' > /usr/share/nginx/html/ready-ok
printf 'health ok\n' > /usr/share/nginx/html/health-ok
exec nginx -g 'daemon off;'
ports:
- name: http
containerPort: 80
volumeMounts:
- name: nginx-conf
mountPath: /etc/nginx/conf.d/default.conf
subPath: default.conf
startupProbe:
httpGet:
path: /startup
port: http
scheme: HTTP
periodSeconds: 2
failureThreshold: 30
readinessProbe:
httpGet:
path: /ready
port: http
periodSeconds: 5
failureThreshold: 3
livenessProbe:
httpGet:
path: /health
port: http
periodSeconds: 10
failureThreshold: 3
volumes:
- name: nginx-conf
configMap:
name: probe-nginx-confThe startup command recreates the marker files whenever the container restarts.
Important httpGet fields:
path— URL path the kubelet requestsport— number or named port from the container specscheme—HTTPorHTTPShttpHeaders— optional extra headers (not shown here)
Apply the manifest:
kubectl apply -f web-probes.yamlSample output:
deployment.apps/web createdWait until the Deployment reports available:
kubectl wait --for=condition=Available deployment/web -n probe-lab --timeout=120skubectl get pods -n probe-lab -l app=webSample output:
NAME READY STATUS RESTARTS AGE
web-6f48c76c7c-qbrhv 1/1 Running 0 3sInspect probe configuration on the Pod:
kubectl describe pod -n probe-lab -l app=webThe Liveness, Readiness, and Startup sections list probe type, path, port, and timing. Events at the bottom show probe failures when they occur.
Watch READY change during later tests:
kubectl get pods -n probe-lab -l app=web --watchStop the watch with Ctrl+C when you finish observing changes.
TCP Socket Probe
A TCP probe succeeds when the kubelet opens a TCP connection to the port. It does not read HTTP bodies or validate application logic.
livenessProbe:
tcpSocket:
port: 80
periodSeconds: 5Use TCP when the process listens on a port but does not expose a dedicated HTTP health path. An open socket does not prove the application returns correct responses.
exec Probe
An exec probe runs a command inside the container namespace. Exit code 0 means success. Any non-zero exit code means failure.
livenessProbe:
exec:
command:
- cat
- /tmp/healthy
periodSeconds: 5The command and any binaries it calls must exist in the container image. A typical pattern creates /tmp/healthy during container start, then probes with cat.
Shell quoting, command versus args, and entrypoint interaction are covered in commands, args and environment variables.
gRPC Probe
gRPC probes use the gRPC Health Checking Protocol. The application must implement the health service on the target port.
livenessProbe:
grpc:
port: 50051
service: health
periodSeconds: 5The port field must be numeric. Named ports are not supported for gRPC probes. If the service name is wrong or the health RPC is not implemented, the probe fails.
Lab example with agnhost. Save the manifest as grpc-probe.yaml:
apiVersion: v1
kind: Pod
metadata:
name: grpc-probe
namespace: probe-lab
spec:
containers:
- name: agnhost
image: registry.k8s.io/e2e-test-images/agnhost:2.53
args:
- grpc-health-checking
- --port=50051
ports:
- containerPort: 50051
readinessProbe:
grpc:
port: 50051
periodSeconds: 2
failureThreshold: 3
livenessProbe:
grpc:
port: 50051
periodSeconds: 5kubectl apply -f grpc-probe.yamlSample output:
pod/grpc-probe createdkubectl wait --for=condition=Ready pod/grpc-probe -n probe-lab --timeout=60sSample output:
pod/grpc-probe condition metkubectl describe pod grpc-probe -n probe-labThe Readiness and Liveness sections should show grpc <pod>:50051. Without a readiness probe, the container can become Ready before its first gRPC liveness check succeeds; readiness controls the Pod Ready condition, while liveness controls container restarts. The wait command above verifies that the gRPC health service actually returns SERVING. The agnhost grpc-health-checking command supports --port, so the --port=50051 argument is valid. This article does not cover implementing the gRPC health service in application code.
Tune Probe Timing and Thresholds
| Field | Purpose |
|---|---|
initialDelaySeconds |
Delay before the first probe |
periodSeconds |
Interval between checks |
timeoutSeconds |
Time allowed for one check |
failureThreshold |
Consecutive failures before action |
successThreshold |
Consecutive successes required after failure |
Approximate startup allowance is initialDelaySeconds + (failureThreshold × periodSeconds). Probe execution and timeout timing can make the observed wall-clock interval vary slightly.
For the HTTP Deployment manifest above:
0 + (30 × 2 seconds) = approximately 60 seconds
Kubernetes documents startup sizing using the initial delay plus the failure-threshold and period window. Liveness and startup probes require successThreshold: 1. Readiness can use a higher successThreshold when you want several consecutive successes before marking the Pod ready.
There is no single timing preset that fits every application. Tune from observed startup time and failure behavior rather than copying defaults blindly.
How Probe Failures Affect the Pod
Readiness probe failure
When readiness fails repeatedly:
- The container keeps running.
- The Pod Ready condition becomes
False. - Endpoints for matching Services and EndpointSlices drop the Pod until readiness succeeds again.
Traffic stops, but the process is not restarted.
Liveness probe failure
When liveness fails past failureThreshold:
- The kubelet stops and restarts the container.
RESTARTSincreases onkubectl get pods.- Repeated failures can lead to
CrashLoopBackOffbackoff between restarts.
Startup probe failure
When startup fails past its threshold:
- The container is restarted before liveness and readiness run.
- Fix slow startup by widening startup timing, not by disabling liveness without analysis.
Test Readiness and Liveness Failures
This controlled demo uses the web Deployment from the HTTP section. Readiness and liveness are tested on the same running container by removing marker files the nginx config serves.
Confirm the Pod is ready:
kubectl get pods -n probe-lab -l app=webSample output:
NAME READY STATUS RESTARTS AGE
web-6f48c76c7c-qbrhv 1/1 Running 0 3sReadiness failure test
POD=$(kubectl get pod -n probe-lab -l app=web -o jsonpath='{.items[0].metadata.name}')kubectl exec -n probe-lab "$POD" -- rm -f /usr/share/nginx/html/ready-okkubectl wait --for=condition=Ready=false pod/"$POD" -n probe-lab --timeout=30skubectl get pod "$POD" -n probe-labExpected state:
NAME READY STATUS RESTARTS AGE
web-6f48c76c7c-qbrhv 0/1 Running 0 2mRestore readiness:
kubectl exec -n probe-lab "$POD" -- sh -c "printf 'ready ok\n' > /usr/share/nginx/html/ready-ok"kubectl wait --for=condition=Ready pod/"$POD" -n probe-lab --timeout=30sA readiness failure marks the container and Pod not ready without restarting it.
Liveness failure test
BEFORE=$(kubectl get pod "$POD" -n probe-lab -o jsonpath='{.status.containerStatuses[0].restartCount}')kubectl exec -n probe-lab "$POD" -- rm -f /usr/share/nginx/html/health-okWait for the restart instead of immediately assuming RESTARTS=1:
DEADLINE=$((SECONDS + 120))
while true; do
CURRENT=$(kubectl get pod "$POD" -n probe-lab -o jsonpath='{.status.containerStatuses[0].restartCount}')
if [ "$CURRENT" -gt "$BEFORE" ]; then
break
fi
if [ "$SECONDS" -ge "$DEADLINE" ]; then
echo "Timed out waiting for the liveness restart" >&2
exit 1
fi
sleep 2
donekubectl get pod "$POD" -n probe-labThe Pod name remains unchanged while the container restart count increases. The container startup command then recreates health-ok.
Inspect probe events:
kubectl describe pod "$POD" -n probe-labSample Events lines:
Warning Unhealthy ... Liveness probe failed: HTTP probe failed with statuscode: 500The kubelet restarted the container because the liveness probe could not read a healthy response from /health.
Choose the Correct Probe
| Requirement | Probe |
|---|---|
| Do not send traffic until startup is complete | Readiness (after startup succeeds) |
| Temporarily stop traffic during overload or maintenance | Readiness |
| Restart an application stuck in an unrecoverable state | Liveness |
| Allow a slow application extra startup time | Startup |
| Check a web endpoint | HTTP httpGet |
| Check whether a port accepts connections | TCP tcpSocket |
| Run an application-specific command | exec |
| Check a gRPC health service | gRPC |
Common Probe Configuration Mistakes
| Symptom | Likely cause | Fix |
|---|---|---|
| Same strict dependency check on liveness and readiness | Restart loops during external outages | Use readiness for dependencies; keep liveness focused on the local process |
| Container restarts during slow startup | Liveness runs before the app listens | Add a startup probe with a longer failureThreshold × periodSeconds window |
| Probe always fails on a healthy app | Wrong port, path, or scheme | Match probe settings to the listening port and health URL |
| exec probe always fails | Command or file missing in the image | Verify binaries and paths inside the container filesystem |
| Pod Running but not Ready | Readiness probe failing | kubectl describe pod — check readiness Events and probe fields |
| Rising RESTARTS or CrashLoopBackOff | Liveness too aggressive or app exits | Inspect probe timing, logs, and previous container logs |
For describe, logs, conditions, and restart-count workflows, use Kubernetes Pods and Pod lifecycle. When restarts coincide with memory limits, see OOMKilled and exit code 137. Kubernetes Services explains how ready Pods become Service endpoints.
What's Next
- Kubernetes ConfigMap with Examples
- Kubernetes Secrets with Examples
- Kubernetes Requests, Limits and QoS Classes
References
- Configure Liveness, Readiness and Startup Probes — official task guide
- Pod lifecycle — probe behavior in Pod conditions
Summary
You configured liveness, readiness, and startup probes on one Deployment, using separate HTTP paths so each check can target a different concern. Readiness failures removed the Pod from the ready set without killing the container. Liveness failures increased the restart count when the kubelet could not reach the health endpoint.
The main configuration mistake is using liveness for problems a restart cannot fix. Pair readiness with Service traffic decisions, startup with slow initialization, and liveness only when restarting the container is a valid recovery step. Validate probe YAML with kubectl apply --dry-run=server before production changes — see kubectl apply, edit, patch and replace for server-side dry-run mechanics.
When probes look correct but traffic still misbehaves, read Pod conditions and Service endpoints together.

