DEV Community

Maroun Maroun
Maroun Maroun

Posted on

Hello, K8s Spring Boot!

Let's try to build the simplest Java Spring application that runs as a pod in a Kubernetes cluster.

The full project can be found on my GitHub.

The project's structure:

├── Dockerfile
├── build.gradle
├── gradle
│   └── wrapper
│       ├── gradle-wrapper.jar
│       └──
├── gradlew
├── k8s
│   └── depl.yaml
├── settings.gradle
└── src
    └── main
        └── java
            └── hello
                └── is our entry point:

package hello;

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

public class App {

    public static void main(String[] args) {, args);


and our controller simply returns "hello world" on the root path:

package hello;

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

public class HelloWorldCtrl {

    public String index() {
        return "Greetings from Spring Boot!";


Now let's write a Dockerfile:

FROM gradle:jdk10 as builder

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


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

It uses Gradle in order to build the application, and the CMD instruction runs the JAR file.

The K8s deployment is simple. It consists of a deployment and a service:

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

The deployment defines two replicas of the pod that will be running the container that's built from the image specified in the image attribute.

The service is of type ClusterIP (the default Kubernetes service). It gives us a service inside our cluster that other apps can access.

Creating the resources in your cluster:

kubectl create -f <yaml_file>

The resources can be visualized as follows:

| hello-world-service |
|                     |
|    |
                        |                          |
              +---------O-----------+    +---------O-----------+
              |        pod 1        |    |        pod 2        |
              |                     |    |                     |
              |     hello-world     |    |     hello-world     |
              +---------------------+    +---------------------+

Inside The Cluster

If you're using minikube for running the cluster locally, you might encounter issues (I really don't know why). But if you're running on a cloud provider, or something more "serious" than minikube, you should be able to do the following:

$ 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   <none>        8080/TCP   5s
kubernetes            ClusterIP     <none>        443/TCP    7h
$ kubectl exec -it hello-world-5bb87c95-6h4kh bash
$ (inside the pod) curl
$ (inside the pod) Greetings from Spring Boot!

If you have any questions, please drop a comment.

Discussion (0)