Health Checks for Spring Boot Apps in Kubernetes
Ensuring application availability is paramount in modern distributed cloud environments. Kubernetes provides a reliable mechanism for monitoring application health through readiness and liveness probes. These probes assist in detecting issues early, preventing them from affecting service availability. Coupled with Spring Boot’s Actuator health capabilities, these tools allow developers to architect robust services that are self-healing and adaptive.
This article explains how to set up and optimize health checks for Spring Boot applications deployed in Kubernetes, detailing their purpose, implementation, and best practices.
Purpose of Readiness and Liveness Probes
Kubernetes uses health probes to determine the operational state of a Pod. These probes ensure that workloads remain stable and accessible, offering the following functionalities:
- Readiness Probe
Ensures the application is ready to serve requests.
- When failing, the Pod is removed from the service’s Endpoints, stopping traffic routing to it.
- Liveness Probe
Confirms whether the application is alive and responsive.
- When failing, Kubernetes restarts the Pod to recover from failure states like deadlocks or extensive resource starvation.
By combining these probes, Kubernetes can dynamically maintain service reliability while optimizing deployments.
Real-World Scenario Illustrations:
- Readiness Probe: A service loading large configuration files on startup should not receive traffic until initialization completes.
- Liveness Probe: An application stuck in an infinite loop or consuming excessive memory can be restarted upon failure detection.
Enabling Actuator Endpoints (/health)
Spring Boot Actuator simplifies health monitoring by exposing REST APIs like /actuator/health
. These endpoints provide system-level health information and integrate seamlessly with Kubernetes health probes.
Step 1. Add the Actuator Dependency
Include the Spring Boot Actuator module in your pom.xml
:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency>
Step 2. Expose the /health
Endpoint
Configure the Actuator endpoint in application.properties
or application.yml
:
management: endpoints: web: exposure: include: health
Verify:
curl http://<host>:<port>/actuator/health
Typical response:
{ "status": "UP" }
With this endpoint enabled, you can integrate it into Kubernetes probes.
Adding Readiness and Liveness Probes in YAML
Kubernetes health probes are defined within deployment YAML files. Both HTTP and command-based checks are supported.
Example YAML for a Spring Boot Deployment:
apiVersion: apps/v1 kind: Deployment metadata: name: springboot-app spec: replicas: 2 template: spec: containers: - name: springboot-container image: springboot-app-image readinessProbe: httpGet: path: /actuator/health/readiness port: 8080 initialDelaySeconds: 10 periodSeconds: 5 livenessProbe: httpGet: path: /actuator/health/liveness port: 8080 initialDelaySeconds: 15 periodSeconds: 5
Key Configurations:
initialDelaySeconds
: Wait time before the first check after Pod startup.periodSeconds
: Frequency of probe execution.httpGet.path
: Actuator or custom health endpoint path.
These probes ensure the workload transitions smoothly between states during startup and operation.
Customizing Health Checks (DB, Queue Connections, etc.)
Spring Boot Actuator supports customizable health indicators, allowing health checks beyond system status. For example, you can monitor:
- Database connectivity.
- Queue status (e.g., RabbitMQ, Kafka).
- External system availability (e.g., third-party APIs).
Adding a Database Health Check:
Include the database driver dependency (e.g., for MySQL):
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency>
Spring Boot automatically integrates database connectivity into its default health check. The /actuator/health
response will include:
{ "status": "UP", "components": { "db": { "status": "UP", "details": { "database": "MySQL", "validationQuery": "isValid()" } } } }
Writing a Custom Health Indicator:
For applications needing specific operational checks, implement the HealthIndicator
interface:
@Component public class QueueHealthIndicator implements HealthIndicator { @Override public Health health() { boolean queueUp = checkQueueStatus(); // Custom logic return queueUp ? Health.up().build() : Health.down().withDetail("Error", "Queue not reachable").build(); } }
This adds the QueueHealthIndicator
details to /actuator/health
.
Testing Health Checks by Failing a Pod
Intentional failure testing verifies resilience and probe correctness. Simulate failures with scenarios like:
- Artificial Overload: Consume excess CPU to trigger liveness probe failure.
- Database Disconnects: Stop the database service and observe readiness probe behavior.
Use:
kubectl describe pod <pod-name>
Inspect the Conditions
and Events
for probe failures.
Example:
Readiness probe failed: HTTP GET http://10.0.0.1/actuator/health/readiness status code 503
A failed readiness probe halts traffic dispatch to this Pod.
The Impact of Failed Checks on Service Availability
When a health probe fails:
- Liveness Probe Failure: Kubernetes restarts the Pod.
- Readiness Probe Failure: The Pod stops receiving traffic until healthy.
Failed liveness checks address corrupted Pods, while readiness checks ensure users aren’t exposed to unhealthy Pods.
Best Practices:
- Avoid aggressive restart loops with high
initialDelaySeconds
. - Use appropriate thresholds to avoid false negatives.
Best Practices for Robust Probe Setup
- Separate Readiness and Liveness Checks: Use targeted endpoints to differentiate between long initialization processes and runtime stability.
- Use Graceful Timeouts: Tune
periodSeconds
andtimeoutSeconds
to match service startup/response times. - Integrate with Monitoring Tools: Correlate probe failures with dashboard alerts in tools like Grafana or Prometheus.
For readiness checks, ensure environmental dependencies (like DBs) are fully monitored before marking the service as operational.
FAQ
What is the difference between readiness and liveness probes?
- Readiness Probe: Verifies if a Pod is ready to accept traffic.
- Liveness Probe: Checks if the application is alive and permits restart if unresponsive.
What happens if all readiness probes fail in a deployment?
Kubernetes removes failing Pods from the Endpoint list, redirecting traffic to healthy Pods only.
How do I test the behavior of failed probes?
Manually stop dependencies (e.g., databases), simulate load spikes, or send traffic to unresponsive endpoints to observe failed probe handling.
Can both probes reference the same endpoint?
Yes, but separating checks for specific behaviors (e.g., /readiness
for dependencies, /liveness
for application state) is a better practice.
How does Spring Boot Actuator help with probes?
Actuator provides built-in and customizable endpoints like /health/readiness
, enabling targeted health checks that integrate with Kubernetes.
By following these configurations and best practices, you can enhance the resilience and reliability of your Spring Boot services deployed on Kubernetes.