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:

  1. 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.
  1. 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:

  1. Artificial Overload: Consume excess CPU to trigger liveness probe failure.
  2. 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

  1. Separate Readiness and Liveness Checks: Use targeted endpoints to differentiate between long initialization processes and runtime stability.
  2. Use Graceful Timeouts: Tune periodSeconds and timeoutSeconds to match service startup/response times.
  3. 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.

Similar Posts