Deploying a Spring Boot Application with MySQL Database on Kubernetes

Welcome to day 34-35 of the #90DaysOfDevOps challenge initiated by Shubham Londhe . In my previous blogs, I have shared what are pods, deployments and services. So, we will implement that knowledge in today's blog post, we'll deploy a Spring Boot application with a database on Kubernetes. Let's get started!

Prerequisites: Before we begin, make sure you have the following:

  1. Amazon Linux 2 instance with t2.medium

  2. A Docker Hub account (if you don't have one, create it at hub.docker.com)

  3. Go through the manifest files present in the repository to understand more about pods, services, deployments and PVC.

Let's get started!

Step 1: Launch an instance from an Amazon Linux 2 with t2.medium.

Step 2: Connect to your instance.

Step 3: Update the packages and package caches we have installed on the instance.

sudo su
yum update -y

Step 4: Install the latest Docker Engine packages and start the Docker service.

amazon-linux-extras install docker  OR 
yum install docker -y

Using the amazon-linux-extras install docker command is a convenient and reliable way to install Docker on an Amazon Linux 2 instance, as it takes care of the necessary installation steps and ensures compatibility with the Amazon Linux 2 environment. So, I am using this as follows.

To check whether docker is properly installed or not, use the following command.

docker -v

Start the Docker service.

systemctl start docker
systemctl enable docker

Step 5: Install Conntrack and git.

Why do we need Conntrack to install Docker?

Docker heavily relies on Conntrack for its networking features. Conntrack ensures that Docker can accurately track and manage the network connections established by containers, enabling seamless communication between containers and the external network.

Without Conntrack, Docker's networking capabilities would be severely limited, leading to issues with container communication and network connectivity.

yum install conntrack -y

On completion, it will look like this and pop up as complete!

Confirm the installation by running the following command.

conntrack --version

Step 6: Install k8s through Minikube and configure kubctl to use the Minikube cluster.

i. Download the latest version of Minikube for the Linux platform.

curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64

And yes, as we can see below, minikube is downloaded successfully.

ii. Install the downloaded Minikube.

install minikube-linux-amd64 /usr/local/bin/minikube

iii. Start the installed Minikube.

/usr/local/bin/minikube start --force --driver=docker

Let's break down the command and understand its components:

  1. /usr/local/bin/minikube: This is the path to the Minikube binary executable file. The exact location of the Minikube binary may vary depending on your system configuration. In this case, it is located at /usr/local/bin/minikube.

  2. start: This command is used to start Minikube and initialize a Kubernetes cluster.

  3. --force: This flag is used to force the start of Minikube, even if there are existing instances of Minikube running. It ensures that Minikube starts fresh, overriding any previous state.

  4. --driver=docker: This flag specifies the driver to use for Minikube. In this case, the docker driver is selected. The docker driver sets up a Kubernetes cluster using Docker containers as the underlying runtime environment.

By running this command, Minikube will be started with the docker driver, creating a Kubernetes cluster that runs on a local machine. The --force flag ensures a clean start, and Minikube will begin setting up the required components to run Kubernetes and manage containerized applications.

As the installation is done, we check Minikube version as follows.

/usr/local/bin/minikube version

iv. Download and install the kubectl

Downloading kubectl with the following command.

curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"

Great, now install the kubectl and check it's version.

install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl 
/usr/local/bin/kubectl version

Step 7: Install the git and clone the repository.

Install git:

yum install git -y

Now, change the working directory and clone the git reposotory.

cd /opt/ 
git clone https://github.com/ShubhamBMatere/springboot-k8s.git

We can observe that the repository is cloned as springboot-k8s

Step 8: Set Up the MySQL Database.

We will change the directory to move inside the cloned repository.

Here, we can observe we have db-deployment.yaml file is present. If you go through this manifest file, the file includes the following configurations

  1. The persistent volume of claims (PVC)

  2. Deployment configurations for MySQL DB.

  3. MySQL service.

cd springboot-k8s
/usr/local/bin/kubectl create -f db-deployment.yaml
/usr/local/bin/kubectl get pods

Now we will check the database pod with help of shell command and Enter the DB. So, to enter inside the database, we will need a username(root) and password (root) which we'll provide as follows. Remember password to interact with DB is root which need to enter once you hit following command.

/usr/local/bin/kubectl exec -it <POD NAME> -- sh
mysql -u root -p

Take the exit from the pod now by putting exit.

Step 9: Install Maven

Maven is a build automation tool that helps manage project dependencies, compile source code, and package the application into a deployable artifact (e.g., JAR or WAR). It ensures that the application and its dependencies are properly resolved and packaged, allowing for smooth deployment and integration with Docker and Kubernetes.

yum install maven -y 
mvn -v

Step 10: Create and push the docker image of the Spring Boot application to Docker Hub.

Navigate to the root directory of your Spring Boot application and use the following command.

docker build -t <dockerhub_username>/<image_name>:<tag> .

This command builds a Docker image with the tag shubhambmatere/springboot-crud-k8s:1.0 using the current directory as the build context.

So, to build an image, it will look for Dockerfile in the directory.

Now, Check the docker images whether it is created or not.

Now, log in and push the Docker image to Docker Hub. To log in you have to enter your Docker Hub credentials.

docker login 
docker push <dockerhub_username>/<image_name>:<tag>

Now, Check on DockerHub if the image is pushed and yes, it's created.

Step 11. Apply the Deployment and Run Services

As we can see, we already have a Kubernetes deployment file (app-deployment.yaml) with the necessary specifications for deploying the Spring Boot application and creating the services. Apply the deployment using the following command:

/usr/local/bin/kubectl  apply -f app-deployment.yaml
/usr/local/bin/kubectl  get svc

Step 12: Obtain the Minikube IP and Set Up Port Forwarding.

What is port forwarding? Port forwarding is a method of network redirection that redirects network traffic from a specific port on one host to another port on a different host or the same host. In the context of Kubernetes, port forwarding enables accessing services running within a Kubernetes cluster from a local machine or a remote host.

/usr/local/bin/minikube ip 
/usr/local/bin/kubectl port-forward --address 0.0.0.0 svc/springbootcrud-svc 8080:8080 &

For example, if my service is named app and is listening on 80

kubectl port-forward --address 0.0.0.0 svc/app 8888:80

/usr/local/bin/kubectl port-forward --address 0.0.0.0 svc/app 8888:80

The command I used is explained as /usr/local/bin/kubectl port-forward --address 0.0.0.0 svc/springbootcrud-svc 8080:8080 &

It forwards network traffic from all available network interfaces (0.0.0.0) to the Kubernetes service (svc) named springbootcrud-svc, mapping port 8080 on the local machine to port 8080 on the Kubernetes service. The & at the end runs the command in the background, allowing you to continue using the terminal.

Step 13: Hitting the URL to check application is working or not.

So, to hit the URL, first, we need to open the ports of the instance by editing the inbound rules of the security group. I am opening it for all traffic.

I am using the POSTMAN application to hit the URL and store the data in DB as we don't have UI for this application for now. Note the URL.

http://<EC2IP>:8080/orders
{ 
    "name":"shoe", 
    "qty":11, 
    "price":80000 
}

Here, I am keeping the request type POST, and body as raw in JSON format. So, when I hot the URL with JSON and I got the response 200OK.

Step 14: Checking the DB to ensure entry of the above request.

First, enter into the DB pod with the shell command explained in step 7.

Use the following commands to view the table: show databese ---> use singamlabs ---> show tables ----> select * from orders_tbl

Yesss, we can see our entries in the table which means our application is working as expected. Wow, that's great.

Step 15: Accessing the Kubernetes Dashboard
The Kubernetes dashboard provides a user-friendly web-based interface for managing and monitoring Kubernetes clusters, allowing users to easily visualize and interact with pods, services, and deployments. Its key features include real-time monitoring of cluster health, resource usage visualization, and the ability to manage and troubleshoot applications within the cluster using an intuitive graphical interface.

Inside EC2 our minikube is running so we are setting a proxy for all the local addresses with the following command.

/usr/local/bin/kubectl proxy --address='0.0.0.0' --accept-hosts='^*$'

The proxy server is started on port 8001.

Now open another terminal of the same instance as we can not stop the above proxy to access the dashboard and run the below command.

/usr/local/bin/minikube dashboard

Open a web browser and hit the following URL with your EC2 IP.

http://<EC2IP>:8001/api/v1/namespaces/kubernetes-dashboard/services/http:kubernetes-dashboard:/proxy/#/pod?namespace=default

Now, as we are on the Kubernetes dashboard, let's check the pods running.

Let's check the deployments.

Let's check the services running.

Let's check the PVC-Persistent Volume Claims

Also, we can the logs of application.

And finally the workload status

In the next blog post, we will explore more advanced topics in the realm of DevOps. Also, I will be deploying more projects using K8s. So, stay tuned and let me know if there is any correction.