avatarIvan Franchin

Summary

The provided content is a comprehensive guide on deploying a reactive Spring WebFlux application, Book API, with MongoDB as its database, within a local Minikube (Kubernetes) environment.

Abstract

The article details the process of setting up a local Kubernetes environment using Minikube and deploying a reactive Spring Boot application, known as Book API, alongside a MongoDB database instance. It covers the necessary prerequisites, including Java 17+, Docker, Minikube, Kubectl, and VirtualBox. The guide explains how to add Actuator for health checks, configure liveness and readiness probes, and create Kubernetes deployment YAML files for both the MongoDB database and the Book API application. It also demonstrates how to build and deploy the Docker image of the Book API within Minikube, test the application's endpoints, and finally, shut down the Minikube environment. The article aims to provide developers with a step-by-step approach to running a reactive application in a Kubernetes setup, ensuring that the application is healthy and ready to handle requests.

Opinions

  • The author emphasizes the importance of Kubernetes in managing the health of applications by using readiness and liveness probes.
  • The use of Minikube for local Kubernetes development is recommended for its simplicity and ease of setup.
  • The article suggests that using the Actuator tool is beneficial for monitoring the health and status of the application.
  • The author provides a positive outlook on the use of Kubernetes services and deployments for exposing and scaling applications.
  • The step-by-step approach to testing the Book API endpoints is presented as a practical method to verify the application's functionality in a Kubernetes environment.
  • The author encourages reader engagement and support by inviting them to clap, share, follow on social media, and subscribe to a newsletter.

Running in Minikube (Kubernetes) a Reactive App that uses Spring WebFlux and MongoDB

Step-by-step guide on how to run Book API in Minikube (Kubernetes)

Photo by Paul Teysen on Unsplash

In this article, we will demonstrate how to locally set up Minikube (Kubernetes) on our machines and deploy, within it, an instance of a Spring Boot Reactive application called Book API. Additionally, we’ll show you how to deploy an instance of the MongoDB database in Minikube, which the Book API relies on for storage.

You can find the complete code and implementation of Book API in the article linked below. Feel free to follow the steps explained in the article and get started.

So, let’s get started!

Prerequisites

To follow along with this guide, beside Java 17+ and Docker, please ensure that you have the Minikube, Kubectl and VirtualBox installed on your machine.

Updating Book API App

When we use Kubernetes to control our apps, it takes care of keeping the pods healthy. For example, it makes sure our apps only start handling requests when they’re ready. If a pod’s main process stops working, Kubernetes restarts the container.

To do this job, Kubernetes uses two probes: readiness and liveness. The readiness probe checks if an app is ready to get requests. The liveness probe checks if a pod is still going. This helps decide when to restart a container.

Now, let’s add the Actuator tool and enable the liveness and readiness probes.

Add the Actuator Dependency

In the pom.xml file, let’s include the Actuator dependency by adding the following code (highlighted in bold):

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" ...>
    ...
    <dependencies>
        ...
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        ...
    </dependencies>
    ...
</project>

It was added because it provides built-in endpoints for checking the application’s health, including specific ones for liveness and readiness probes.

Enable the Liveness and Readiness Probes

In the application.properties, let’s enable the liveness and readiness probes by adding the following code (highlighted in bold):

management.endpoint.health.probes.enabled=true

Creating YAML Deployment files

Create k8s folder

Inside the book-api root folder, let’s create a folder called k8s.

Create MongoDB YAML Deployment file

Inside the k8s folder, let’s create a file named mongodb.yaml and include the following content:

apiVersion: v1
kind: Service
metadata:
  name: mongodb
  labels:
    app: mongodb
spec:
  type: ClusterIP
  ports:
    - port: 27017
  selector:
    app: mongodb
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: mongodb
  labels:
    app: mongodb
spec:
  replicas: 1
  selector:
    matchLabels:
      app: mongodb
  template:
    metadata:
      labels:
        app: mongodb
    spec:
      containers:
        - name: mongodb
          image: mongo:7.0.4
          ports:
            - containerPort: 27017

This YAML file sets up a mongodb service and deployment. The service makes the database accessible within the cluster via ClusterIP, and the deployment ensures that the specified MongoDB image is run within a pod with the given configuration.

Create Book API YAML Deployment file

Inside the k8s folder, let’s create the book-api.yaml with the content below:

apiVersion: v1
kind: Service
metadata:
  name: book-api
  labels:
    app: book-api
spec:
  type: LoadBalancer
  ports:
    - name: http
      port: 8080
      targetPort: 8080
  selector:
    app: book-api
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: book-api
spec:
  replicas: 1
  selector:
    matchLabels:
      app: book-api
  template:
    metadata:
      labels:
        app: book-api
    spec:
      containers:
        - name: book-api
          image: book-api:0.0.1-SNAPSHOT
          imagePullPolicy: Never
          ports:
            - name: http
              containerPort: 8080
          env:
            - name: MONGODB_HOST
              value: mongodb
            - name: MONGODB_PORT
              value: "27017"
          livenessProbe:
            httpGet:
              path: /actuator/health/liveness
              port: http
          readinessProbe:
            httpGet:
              path: /actuator/health/readiness
              port: http

This YAML file sets up a Book API service and deployment. The service is a LoadBalancer, exposing the port 8080 for external access. The deployment creates a single pod with the book-api:0.0.1-SNAPSHOT image and configuration, connecting to a MongoDB database. The configuration includes liveness and readiness probes.

Start Environment

In a terminal, make sure you are in the book-api root folder.

Start Minikube

Run the following command to start Minikube:

minikube start --memory=8192 --cpus=2 --vm-driver=virtualbox

Create dev namespace

Once Minikube is up and running, let’s create a namespace called dev. For it, run the command below:

kubectl create namespace dev

To delete the dev namespace, run: kubectl delete namespace dev

Deploy MongoDB

Let’s deploy MongoDB by running the following command:

kubectl -n dev apply -f k8s/mongodb.yaml

To delete the mongodb deployment, run: kubectl -n dev delete -f k8s/mongodb.yaml

Watching Deployment

We can watch the MongoDB deployment by running the following command:

kubectl -n dev get pods -w

To stop watching, press: Ctrl+C

Please be patient as MongoDB Docker image will be pulled before we can proceed further. After a few seconds, the MongoDB instance should be up and running. To confirm this, you can use the following command:

kubectl -n dev get pods

You should see something like:

NAME                       READY   STATUS    RESTARTS   AGE
mongodb-65f498b766-2t2mm   1/1     Running   0          114s

Building Book API Docker image

In a terminal, let’s execute the following command to sets up our local Docker environment to use Minikube’s Docker daemon:

eval $(minikube docker-env)

Make sure you are in the book-api root folder. To build the Book API Docker image, run the following command:

./mvnw clean spring-boot:build-image -DskipTests

After the completion of the above command, the Book API Docker image will be available within Minikube. You can verify this by executing the following command:

docker images

Let’s switch back to our local host Docker daemon by running the command below:

eval $(minikube docker-env -u)

Deploying Book API

In a terminal, ensure that you are in the book-api root folder. Then, execute the following command to deploy the Book API:

kubectl -n dev apply -f k8s/book-api.yaml

To delete the book-api deployment, run: kubectl -n dev delete -f k8s/book-api.yaml

After a few seconds, the Book API instance should be up and running. To confirm this, you can use the following command:

kubectl -n dev get pods -l app=book-api

You should see something like:

NAME                        READY   STATUS    RESTARTS   AGE
book-api-559ddd9bcd-dl52h   1/1     Running   0          13s

Testing Endpoints

In a terminal, run the following command to get the BOOK_API_HOST_PORT:

BOOK_API_HOST_PORT="$(minikube ip):$(kubectl get services -n dev book-api -o go-template='{{(index .spec.ports 0).nodePort}}')"
echo $BOOK_API_HOST_PORT

Let’s retrieve all books:

curl -i $BOOK_API_HOST_PORT/api/books

As there is no book registered, we should get:

HTTP/1.1 200 OK
transfer-encoding: chunked
Content-Type: application/x-ndjson

Let’s create a book:

curl -i -X POST $BOOK_API_HOST_PORT/api/books \
  -H 'Content-Type: application/json' \
  -d '{"title": "Spring in Action", "author": "Craig Walls and Ryan Breidenbach", "year": 1005}'

It should return:

HTTP/1.1 201 Created
Content-Type: application/json
...
{"id":"657992b3a1e4811acc14e2b7","title":"Spring in Action","author":"Craig Walls and Ryan Breidenbach","year":1005}

Note: In my case, the book ID is 657992b3a1e4811acc14e2b7. For you, it will be different.

In order to facilitate the writing of this article, we will export to an environment variable the book ID. For it, run the following command in the terminal where you are performing the calls to Book API endpoints:

BOOK_ID=<the-created-book-id>

Again, let’s retrieve all books:

curl -i $BOOK_API_HOST_PORT/api/books

This time, it should return:

HTTP/1.1 200 OK
transfer-encoding: chunked
Content-Type: application/x-ndjson

{"id":"657992b3a1e4811acc14e2b7","title":"Spring in Action","author":"Craig Walls and Ryan Breidenbach","year":1005}

Let’s update the book year, as it should be 2005 and not 1005:

curl -i -X PATCH $BOOK_API_HOST_PORT/api/books/$BOOK_ID \
  -H 'Content-Type: application/json' \
  -d '{"year": 2005}'

We should get:

HTTP/1.1 200 OK
Content-Type: application/json
...
{"id":"657992b3a1e4811acc14e2b7","title":"Spring in Action","author":"Craig Walls and Ryan Breidenbach","year":2005}

Let’s retrieve the book:

curl -i $BOOK_API_HOST_PORT/api/books/$BOOK_ID

We should get as response:

HTTP/1.1 200 OK
Content-Type: application/json
...
{"id":"657992b3a1e4811acc14e2b7","title":"Spring in Action","author":"Craig Walls and Ryan Breidenbach","year":2005}

Finally, let’s delete the book:

curl -i -X DELETE $BOOK_API_HOST_PORT/api/books/$BOOK_ID

The response should be:

HTTP/1.1 200 OK
Content-Type: application/json
...
{"id":"657992b3a1e4811acc14e2b7","title":"Spring in Action","author":"Craig Walls and Ryan Breidenbach","year":2005}

In case, we try to retrieve a book that does not exist:

curl -i $BOOK_API_HOST_PORT/api/books/$BOOK_ID

The following response should be returned:

HTTP/1.1 404 Not Found
Content-Type: application/json
...
{"timestamp":"2023-12-13T11:19:06.586+00:00","path":"/api/books/657992b3a1e4811acc14e2b7","status":404,"error":"Not Found","requestId":"b6260034-7"}

Shutdown

In a terminal, run the following command to delete completely Minikube:

minikube delete

Conclusion

In this article, we have walked through the steps of configuring Minikube for local Kubernetes development. Before deploying the Book API, we added the Actuator dependency and enabled its liveness and readiness probes.

In Minikube, we deployed a single instance of the Book API Reactive app, setting up a MongoDB database as the storage backend. At the end, we test the application endpoints to certify that it is running as expected.

Additional Readings

Support and Engagement

If you enjoyed this article and would like to show your support, please consider taking the following actions:

  • 👏 Engage by clapping, highlighting, and replying to my story. I’ll be happy to answer any of your questions;
  • 🌐 Share my story on Social Media;
  • 🔔 Follow me on: Medium | LinkedIn | Twitter | GitHub;
  • ✉️ Subscribe to my newsletter, so you don’t miss out on my latest posts.
Kubernetes
Minikube
Spring Boot
Reactive
Technology
Recommended from ReadMedium