An example of deploying a Spring Boot application to Kubernetes

The translation of the article was prepared especially for the students of the course “Spring Framework Developer”

Let’s create a basic Spring Boot application that will run on a Kubernetes cluster.


Project structure

├── Dockerfile
├── build.gradle
├── gradle
│   └── wrapper
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── gradlew
├── k8s
│   └── depl.yaml
├── settings.gradle
└── src
   └── main
       └── java
           └── hello
               ├── App.java
               └── HelloWorldCtrl.java

App.java is the entry point for the application:

package hello;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class App {

    public static void main(String[] args) {
        SpringApplication.run(App.class, args);
    }

}

The above code is a minimal Spring Boot application.
The HelloWorldCtrl.java file contains a simple controller that maps the root (“/”) to the index method, which returns a welcome string:

package hello;

import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.RequestMapping;

@RestController
public class HelloWorldCtrl {

    @RequestMapping("/")
    public String index() {
        return "Greetings from Spring Boot!";
    }

}

Building the application

I am using Gradle to build. The build.gradle file is also minimalistic:

plugins {
   id 'org.springframework.boot' version '2.3.3.RELEASE'
   id 'io.spring.dependency-management' version '1.0.8.RELEASE'
   id 'java'
}

group = 'com.test'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '1.8'

repositories {
   mavenCentral()
}

dependencies {
   implementation 'org.springframework.boot:spring-boot-starter-web'
}

Create K8s resources

To deploy to K8s, we need a Docker image. Let’s add the following lines to the Dockerfile:

FROM gradle:jdk10

COPY --chown=gradle:gradle . /app
WORKDIR /app
RUN gradle build

EXPOSE 8080
WORKDIR /app

CMD java -jar build/libs/gs-spring-boot-0.1.0.jar

Steps in our Dockerfile:

  • copying the project to / app
  • building the project using Gradle
  • launching the application using the result of the previous step

docker build -t marounbassam/hello-spring .
docker push marounbassam/hello-spring

The K8s manifest file is simple too. It consists of a deployment (Deployment) and service (Service):

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: hello-world
spec:
  replicas: 2
  template:
    metadata:
      labels:
        app: hello-world
        visualize: "true"
    spec:
      containers:
      - name: hello-world-pod
        image: marounbassam/hello-spring
        ports:
        - containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
  labels:
    visualize: "true"
  name: hello-world-service
spec:
  selector:
    app: hello-world
  ports:
  - name: http
    protocol: TCP
    port: 8080
    targetPort: 8080
  type: ClusterIP

Deployment defines two pod replicas that will run the container created from the image specified in the image attribute.

Service has ClusterIP type (default service type). It provides within the cluster the ability to connect to us for other applications.

We create resources in the cluster:

kubectl create -f <yaml_file>

Resources can be visually represented as follows:

Inside the cluster

$ kubectl get pods
NAME                         READY     STATUS    RESTARTS   AGE
hello-world-5bb87c95-6h4kh   1/1       Running   0          7h
hello-world-5bb87c95-bz64v   1/1       Running   0          7h
$ kubectl get svc
NAME                  TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
hello-world-service   ClusterIP   10.15.242.210   <none>        8080/TCP   5s
kubernetes            ClusterIP   10.15.240.1     <none>        443/TCP    7h
$ kubectl exec -it hello-world-5bb87c95-6h4kh bash
$ (inside the pod) curl 10.15.242.210:8080
$ (inside the pod) Greetings from Spring Boot!

We can see that the server has started and is running inside the pods. You can also set up a service like LoadBalancer (depending on your cloud provider) and access the application from outside the cluster.

Conclusion

We created a simple Spring Boot application, launched it in a Docker container in the K8s pod, which is managed through K8s deployment and is available through the service.

We now have simple load balancing for the two created pods, and easy scalability according to the needs of the application.

Spring Framework Developer

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *