How to deploy a Spring Boot application on Kubernetes in 3 simple steps

In this tutorial we will learn how to install a Spring Boot application on Kubernetes using Minikube and JKube Maven plugin.

Install a Kubernetes Cluster with Minikube

Kubernetes is an open source system for managing containerized applications across multiple hosts. It provides basic mechanisms for deployment, maintenance, and scaling of applications. The simplest way to get started with Kubernetes is to install Minikube.

Minikube is a lightweight Kubernetes implementation that creates a VM on your local machine and deploys a simple cluster containing a single node and ships with a CLI that provides basic bootstrapping operations for working with your cluster, including start, stop, status, and delete

The procedure for installing Minikube is detailed at: https://minikube.sigs.k8s.io/docs/start/

To install the binary distribution you can just download it and run the “install” command on it:

$ curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64 $ sudo install minikube-linux-amd64 /usr/local/bin/minikube 

When done, launch the “minikube start“command which will select the Driver for your environment and download the Virtual Machine required to run Kubernetes components:

$ minikube start ?  minikube v1.15.1 on Fedora 29     ▪ KUBECONFIG=/home/francesco/taskforce/install/auth/kubeconfig ✨  Automatically selected the kvm2 driver ?  Downloading driver docker-machine-driver-kvm2:     > docker-machine-driver-kvm2.sha256: 65 B / 65 B [-------] 100.00% ? p/s 0s     > docker-machine-driver-kvm2: 13.56 MiB / 13.56 MiB  100.00% 1.15 MiB p/s 1 ?  Downloading VM boot image ...     > minikube-v1.15.0.iso.sha256: 65 B / 65 B [-------------] 100.00% ? p/s 0s     > minikube-v1.15.0.iso: 181.00 MiB / 181.00 MiB  100.00% 1.16 MiB p/s 2m36s ?  Starting control plane node minikube in cluster minikube ?  Downloading Kubernetes v1.19.4 preload ...     > preloaded-images-k8s-v6-v1.19.4-docker-overlay2-amd64.tar.lz4: 486.35 MiB ?  Creating kvm2 VM (CPUs=2, Memory=6000MB, Disk=20000MB) ... ?  Preparing Kubernetes v1.19.4 on Docker 19.03.13 ... ?  Verifying Kubernetes components... ?  Enabled addons: storage-provisioner, default-storageclass  ❗  /usr/local/bin/kubectl is version 1.15.3, which may have incompatibilites with Kubernetes 1.19.4.     ▪ Want kubectl v1.19.4? Try 'minikube kubectl -- get pods -A' ?  Done! kubectl is now configured to use "minikube" cluster and "default" namespace by default 

When done, verify that the default and kube-system services are available:

$ minikube service list |-------------|------------|--------------|-----| |  NAMESPACE  |    NAME    | TARGET PORT  | URL | |-------------|------------|--------------|-----| | default     | kubernetes | No node port | | kube-system | kube-dns   | No node port | |-------------|------------|--------------|-----| 

Great, you Kubernetes cluster is now up and running.

Then, in order to build the Docker image using Minikube’s Docker instance, execute:

$ eval $(minikube docker-env)

The command minikube docker-env returns a set of Bash environment variable exports to configure your local environment to re-use the Docker daemon inside the Minikube instance.

If you fail to configure your Minikube environment, you will see an error when deploying your resource: “Connection reset by peer”

Coding a sample Spring Boot application

We will deploy on Minikube a minimal Spring Boot application with just an Hello World Controller in it:

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

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

In order to deploy this Spring Boot application on Kubernetes we will use JKube.

Eclipse JKube is a collection of plugins and libraries that are used for building container images using Docker, JIB or S2I build strategies. Eclipse JKube generates and deploys Kubernetes/OpenShift manifests at compile time too.

To use JKube, just add it as Maven plugin to your project:

<?xml version="1.0" encoding="UTF-8"?><profile>
      
   <id>kubernetes</id>
      
   <build>
           
      <plugins>
                
         <plugin>
                     
            <groupId>org.eclipse.jkube</groupId>
                     
            <artifactId>kubernetes-maven-plugin</artifactId>
                     
            <version>${jkube.version}</version>
                      
            <configuration>
                           
               <resources>
                               
                  <labels>
                                    
                     <all>
                                         
                        <testProject>spring-boot-sample</testProject>
                                       
                     </all>
                                  
                  </labels>
                             
               </resources>
                           
               <generator>
                               
                  <includes>
                                    
                     <include>spring-boot</include>
                                  
                  </includes>
                               
                  <config>
                                    
                     <spring-boot>
                                         
                        <color>always</color>
                                       
                     </spring-boot>
                                  
                  </config>
                             
               </generator>
                          
               <enricher>
                               
                  <excludes>
                                    
                     <exclude>jkube-expose</exclude>
                                  
                  </excludes>
                               
                  <config>
                                    
                     <jkube-service>
                                         
                        <type>NodePort</type>
                                       
                     </jkube-service>
                                  
                  </config>
                             
               </enricher>
                        
            </configuration>
                      
            <executions>
                          
               <execution>
                               
                  <goals>
                                    
                     <goal>resource</goal>
                                    
                     <goal>build</goal>
                                    
                     <goal>helm</goal>
                                  
                  </goals>
                             
               </execution>
                        
            </executions>
                   
         </plugin>
              
      </plugins>
         
   </build>
    
</profile>

Deploying the Spring Boot application on Kubernetes

Deploying the application on Kubernetes, just requires 3 simple steps:

1) Create your Kubernetes resource descriptors.

mvn clean k8s:resource -Pkubernetes 

Then start docker build by hitting the build goal.

mvn package k8s:build -Pkubernetes 

Finally, deploy your application on the Kubernetes cluster:

mvn k8s:deploy -Pkubernetes 

Once deployed, you can see the pods running inside your Kubernetes cluster:

$ kubectl get pods NAME                           READY   STATUS    RESTARTS   AGE spring-boot--5b7d6dfb6f-2nsnm  1/1     Running   0          23s 

You can try to access your application using minikube service command like this:

$ minikube service spring-boot |-----------|-------------|-------------|----------------------------| | NAMESPACE |    NAME     | TARGET PORT |            URL             | |-----------|-------------|-------------|----------------------------| | default   | spring-boot | http        | http://192.168.39.76:32429 | |-----------|-------------|-------------|----------------------------|  Opening service default/spring-boot in default browser... 

Please notice that there’s a known issue which affects some JDKs: https://bugs.openjdk.java.net/browse/JDK-8236039

When this occurs the client throws an exception:

“javax.net.ssl.SSLHandshakeException: extension (5) should not be presented in certificate_request”

This happens because JDK 11 onwards has support for TLS 1.3 which can cause the above error.

You can work around this issue by setting the property -Djdk.tls.client.protocols=TLSv1.2 to the JVM args to make it use 1.2 instead. As an alternative, update to the latest version od JDK (it’s fully solved in JDK 15).

Enjoy Spring Boot on Kubernetes!

You can find the source code for this Maven project at: https://github.com/eclipse/jkube/tree/master/quickstarts/maven/spring-boot