Lab2 (Spring Boot/K8S): Kubernetes health probes with Spring Boot

Hello Devs! In this post, we’ll show how Kubernetes checks a Spring boot application’s health.

· Overview
∘ Probes Check mechanisms
∘ Probe outcome
∘ Types of probe
· How does it work with Spring Boot?
∘ Spring Boot Actuator
∘ Kubernetes deployment
∘ Deploy the container image to Kubernetes
· Conclusion
· References

This series of stories shows how to use Kubernetes in the Spring ecosystem. We work with a Spring boot API and Minikube to have a lightweight and fast development environment similar to production.

In the previous lab, we containerized and deployed a Spring Boot API to a Kubernetes cluster using Minikube. In this story, we’ll look at how to configure our Spring Boot API to use Kubernetes Probes.

Overview

Health checks are a way to query the status of the running application, such as whether the service is slow or unavailable.

Kubernetes probes are a diagnostic performed periodically by the kubelet on a container. kubelet runs code in the container or makes a network request to perform this diagnosis.

Probes Check mechanisms

There are four different ways to check a container using a probe. Each probe must define exactly one of these four mechanisms:

  • exec

Executes a specified command inside the container. The diagnostic is considered successful if the command exits with a status code of 0.

  • grpc

Performs a remote procedure call using gRPC. The target should implement gRPC health checks. The diagnostic is considered successful if the status of the response is SERVING.

  • httpGet

Performs an HTTP GET request against the Pod’s IP address on a specified port and path. The diagnostic is considered successful if the response has a status code greater than or equal to 200 and less than 400.

  • tcpSocket

Performs a TCP check against the Pod’s IP address on a specified port. The diagnostic is considered successful if the port is open. If the remote system (the container) closes the connection immediately after it opens, this counts as healthy.

Probe outcome

Each probe has one of three results:

  • Success

The container passed the diagnostic.

  • Failure

The container failed the diagnostic.

  • Unknown

The diagnostic failed (no action should be taken, and the kubelet will make further checks).

Types of probe

  • livenessProbe

Indicates whether the container is running. If the liveness probe fails, the kubelet kills the container, and the container is subjected to its restart policy. If a container does not provide a liveness probe, the default state is Success.

  • readinessProbe

Indicates whether the container is ready to respond to requests. If the readiness probe fails, the endpoints controller removes the Pod’s IP address from the endpoints of all Services that match the Pod. The default state of readiness before the initial delay is Failure. If a container does not provide a readiness probe, the default state is Success.

  • startupProbe

Indicates whether the application within the container is started. All other probes are disabled if a startup probe is provided until it succeeds. If the startup probe fails, the kubelet kills the container, and the container is subjected to its restart policy. If a container does not provide a startup probe, the default state is Success.

How does it work with Spring Boot?

Spring Boot includes out-of-the-box support for the commonly used “liveness” and “readiness” availability states. If you are using Spring Boot’s “actuator” support then these states are exposed as health endpoint groups.

Now let’s clone the main Spring boot project with lab1 configuration.

$ git clone https://github.com/anicetkeric/spring-boot-k8s.git -b lab1

Spring Boot Actuator

Add the actuator to the pom.xml file.

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

Then, in the application.yaml file, we need to enable probes:


management:
endpoint:
health:
show-details: always
show-components: always
probes:
enabled: true
health:
livenessState:
enabled: true
readinessState:
enabled: true
endpoints:
web:
exposure:
include: ['env', 'health', 'info']

The liveness endpoint will be exposed at/actuator/health/liveness and the readiness at /actuator/health/readiness.

As we can see, the actuator configuration works well.

Kubernetes deployment

We can then configure the Kubernetes infrastructure with the following endpoint information:

livenessProbe:
httpGet:
path: "/actuator/health/liveness"
port: <actuator-port>
failureThreshold: ...
periodSeconds: ...
readinessProbe:
httpGet:
path: "/actuator/health/readiness"
port: <actuator-port>
failureThreshold: ...
periodSeconds: ...

<actuator-port> should be set to the port that the actuator endpoints are available on. It could be the main web server port or a separate management port if the "management.server.port" property has been set.

We need to include these probes in our Kubernetes deployment:

apiVersion: v1
kind: Service
metadata:
name: book-api-service
spec:
selector:
app: backend
ports:
- protocol: TCP
port: 8081
targetPort: 8080
type: NodePort
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: backend-book-api
spec:
replicas: 2
selector:
matchLabels:
app: backend
environment: dev
template:
metadata:
labels:
app: backend
environment: dev
spec:
containers:
- name: book-api
image: spring-boot-k8s:latest
ports:
- containerPort: 8080
imagePullPolicy: Never
livenessProbe:
httpGet:
path: /actuator/health/liveness
port: 8080
initialDelaySeconds: 15
periodSeconds: 5
timeoutSeconds: 2
failureThreshold: 1
readinessProbe:
httpGet:
path: /actuator/health/readiness
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
timeoutSeconds: 2
failureThreshold: 1
  • initialDelaySeconds: Number of seconds after the container has started before startup, liveness, or readiness probes are initiated. If a startup probe is defined, liveness and readiness probe delays do not begin until the startup probe has succeeded. If the value of periodSeconds is greater than initialDelaySeconds then the initialDelaySeconds would be ignored. Defaults to 0 seconds. The minimum value is 0.
  • periodSeconds: How often (in seconds) to perform the probe. Default to 10 seconds. The minimum value is 1.
  • timeoutSeconds: Number of seconds after which the probe times out. Defaults to 1 second. The minimum value is 1.
  • successThreshold: Minimum consecutive successes for the probe to be considered successful after having failed. Defaults to 1. Must be 1 for liveness and startup Probes. The minimum value is 1.
  • failureThreshold: After a probe fails failureThreshold times in a row, Kubernetes considers that the overall check has failed: the container is not ready/healthy/live. In the case of a startup or liveness probe, if at least failureThreshold probes have failed, Kubernetes treats the container as unhealthy and triggers a restart for that specific container. The kubelet honors the setting of terminationGracePeriodSeconds that container. For a failed readiness probe, the kubelet continues running the container that failed checks, and also continues to run more probes; because the check failed, the kubelet sets the Ready condition on the Pod to false.
  • terminationGracePeriodSeconds: configure a grace period for the kubelet to wait between triggering a shutdown of the failed container, and then forcing the container runtime to stop that container. The default is to inherit the Pod-level value for terminationGracePeriodSeconds (30 seconds if not specified), and the minimum value is 1. See probe-level terminationGracePeriodSeconds for more details.

Deploy the container image to Kubernetes

Now we are ready to deploy this app to Kubernetes.

$ kubectl apply -f k8s.yaml

service/book-api-service created
deployment.apps/backend-book-api created

Check that the application is running:

$ kubectl get pods
$ kubectl logs backend-book-api-68c85b6ff5–5sjk2

kubelet will check for the liveness and readiness probe every 5 seconds.

Conclusion

Well done !!. In this post, we have seen how to use Spring’s Actuator to improve our application’s health monitoring with Kubernetes.

The complete source code of this series is available on GitHub.

You can reach out to me and follow me on MediumTwitterGitHubLinkedln

Support me through GitHub Sponsors.

Thanks for reading!

References

👉 Link to Medium blog

Related Posts