In this tutorial we will learn how to deploy a Spring Boot application on Kubernetes and manage it using Helm charts.
Helm Chart is an application package manager for the Kubernetes cluster. A chart is a collection of files that describe a related set of Kubernetes resources. A single chart might be used to deploy something simple, like a memcached pod, or a full application stack.
By using Helm Charts you can simplify the management of your cluster without the need to remember complex Kubernetes commands to manage the Kubernetes resources.
Installing Helm
There are several ways to install Helm. The following command will install is as a script:
$ curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3 $ chmod 700 get_helm.sh $ ./get_helm.sh
We will use MiniKube to start our Kubernetes cluster. Please refer to this tutorial to learn how to get started with Minikube: How to deploy a Spring Boot application on Kubernetes in 3 simple steps
Start MiniKube:
$ minikube start
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, make sure you use Minikube docker repository:
$ eval $(minikube docker-env)
Create your first Helm chart
In order to create our first Helm chart, you can run the “helm create” command followed by the chart name:
helm create springbootdemo
A set of YAML files will be generated.
springboot | |- Chart.yaml # Information about your chart | |- values.yaml # The default values for your templates | |- charts/ # Charts that this chart depends on | |- templates/ # The template files
.Chart.yaml holds metatdata about the chart (name, version, and description)
- values.yaml holds the default values for your chart templates
- charts directory holds any dependency charts. Unless you are building a chart from component charts, this can be empty.
- templates directory holds all the yaml files you are used to push via kubectl cli (deployment, rbac, service, etc files)
So how do we configure helm to use our own Spring Boot application? in a nutshell we have to provide the image name (available on DockerHub or on your own Repository) and the port where the service is running.
The first change will be in values.yaml:
image: repository: kharulp12/spring_hello_rest_api #just an example Spring Boot image pullPolicy: IfNotPresent # Overrides the image tag whose default is the chart appVersion. tag: ""
Then, in the /templates/deployment.yaml set the appropriate port:
ports: - name: http containerPort: 8080 protocol: TCP
Before pushing the charts to the cluster, Helm allows you to do a dry run to simulate an install/upgrade:
helm install --dry-run --debug <path to chart directory>
Then, you can install your application using the “helm install” command:
helm install springbootdemo springbootdemo NAME: springbootdemo LAST DEPLOYED: Sat Dec 19 10:33:41 2020 NAMESPACE: default STATUS: deployed REVISION: 1 NOTES: 1. Get the application URL by running these commands: export POD_NAME=$(kubectl get pods --namespace default -l "app.kubernetes.io/name=springboot,app.kubernetes.io/instance=springbootdemo" -o jsonpath="{.items[0].metadata.name}") export CONTAINER_PORT=$(kubectl get pod --namespace default $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}") echo "Visit http://127.0.0.1:8080 to use your application" kubectl --namespace default port-forward $POD_NAME 8080:$CONTAINER_PORT
Then, check if the Chart is available with the command “helm list”:
[francesco@fedora target]$ helm list -a NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION springbootdemo default 1 2020-12-19 10:33:41.613142795 +0100 CET deployed springboot-0.1.0 1.16.0
And verify that the Pod is also available:
[francesco@fedora target]$ kubectl get all NAME READY STATUS RESTARTS AGE pod/springdemo-79bbc497d5-tj455 1/1 Running 1 15h
Using JKube Maven plugin to deploy Helm Charts
There’s an even simpler approach to generate and deploy your Helm charts. You can use JKube Maven plugin to create an Helm Chart from your Maven project settings.
We will be deploying the following application which includes a simple Hello World controller:
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 with YAML files!!"; } }
The Maven plugin settings will be included in a profile:
<?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-with-yaml-label-for-all</testProject> </all> </labels> </resources> <generator> <config> <spring-boot> <color>always</color> </spring-boot> </config> </generator> </configuration> <executions> <execution> <phase>package</phase> <goals> <goal>resource</goal> <goal>build</goal> <goal>helm</goal> </goals> </execution> </executions> </plugin> </plugins> </build> </profile>
With this plugin, you can generate the helm chart with defaults using:
mvn k8s:resource k8s:helm -Pkubernetes
The great thing of this plugin is that it automatically sets the correct values for Spring Boot application using some default values:
[INFO] k8s: spring-boot: Using Docker image quay.io/jkube/jkube-java-binary-s2i:0.0.8 as base / builder [INFO] k8s: Using resource templates from /home/git/jkube-master/quickstarts/maven/spring-boot-helm/src/main/jkube [INFO] k8s: jkube-controller: Adding a default Deployment [INFO] k8s: jkube-service: Adding a default service 'spring-boot-helm' with ports [8080] [INFO] k8s: jkube-healthcheck-spring-boot: Adding readiness probe on port 8080, path='/actuator/health', scheme='HTTP', with initial delay 10 seconds [INFO] k8s: jkube-healthcheck-spring-boot: Adding liveness probe on port 8080, path='/actuator/health', scheme='HTTP', with initial delay 180 seconds [INFO] k8s: jkube-revision-history: Adding revision history limit to 2
The Helm files will be generated under the target/jkube directory:
tree target/jkube/ target/jkube/ ├── helm │ └── spring-boot-helm │ └── kubernetes │ ├── Chart.yaml │ ├── LICENSE │ ├── README.md │ ├── templates │ │ ├── password-secret.yaml │ │ ├── spring-boot-helm-deployment.yaml │ │ └── spring-boot-helm-service.yaml │ └── values.yaml └── password-secret.yml
On the other hand, if you prefer to build your application and generate the helm files in one command, just execute:
With Minikube running, perform the following commands:
$ mvn -Pkubernetes clean package
Then, install the Helm charts with:
$ helm install spring-boot-helm target/jkube/helm/spring-boot-helm/kubernetes/
Check that the helm chart is available:
helm list -a NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION spring-boot-helm default 2 2020-12-19 11:25:04.621514079 +0100 CET deployed spring-boot-helm-1.0.2
Now run the service on the browser:
$ minikube service spring-boot-helm
You will see on the screen:”Greetings from Spring Boot with YAML files!!”
great, you just managed to deploy a Spring Boot application on Kubernetes using Helm charts
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-helm