Install Helm Charts Using This Maven Plugin

Photo by Chris Lawton on Unsplash

There are several Maven plugins in the open source community that integrate with Helm. However, you’ll come to find that these plugins are used to generate Helm charts. Generating Helm charts from scratch suffices for personal usage or small teams, but consider the cases where Helm is used at scale across multiple teams within an organization. While you could expect each team to generate and maintain their own Helm charts, it’s more reasonable for a platform or DevOps team to create a Helm chart repository for use across the enterprise. Creating a Helm chart repository provides many advantages, including:

  • Incorporating best practices that might be missed by Helm chart generators
  • Adding templating to integrate with services such as Vault or an APM. A generic Helm chart generator would be very unlikely to provide these integrations in a way that makes sense for your organization
  • Providing versioned Helm chart releases. As the platform team adjusts its standards or implements new features, users can avoid copy-pasting changes and instead simply upgrade to the latest version of the chart

Because of the advantages of using managed Helm charts, I decided to write a Maven plugin, helm-maven-plugin, for installing Helm charts from a Helm chart repository within the Maven lifecycle. This blog post will explore the helm-maven-plugin and show you how to use it in an enterprise setting.

Helm Maven Plugin

First, to use this plugin, you need to install the Helm CLI on your local machine. For instructions on installing Helm, refer to Helm’s installation instructions.

Once Helm is installed on your local machine, you’re ready to get started! The plugin comes with two Maven goals:

  • helm:upgrade – Install/Upgrade a Helm chart to Kubernetes
  • helm:uninstall – Uninstall an existing Helm release

The helm:upgrade goal is invoked automatically during Maven’s install lifecycle phase. This goal installs a Helm chart to Kubernetes or upgrades an existing Helm release if one already exists. 

The helm:uninstall goal is not bound to a lifecycle phase, so it is executed by running the command mvn helm:uninstall from the command line.

For complete documentation on the helm-maven-plugin goals, visit the project’s readme. For a set of example POMs, visit the project’s examples.

Let’s walk through an example of using this plugin in practice.

Example Usage

I have a real-world example on GitHub at https://github.com/deweya/helm-maven-plugin-example. The application in this repo is just a simple Spring Boot microservice, but you can use helm-maven-plugin for any Java application on Kubernetes.

To deploy a container image using Helm, you first need to build the image and push it to a registry. For this reason, in the POM.xml file, I added the docker-maven-plugin to the build plugins and positioned it before helm-maven-plugin. An overview of docker-maven-plugin is out of scope, but you can review their project at https://github.com/fabric8io/docker-maven-plugin.

Then, of course, I added helm-maven-plugin to the POM’s build plugins. Below shows the XML used for adding and configuring the plugin:

<plugin>
  <groupId>com.austindewey</groupId>
  <artifactId>helm-maven-plugin</artifactId>
  <version>1.1.1</version>
  <configuration>
    <releaseName>spring-demo-app</releaseName>
    <chart>
      <name>onechart</name>
      <version>0.36.0</version>
      <repository>
        <url>https://chart.onechart.dev</url>
      </repository>
    </chart>
    <values>
      <files>
        <file>values.yaml</file>
      </files>
      <set>
        <image.repository>${image}</image.repository>
        <image.tag>${project.version}</image.tag>
      </set>
    </values>
  </configuration>
  <executions>
    <execution>
      <id>helm-upgrade</id>
      <goals>
        <goal>upgrade</goal>
      </goals>
    </execution>
  </executions>
</plugin>

Let’s explain this XML piece by piece.

Configuration Overview

First, I added the Maven GAV. As of writing, the latest version of the helm-maven-plugin is 1.1.1, but you can view the list of versions in the project’s changelog.

<groupId>com.austindewey</groupId>
<artifactId>helm-maven-plugin</artifactId>
<version>1.1.1</version>

Next, I added the plugin’s configuration. You can view all of the available configurations in the readme, and you can see different ways of configuring the plugin in the examples.

Let’s look at the first part of the configuration:

<releaseName>spring-demo-app</releaseName>

Every Helm release needs a release name, so I provided one using the releaseName element. If one is not provided, the release name defaults to the project.name POM setting.

After the release name, I provided the chart element, which determines the Helm chart we want to install as well as the repository that it comes from:

<chart>
  <name>onechart</name>
  <version>0.36.0</version>
  <repository>
    <url>https://chart.onechart.dev</url>
  </repository>
</chart>

This example installs version 0.36.0 of the chart onechart from the repository https://chart.onechart.dev (this is a generic Helm chart for deploying basic Kubernetes applications).

I suspect most users will install charts directly from an HTTP(S) URL, as demonstrated above. However, there are other ways to install Helm charts. Here are all of the ways that helm-maven-plugin takes into account:

  • Installing directly from an HTTP(S) URL (as demonstrated). This will be done if the repository.url element contains http:// or https://.
  • Installing from an OCI registry. This will be done if the repository.url element contains oci://.
  • Installing from a repository that was previously added using helm repo add. This will be done if the repository.name element is used instead of repository.url.
  • Installing from a local chart on the file system. This will be done if the previous conditions are not reached.

After the chart configuration, I added the values element for adding Helm values:

<values>
  <files>
    <file>values.yaml</file>
  </files>
  <set>
    <image.repository>${image}</image.repository>
    <image.tag>${project.version}</image.tag>
  </set>
</values>

The values.files element is the equivalent of passing the --values flag from the command line. Here, I’m using this values file from the example repository.

The values.set element is the equivalent of passing the --set flag. Here, I added two values inline for setting the image repository and tag. Here, you’ll notice I used interpolation, referencing the image property (defined in the POM’s properties) and the project’s version. I demonstrated it this way because this is how I imagine users will keep the image and tag consistent between the project name, the docker-maven-plugin, and the helm-maven-plugin.

Finally, I added the executions to bind the helm-maven-plugin’s upgrade goal with Maven’s install phase:

<executions>
  <execution>
    <id>helm-upgrade</id>
    <goals>
      <goal>upgrade</goal>
    </goals>
  </execution>
</executions>

The upgrade goal binds to the install phase by default, but I could have been explicit by adding the <phase>install</phase> element. When I run mvn clean install, the Maven will automatically install/upgrade the Helm chart to your Kubernetes environment!

There is not a logical lifecycle phase that the uninstall goal pairs well with, so I left that goal out of the executions config. So, to uninstall a release, you can execute the goal directly by running mvn helm:uninstall.

Let’s see how helm-maven-plugin works in practice.

Helm Maven Plugin in Action

With the above plugin configuration, I am ready to use Maven to build my project:

$ mvn clean install

This command, of course, runs the project’s tests and produces the jar file. Then, since my example POM includes the docker-maven-plugin, the container image is built and pushed to my registry in Docker Hub. Finally, Maven invokes the upgrade goal of helm-maven-plugin, producing the following log output:

[INFO] --- helm-maven-plugin:1.1.1:upgrade (helm-upgrade)
[INFO] Installing/Upgrading release "spring-demo-app"
Release "spring-demo-app" does not exist. Installing it now.
NAME: spring-demo-app
LAST DEPLOYED: Sat May 21 12:50:07 2022
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
[INFO] -----------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] -----------------------------------------------------------
[INFO] Total time:  30.554 s
[INFO] Finished at: 2022-05-21T12:50:07-04:00
[INFO] -----------------------------------------------------------

As you can see, the release spring-demo-app was deployed to the default namespace. The target namespace can be changed using the plugin’s namespace element in the POM.

A quick check on the default namespace will reveal that Maven successfully installed the chart!

$ kubectl get pods
NAME                            READY   STATUS    RESTARTS
spring-demo-app-88d5cb6-dhd2x   1/1     Running   0

$ helm list
NAME           	NAMESPACE	REVISION
spring-demo-app	default  	1

Though the chart installation was successful, you’ll sometimes notice that your pod will display the 0/1 ready state, indicating that it is still starting up. You can tell Maven to wait until your pod is ready by setting the plugin’s wait element to true in the POM.

When it is time to uninstall your release, you can invoke the uninstall goal directly:

$ mvn helm:uninstall

Afterward, you’ll see output similar to the following:

[INFO] Uninstalling release "spring-demo-app"
release "spring-demo-app" uninstalled
[INFO] -----------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] -----------------------------------------------------------
[INFO] Total time:  2.298 s
[INFO] Finished at: 2022-05-21T12:59:50-04:00
[INFO] -----------------------------------------------------------

Thanks for Reading

If you or your organization uses Helm chart repositories to deploy Java applications to Kubernetes, helm-maven-plugin can help provide you with a simple developer experience. If you are interested, feel free to check out the plugin’s documentation or leave a GitHub issue. I’d be happy to answer any questions or listen to any feedback you might have. Thanks for reading, and I’ll see you next time.

Austin Dewey

Austin Dewey is a DevOps engineer focused on delivering a streamlined developer experience on cloud and container technologies. Austin started his career with Red Hat’s consulting organization, where he helped drive success at many different Fortune 500 companies by automating deployments on Red Hat’s Kubernetes-based PaaS, OpenShift Container Platform. Currently, Austin works at fintech startup Prime Trust, building automation to scale financial infrastructure and support developers on Kubernetes and AWS. Austin is the author of "Learn Helm", a book focused on packaging and delivering applications to Kubernetes, and he enjoys writing about open source technologies at his blog in his free time, austindewey.com.

Leave a Reply