Enterprise Java

Self-Healing Microservices: Implementing Health Checks with Spring Boot and Kubernetes

Building resilient microservices isn’t just about writing fault-tolerant code—it’s about creating systems that can detect failures and recover automatically. This is the core idea behind self-healing microservices.

In this article, you’ll learn how to:

  • Implement liveness and readiness probes in Spring Boot.
  • Create custom health indicators using Spring Actuator.
  • Configure Kubernetes for auto-restart and traffic control.
  • Debug and troubleshoot health check issues.

Let’s get started.

1. Why Self-Healing Matters

Failures are inevitable in distributed systems. Network timeouts, memory leaks, thread deadlocks, or even simple bugs can bring down a service. The goal is not to prevent all failures but to detect and recover gracefully, minimizing downtime.

Kubernetes, combined with Spring Boot’s Actuator health endpoints, provides a robust foundation for this.

2. Liveness vs Readiness Probes

ProbePurposeEffect on Pod
LivenessChecks if the app is alive. If not, Kubernetes restarts the pod.Pod is restarted.
ReadinessChecks if the app is ready to handle traffic. If not, Kubernetes removes it from the load balancer.Traffic stops flowing to the pod.

Step 1: Add Spring Boot Actuator

Start by adding Spring Boot Actuator to expose health endpoints:

<!-- pom.xml -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

Step 2: Configure Actuator Endpoints

In application.yml, expose liveness and readiness:

management:
  endpoints:
    web:
      exposure:
        include: health, info
  endpoint:
    health:
      probes:
        enabled: true

By setting probes.enabled: true, Spring Boot automatically exposes:

  • /actuator/health/liveness
  • /actuator/health/readiness

Step 3: Define Kubernetes Probes

Here’s how to configure Kubernetes probes in your Deployment YAML:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-service
spec:
  replicas: 3
  selector:
    matchLabels:
      app: my-service
  template:
    metadata:
      labels:
        app: my-service
    spec:
      containers:
      - name: my-service
        image: my-service:latest
        ports:
        - containerPort: 8080
        livenessProbe:
          httpGet:
            path: /actuator/health/liveness
            port: 8080
          initialDelaySeconds: 10
          periodSeconds: 15
        readinessProbe:
          httpGet:
            path: /actuator/health/readiness
            port: 8080
          initialDelaySeconds: 5
          periodSeconds: 10

Step 4: Add Custom Health Indicators

Sometimes the default probes aren’t enough. You may need to check:

  • Database connectivity
  • External service availability
  • Message queue readiness

Create a custom health indicator:

import org.springframework.boot.actuate.health.Health;
import org.springframework.boot.actuate.health.HealthIndicator;
import org.springframework.stereotype.Component;

@Component
public class DatabaseHealthIndicator implements HealthIndicator {

    @Override
    public Health health() {
        boolean dbUp = checkDatabase();
        if (dbUp) {
            return Health.up().withDetail("database", "Available").build();
        } else {
            return Health.down().withDetail("database", "Unavailable").build();
        }
    }

    private boolean checkDatabase() {
        // Simulate DB check
        return true; // Replace with real logic
    }
}

Step 5: Auto-Restart Logic with Kubernetes

Once Kubernetes detects a liveness failure, it automatically:

  • Sends a SIGTERM
  • Waits for graceful shutdown (default 30s)
  • Kills the container and restarts it

This reduces the need for manual intervention.

Common failure scenarios handled automatically:

FailureHandled by
DeadlocksLiveness probe restart
Out-of-memory crashK8s OOM killer + restart
Downstream service crashReadiness probe pause traffic

3. Debugging and Troubleshooting

  1. Check logs
kubectl logs my-service-pod

2. Describe pod for probe errors

kubectl describe pod my-service-pod

Look for:

  • Last State: Terminated
  • Reason: Probe failed
  • Events: sections
  1. Manually test probes
curl http://localhost:8080/actuator/health/liveness
curl http://localhost:8080/actuator/health/readiness

Step 6: Use Spring Boot Graceful Shutdown

To avoid abrupt shutdowns during restarts, enable graceful shutdown:

server:
  shutdown: graceful

spring:
  lifecycle:
    timeout-per-shutdown-phase: 30s

Override DisposableBean or @PreDestroy to clean up resources.

4. Useful Links & Resources

5. Final Thoughts

Self-healing microservices are critical for resilient architectures. By combining Spring Boot Actuator health checks with Kubernetes liveness/readiness probes, you can:

  • Minimize downtime
  • Detect failures early
  • Let Kubernetes handle automatic recovery

This approach leads to systems that heal themselves, requiring less human intervention and ensuring higher availability.

Eleftheria Drosopoulou

Eleftheria is an Experienced Business Analyst with a robust background in the computer software industry. Proficient in Computer Software Training, Digital Marketing, HTML Scripting, and Microsoft Office, they bring a wealth of technical skills to the table. Additionally, she has a love for writing articles on various tech subjects, showcasing a talent for translating complex concepts into accessible content.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Oldest
Newest Most Voted
Back to top button