Introduction
Kubernetes probes are essential for controlling container lifecycle, but misconfigured probes can cause cascading failures, increased latency, and service disruptions. This article provides a practical field guide to performance tuning for Kubernetes probes, covering diagnosis, optimization, and verification. It focuses on the three types of probes—liveness, readiness, and startup—and shows you how to identify bottlenecks, adjust parameters, and validate changes safely.
Targeted at developers, DevOps engineers, and SREs, this guide bridges the gap between theory and practice. You'll learn concrete techniques for improving probe latency, reducing false positives, and ensuring your deployments remain stable under load. We'll use real-world examples, commands, and expected outputs to illustrate every concept.
Our approach emphasizes operational safety: always observe before changing, limit the blast radius of any modification, use placeholders for sensitive values, and verify results with clear acceptance criteria. By following this guide, you'll be able to tune probes confidently and minimize risk.
Understanding Kubernetes Probes
Kubernetes probes are health checks performed by the kubelet on behalf of your containers. There are three types:
- Liveness probes determine if a container is alive. If they fail, the kubelet kills the container and restarts it according to your restart policy.
- Readiness probes determine if a container is ready to serve traffic. If they fail, the container's endpoints are removed from the service, so no traffic is sent to it.
- Startup probes are used for containers that need extra time to start. They succeed when the application is ready, and then liveness/readiness take over.
Each probe is configured with four parameters:
initialDelaySeconds: how long to wait after the container starts before probing.periodSeconds: how frequently to probe.timeoutSeconds: how long to wait for a probe response before considering it failed.failureThreshold: how many consecutive failures trigger a restart (for liveness) or removal from service (for readiness).successThreshold: how many consecutive successes are required to consider the probe passed after it has failed (readiness only).
Common probe handlers include:
exec: runs a command inside the container; success if exit code 0.httpGet: performs an HTTP GET request; success if response code is 200-399.tcpSocket: attempts to open a TCP connection; success if the port accepts a connection.
Proper tuning involves selecting the right handler, setting appropriate thresholds, and ensuring your application's endpoints respond promptly.
Version and Environment Inventory
Before tuning any probe, you must understand your environment. This means identifying:
- Kubernetes version: the version determines which probe features are available (e.g., startup probes are beta in 1.16 and GA in 1.20).
- Container runtime: e.g., containerd, CRI-O, Docker (deprecated).
- Network plugin: e.g., Calico, Flannel, Cilium, which can affect probe response times.
- Application stack: programming language, framework, and dependencies that affect startup time and resource usage.
Read-only observation: Start by gathering the current state of your pods and their probe configurations. Use kubectl get pods -o wide to see the list of pods and their IPs. Then, for a specific pod, run kubectl describe pod <pod-name> to view its current probe settings and recent events. Also check logs with kubectl logs <pod-name> --previous to see why a previous container crashed.
Prerequisite check: Ensure kubectl is configured and you have adequate permissions. Verify your cluster version with kubectl version.
Command example:
kubectl get pods -o wide
kubectl describe pod my-app-7d8f9b5c5c-abc123
Expected output: The describe output includes a section like:
Liveness: http-get http://:8080/healthz delay=0s timeout=1s period=10s #success=1 #failure=3
Readiness: http-get http://:8080/readyz delay=0s timeout=1s period=10s #success=1 #failure=3
Now you have a baseline to compare against.
Safe Configuration Path
When you decide to change a probe, follow a safe path: make one small, reversible change at a time, and verify it before moving on. This limits the blast radius if something goes wrong.
Smallest justified change: For example, if your readiness probe is causing endpoints to be removed unnecessarily due to slow responses, you might increase the failureThreshold or the timeoutSeconds slightly. Do not change multiple parameters at once.
Test locally first: Use a development or staging cluster to test changes. You can also use kubectl port-forward to test your application's health endpoints locally before rolling out changes.
Command example: First, inspect the current probe config with:
kubectl get deployment my-app -o jsonpath='{.spec.template.spec.containers[0].livenessProbe}'
Then, apply a patch to modify the timeout:
kubectl patch deployment my-app -p '{"spec":{"template":{"spec":{"containers":[{"name":"my-app","livenessProbe":{"timeoutSeconds":2}}]}}}}'
Expected output: The deployment is updated, and a new ReplicaSet is created. Verify the rollout status:
kubectl rollout status deployment/my-app
Key insight: Always check the impact on the application before and after the change. Use metrics from your application, such as request latency, error rates, and pod restarts, to determine if the change improved things.
Verification and Diagnostics
After making a change, you must verify that it achieves the desired effect without side effects. This involves both automated checks and manual inspection.
Observe the results: Use kubectl describe pod to see if probes are now passing. Check the Events section for any new failures. Also, monitor the pod's status: e.g., kubectl get pod -o wide to see if the pod is Running and Ready.
Check application logs: Look for patterns that indicate probe success or failure. For example, if you have a health endpoint that logs every request, you can see if probes are hitting it and how long they take.
Command example: To check if the probe is hitting a specific endpoint, you can tail logs:
kubectl logs deployment/my-app --tail=10
Expected output: You should see log lines like:
Received probe request at /healthz from 10.244.0.5:45922 - 200 OK (0.4ms)
Useful diagnostic commands:
kubectl get events --sort-by=.lastTimestampto see cluster events including probe failures.kubectl describe node <node-name>to check the health of the node and its kubelet.
Verification of the fix: If you increased the probe timeout because the probe was timing out, you can simulate a slow response by stress-testing the endpoint. For example, using curl with timing:
curl -o /dev/null -s -w 'time_total: %{time_total}\n' http://<pod-ip>:8080/healthz
If the response time is now within the timeout, the probe should pass.
Failure Modes and Recovery
Understanding failure modes is crucial for effective tuning. Common failures include:
- Probe timeout: The probe command/HTTP request takes longer than
timeoutSeconds. This could be due to a slow server or network issues. - Connection refused: The port is not open, indicating the application is not listening yet.
- Invalid response: The HTTP endpoint returns a non-2xx code. This could be due to a misconfigured health check path.
- Application overload: The container is consuming too much CPU/memory, causing probe responses to be slow.
Each of these requires a different recovery strategy.
Recovery steps:
- Immediate: Check the pod status and events. If the pod is in
CrashLoopBackOff, inspect logs for the cause.
kubectl logs my-app-7d8f9b5c5c-abc123 --previous
- Diagnose: Use
kubectl execto test the endpoint from within the container:
kubectl exec -it my-app-7d8f9b5c5c-abc123 -- curl localhost:8080/healthz
- Mitigate: If the probe is failing because the application is slow to start, consider increasing
initialDelaySecondsor adding a startup probe. If the application is under heavy load, scale up or improve resource requests/limits.
Example scenario: Your liveness probe is using an HTTP endpoint that performs a database query. During a database slowdown, the probe times out, causing the container to be restarted. To recover, you might change the liveness endpoint to a more lightweight check (e.g., a simple process check) or increase the timeout. Always document the change and its rationale.
Recovery verification: After applying a fix, verify that the pod remains healthy for a sustained period. Use kubectl get pods -w to watch for restarts.
Operations Checklist
To ensure consistency and safety, follow this checklist when tuning probes:
- [ ] Version and environment: Confirm Kubernetes version, runtime, network, and application stack.
- [ ] Baseline observation: Record current probe configuration (with
kubectl describe) and application metrics. - [ ] Read-only diagnostic: Check pod status, events, and logs.
- [ ] Single change: Modify only one probe parameter at a time.
- [ ] Test in dev: Apply the change in a non-production environment first.
- [ ] Validate: Check probe success/failure intervals using
kubectl get eventsand application logs. - [ ] Monitor: Watch for changes in restart count, readiness, and traffic.
- [ ] Document: Record what you changed, why, and the outcome.
- [ ] Rollback plan: If the change worsens performance, revert to the previous configuration.
Automation tip: Use GitOps-style practices where your Kubernetes manifests are versioned. You can then review probe changes in pull requests and roll back easily.
Conclusion
Tuning Kubernetes probes is a delicate task that requires a systematic approach. By understanding your environment, making small incremental changes, and verifying with concrete metrics, you can optimize probe performance without introducing instability.
Remember: the goal is not just to pass probes but to ensure your application is truly healthy and available. Use the techniques described here to diagnose issues, apply fixes, and confirm they work. Always document your changes and maintain a rollback plan.
As a next step, audit your current deployments: list all probe configurations, identify any that are unusually aggressive or lenient, and plan a tuning exercise for one deployment following this guide. With practice, you'll be able to tweak probes with confidence and keep your services running smoothly.
Now, go ahead and apply these principles to your own clusters, and build a more resilient Kubernetes environment.