How To Deploy Helidon Application to Kubernetes With Kubernetes Maven Plugin
Dive into the world of containerizing Helidon applications and seamlessly deploying them to Kubernetes using the Eclipse JKube's Kubernetes Maven Plugin.
Join the DZone community and get the full member experience.
Join For FreeIn this article, we delve into the exciting realm of containerizing Helidon applications, followed by deploying them effortlessly to a Kubernetes environment. To achieve this, we'll harness the power of JKube’s Kubernetes Maven Plugin, a versatile tool for Java applications for Kubernetes deployments that has recently been updated to version 1.14.0.
What's exciting about this release is that it now supports the Helidon framework, a Java Microservices gem open-sourced by Oracle in 2018. If you're curious about Helidon, we've got some blog posts to get you up to speed:
- Building Microservices With Oracle Helidon
- Ultra-Fast Microservices: When MicroStream Meets Helidon
- Helidon: 2x Productivity With Microprofile REST Client
In this article, we will closely examine the integration between JKube’s Kubernetes Maven Plugin and Helidon. Here's a sneak peek of the exciting journey we'll embark on:
- We'll kick things off by generating a Maven application from Helidon Starter
- Transform your Helidon application into a nifty Docker image.
- Craft Kubernetes YAML manifests tailored for your Helidon application.
- Apply those manifests to your Kubernetes cluster.
- We'll bundle those Kubernetes YAML manifests into a Helm Chart.
- We'll top it off by pushing that Helm Chart to a Helm registry.
- Finally, we'll deploy our Helidon application to Red Hat OpenShift.
An exciting aspect worth noting is that JKube’s Kubernetes Maven Plugin can be employed with previous versions of Helidon projects as well. The only requirement is to provide your custom image configuration. With this latest release, Helidon users can now easily generate opinionated container images. Furthermore, the plugin intelligently detects project dependencies and seamlessly incorporates Kubernetes health checks into the generated manifests, streamlining the deployment process.
Setting up the Project
You can either use an existing Helidon project or create a new one from Helidon Starter. If you’re on JDK 17 use 3.x version of Helidon. Otherwise, you can stick to Helidon 2.6.x which works with older versions of Java. In the starter form, you can choose either Helidon SE or Helidon Microprofile, choose application type, and fill out basic details like project groupId
, version
, and artifactId
.
Once you’ve set your project, you can add JKube’s Kubernetes Maven Plugin to your pom.xml
:
<plugin>
<groupId>org.eclipse.jkube</groupId>
<artifactId>kubernetes-maven-plugin</artifactId>
<version>1.14.0</version>
</plugin>
Also, the plugin version is set to 1.14.0, which is the latest version at the time of writing. You can check for the latest version on the Eclipse JKube releases page.
It’s not really required to add the plugin if you want to execute it directly from some CI pipeline. You can just provide a fully qualified name of JKube’s Kubernetes Maven Plugin while issuing some goals like this:
$ mvn org.eclipse.jkube:kubernetes-maven-plugin:1.14.0:resource
Now that we’ve added the plugin to the project, we can start using it.
Creating Container Image (JVM Mode)
In order to build a container image, you do not need to provide any sort of configuration. First, you need to build your project.
$ mvn clean install
Then, you just need to run k8s:build goal of JKube’s Kubernetes Maven Plugin. By default, it builds the image using the Docker build strategy, which requires access to a Docker daemon.
If you have access to a docker daemon, run this command:
$ mvn k8s:build
If you don’t have access to any docker daemon, you can also build the image using the Jib build strategy:
$ mvn k8s:build -Djkube.build.strategy=jib
You will notice that Eclipse JKube has created an opinionated container image for your application based on your project configuration. Here are some key points about JKube’s Kubernetes Maven Plugin to observe in this zero configuration mode:
- It used quay.io/jkube/jkube-java as a base image for the container image
- It added some labels to the container image (picked from pom.xml)
- It exposed some ports in the container image based on the project configuration
- It automatically copied relevant artifacts and libraries required to execute the jar in the container environment.
Creating Container Image (Native Mode)
In order to create a container image for the native executable, we need to generate the native executable first. In order to do that, let’s build our project in the native-image profile (as specified in Helidon GraalVM Native Image documentation):
$ mvn package -Pnative-image
This creates a native executable file in the target folder of your project. In order to create a container image based on this executable, we just need to run k8s:build goal but also specify native-image profile:
$ mvn k8s:build -Pnative-image
Like JVM mode, Eclipse JKube creates an opinionated container image but uses a lightweight base image: registry.access.redhat.com/ubi8/ubi-minimal
and exposes only the required ports by application.
Customizing Container Image as per Requirements
Creating a container image with no configuration is a really nice way to get started. However, it might not suit everyone’s use case. Let’s take a look at how to configure various aspects of the generated container image.
You can override basic aspects of the container image with some properties like this:
Property Name |
Description |
|
Change Image Name |
|
Change Base Image |
|
A comma-separated value of additional tags for the image |
If you want more control, you can provide a complete XML configuration for the image in the plugin configuration section:
<plugin>
<groupId>org.eclipse.jkube</groupId>
<artifactId>kubernetes-maven-plugin</artifactId>
<version>${jkube.version}</version>
<configuration>
<images>
<image>
<name>${project.artifactId}:${project.version}</name>
<build>
<from>openjdk:11-jre-slim</from>
<ports>8080</ports>
<assembly>
<mode>dir</mode>
<targetDir>/deployments</targetDir>
<layers>
<layer>
<id>lib</id>
<fileSets>
<fileSet>
<directory>${project.basedir}/target/libs</directory>
<outputDirectory>libs</outputDirectory>
<fileMode>0640</fileMode>
</fileSet>
</fileSets>
</layer>
<layer>
<id>app</id>
<files>
<file>
<source>${project.basedir}/target/${project.artifactId}.jar</source>
<outputDirectory>.</outputDirectory>
</file>
</files>
</layer>
</layers>
</assembly>
<cmd>java -jar /deployments/${project.artifactId}.jar</cmd>
</build>
</image>
</images>
</configuration>
</plugin>
The same is also possible by providing your own Dockerfile in the project base directory. Kubernetes Maven Plugin automatically detects it and builds a container image based on its content:
FROM openjdk:11-jre-slim
COPY maven/target/helidon-quickstart-se.jar /deployments/
COPY maven/target/libs /deployments/libs
CMD ["java", "-jar", "/deployments/helidon-quickstart-se.jar"]
EXPOSE 8080
Pushing the Container Image to Quay.io:
Once you’ve built a container image, you most likely want to push it to some public or private container registry.
Before pushing the image, make sure you’ve renamed your image to include the registry name and registry user. If I want to push an image to Quay.io in the namespace of a user named rokumar
, this is how I would need to rename my image:
$ mvn k8s:build -Djkube.generator.name=quay.io/rokumar/%a:%v
%a
and %v
correspond to project artifactId
and project version. For more information, you can check the Kubernetes Maven Plugin Image Configuration documentation.
Once we’ve built an image with the correct name, the next step is to provide credentials for our registry to JKube’s Kubernetes Maven Plugin. We can provide registry credentials via the following sources:
- Docker login
- Local Maven Settings file (
~/.m2/settings.xml
) - Provide it inline using
jkube.docker.username
andjkube.docker.password
properties
Once you’ve configured your registry credentials, you can issue the k8s:push goal to push the image to your specified registry:
$ mvn k8s:push
Generating Kubernetes Manifests
In order to generate opinionated Kubernetes manifests, you can use k8s:resource goal from JKube’s Kubernetes Maven Plugin:
$ mvn k8s:resource
It generates Kubernetes YAML manifests in the target directory:
$ ls target/classes/META-INF/jkube/kubernetes
helidon-quickstart-se-deployment.yml helidon-quickstart-se-service.yml
JKube’s Kubernetes Maven Plugin automatically detects if the project contains io.helidon:helidon-health
dependency and adds liveness, readiness, and startup probes:
$ cat target/classes/META-INF/jkube/kubernetes//helidon-quickstart-se-deployment.
yml | grep -A8 Probe
livenessProbe:
failureThreshold: 3
httpGet:
path: /health/live
port: 8080
scheme: HTTP
initialDelaySeconds: 0
periodSeconds: 10
successThreshold: 1
--
readinessProbe:
failureThreshold: 3
httpGet:
path: /health/ready
port: 8080
scheme: HTTP
initialDelaySeconds: 0
periodSeconds: 10
successThreshold: 1
Applying Kubernetes Manifests
JKube’s Kubernetes Maven Plugin provides k8s:apply goal that is equivalent to kubectl apply
command. It just applies the resources generated by k8s:resource in the previous step.
$ mvn k8s:apply
Packaging Helm Charts
Helm has established itself as the de facto package manager for Kubernetes. You can package generated manifests into a Helm Chart and apply it on some other cluster using Helm CLI.
You can generate a Helm Chart of generated manifests using k8s:helm goal. The interesting thing is that JKube’s Kubernetes Maven Plugin doesn’t rely on Helm CLI for generating the chart.
$ mvn k8s:helm
You’d notice Helm Chart is generated in target/jkube/helm/
directory:
$ ls target/jkube/helm/helidon-quickstart-se/kubernetes
Chart.yaml helidon-quickstart-se-0.0.1-SNAPSHOT.tar.gz README.md templates values.yaml
Pushing Helm Charts to Helm Registries
Usually, after generating a Helm Chart locally, you would want to push it to some Helm registry. JKube’s Kubernetes Maven Plugin provides k8s:helm-push goal for achieving this task.
But first, we need to provide registry details in plugin configuration:
<plugin>
<groupId>org.eclipse.jkube</groupId>
<artifactId>kubernetes-maven-plugin</artifactId>
<version>1.14.0</version>
<configuration>
<helm>
<snapshotRepository>
<name>ChartMuseum</name>
<url>http://example.com/api/charts</url>
<type>CHARTMUSEUM</type>
<username>user1</username>
</snapshotRepository>
</helm>
</configuration>
</plugin>
JKube’s Kubernetes Maven Plugin supports pushing Helm Charts to ChartMuseum, Nexus, Artifactory, and OCI registries. You have to provide the applicable Helm repository type and URL. You can provide the credentials via environment variables, properties, or ~/.m2/settings.xml
. Once you’ve all set up, you can run k8s:helm-push goal to push chart:
$ mvn k8s:helm-push -Djkube.helm.snapshotRepository.password=yourpassword
Deploying To Red Hat OpenShift
If you’re deploying to Red Hat OpenShift, you can use JKube’s OpenShift Maven Plugin to deploy your Helidon application to an OpenShift cluster. It contains some add-ons specific to OpenShift like S2I build strategy, support for Routes, etc. You also need to add the JKube’s OpenShift Maven Plugin plugin to your pom.xml
. Maybe you can add it in a separate profile:
<profile>
<id>openshift</id>
<build>
<plugins>
<plugin>
<groupId>org.eclipse.jkube</groupId>
<artifactId>openshift-maven-plugin</artifactId>
<version>${jkube.version}</version>
</plugin>
</plugins>
</build>
</profile>
Then, you can deploy the application with a combination of these goals:
$ mvn oc:build oc:resource oc:apply -Popenshift
Conclusion
In this article, you learned how smoothly you can deploy your Helidon applications to Kubernetes using Eclipse JKube’s Kubernetes Maven Plugin. We saw how effortless it is to package your Helidon application into a container image and publish it to some container image registry. We can alternatively generate Helm Charts of our Kubernetes YAML manifests and publish Helm Charts to some Helm registry. In the end, we learned about JKube’s OpenShift Maven Plugin, which is specifically designed for Red Hat OpenShift users who want to deploy their Helidon applications to Red Hat OpenShift. You can find the code used in this blog post in this GitHub repository.
In case you’re interested in knowing more about Eclipse JKube, you can check these links:
Opinions expressed by DZone contributors are their own.
Comments