Kubernetes, Eclipse JKube, and Red Hat (OpenShift) featured image

Helm charts are a popular and convenient way to support different environments on Kubernetes. My previous article, How Helm and JKube simplify Kubernetes management, part 1, explained why generating Helm charts for Java applications can be difficult and how it's made easier by Eclipse JKube, which has Maven and Gradle plugins.

In Part 1, you learned how to generate Helm charts for Java automatically without any configuration and to publish them to desired Helm registries. While a zero-configuration approach is a great way to get started, most projects tune the Eclipse JKube plugins to generate the Helm charts to meet their requirements.

This follow-up article explains how to configure Helm charts generated by JKube's Maven and Gradle plugins via various configuration options provided by Eclipse JKube.

Specifically, we will cover:

  • XML
  • Java properties
  • Resource fragments

Then we will conclude by demonstrating how to configure your Helm registry where you store your configuration.

Assuming you completed part one, you should already have the JKube Maven plugin (available in this Github repository) in your sample project:

<dependency>
  <groupId>org.eclipse.jkube</groupId>
  <artifactId>openshift-maven-plugin</artifactId>
  <version>${jkube.version}</version>
</dependency>

For this series of articles, we use the Maven plugin provided specifically for Red Hat Openshift. You can configure the Helm chart generated by JKube by overriding the opinionated default Helm configuration. The following sections describe how to customize charts via XML, Java properties, and resource fragments.

Edit XML to configure Helm

One way to configure a Helm chart managed by JKube is to directly edit the pom.xml file in the JKube plugin configuration section. Override the default configuration by providing a helm configuration option in the plugin's configuration section. Here is an example:

  <plugin>
    <groupId>org.eclipse.jkube</groupId>
    <artifactId>openshift-maven-plugin</artifactId>
    <version>${jkube.version}</version>
    <configuration>
      <helm>
        <chart>${project.artifactId}</chart>
        <version>${project.version}</version>
        <description>JKube Helm Maven demo Helm Chart</description>
        <home>https://www.eclipse.org/jkube/</home>
        <sources>
           <source>https://github.com/eclipse/jkube</source>
        </sources>
        <maintainers>
          <maintainer>
            <name>Maintainer1</name>
            <email>maintainer1@maintainer1.org</email>
            <url>maintainer1.org</url>
          </maintainer>
          <maintainer>
            <name>Maintainer2</name>
            <email>maintainer2@maintainer2.org</email>
            <url>maintainer2.org</url>
          </maintainer>
        </maintainers>
        <icon>https://helm.sh/img/helm.svg</icon>
        <keywords>eclipse,jkube,kubernetes,maven</keywords>
        <sourceDir>${project.basedir}/target/classes/META-INF/jkube</sourceDir>
        <outputDir>${project.basedir}/target/jkube/helm</outputDir>
        <chartExtension>tar.gz</chartExtension>
         <dependencies>
               <dependency>
                   <name>ingress-nginx</name>
                   <version>3.16.1</version>
                    <repository>https://kubernetes.github.io/ingress-nginx</repository>
               </dependency>
           </dependencies>
      </helm>
    </configuration>
  </plugin>

The complete set of supported configuration options is in the oc:helm documentation.

Now run OpenShift Maven Plugin's resource and the Helm goal to regenerate the YAML manifests and Helm chart. I have added the plugin configuration in a separate xml-configuration profile.

$ ./mvnw oc:resource oc:helm -Pxml-configuration

After running that command, you should be able to see this generated Helm Chart:

apiVersion: v1
name: jkube-helm-maven
home: https://www.eclipse.org/jkube/
sources:
- https://github.com/eclipse/jkube
version: 1.0.0-SNAPSHOT
description: JKube Helm Maven demo Helm Chart
keywords:
- eclipse
- jkube
- kubernetes
- maven
maintainers:
- name: Maintainer1
  email: maintainer1@maintainer1.org
  url: maintainer1.org
- name: Maintainer2
  email: maintainer2@maintainer2.org
  url: maintainer2.org
icon: https://helm.sh/img/helm.svg
dependencies:
- name: ingress-nginx
  version: 3.16.1
  repository: https://kubernetes.github.io/ingress-nginx

Configuring Helm using Java properties

JKube also exposes the Helm configuration via Java properties. Here is an example of how to provide the configuration from the previous section using Maven properties:

    <profile>
      <id>property-configuration</id>
      <properties>
        <jkube.helm.chart>${project.artifactId}</jkube.helm.chart>
        <jkube.helm.version>${project.version}</jkube.helm.version>
        <jkube.helm.description>JKube Helm Maven demo Helm Chart (Properties)</jkube.helm.description>
        <jkube.helm.home>https://www.eclipse.org/jkube/</jkube.helm.home>
        <jkube.helm.icon>https://helm.sh/img/helm.svg</jkube.helm.icon>
        <jkube.helm.type>openshift</jkube.helm.type>
        <jkube.helm.sourceDir>${project.basedir}/target/classes/META-INF/jkube</jkube.helm.sourceDir>
        <jkube.helm.outputDir>${project.basedir}/target/jkube/helm</jkube.helm.outputDir>
        <jkube.helm.chartExtension>tar.gz</jkube.helm.chartExtension>
      </properties>
    </profile>

NOTE: You can't configure complex elements such as maintainers and sources via properties.

Run the OpenShift Maven Plugin's resource and the Helm goal to regenerate the YAML manifests and Helm chart. As in the previous section, I have added the plugin configuration in a separate property-configuration profile.

$ ./mvnw oc:resource oc:helm -Pproperty-configuration

You should see the generated Helm chart in the target/jkube/helm/openshift/ directory. The chart's contents should be similar to the chart generated with the xml-configuration profile in the previous step.

Configuring Helm using resource fragments

Suppose you want to apply a CustomResource object along with your regular Kubernetes resources during the "resource and apply" phase of the OpenShift Maven Plugin's run. It is impossible to provide a custom resource via an XML configuration or property. Instead, use the third method of generating a Helm chart: JKube resource fragments.

JKube allows users to provide their Kubernetes YAML manifests in a specific directory. The manifests are automatically picked up during oc:resource goal and added to the Helm chart.

For this article, we will use the crontab CustomResource from the Kubernetes documentation. To start, apply the crontab CustomResourceDefinition on OpenShift using the command-line tool:

$ oc create -f crontab-crd.yml
customresourcedefinition.apiextensions.k8s.io/crontabs.stable.example.com created

Let's take a look at our crontab custom resource manifest. Usually, you would add this file to the src/main/jkube directory (the default location of the resource directory). But in our case, we have configured a different resource directory (the fragments folder in the root directory). The fragments/jkube/crontab-cr.yaml file contains:

apiVersion: "stable.example.com/v1"
kind: CronTab
metadata:
  name: ${project.artifactId}
  labels:
    helm.sh/chart: "${project.artifactId}-${crontab.release}"
    app.kubernetes.io/managed-by: "${crontab.managedby}"
spec:
  cronSpec: ${crontab.spec}
  image: ${crontab.image}

Note how we provide some of the values in this crontab resource fragment using fields enclosed in ${...}. You must define these values in the Helm parameter configurations, as in the following example:

      <plugin>
        <groupId>org.eclipse.jkube</groupId>
        <artifactId>kubernetes-maven-plugin</artifactId>
        <version>${jkube.version}</version>
        <configuration>
          <resourceDir>${project.basedir}/fragments/jkube</resourceDir>
          <helm>
                <parameters>
                  <parameter>
                    <name>crontab.spec</name>
                    <value>{{ .spec | default "* * * * */5" | quote }}</value>
                  </parameter>
                  <parameter>
                    <name>crontab.image</name>
                    <value>{{ .image | default "my-awesome-cron-image" | upper | quote }}</value>
                  </parameter>
                  <parameter>
                    <name>crontab.release</name>
                    <value>{{ .Chart.Version }}</value>
                  </parameter>
                  <parameter>
                    <name>crontab.managedby</name>
                    <value>jkube</value>
                  </parameter>
                </parameters>
          </helm>
        </configuration>
      </plugin>

You can specify strings, Maven properties, or Helm template directives as values. Helm parameters can contain non-string fields and periods. JKube automatically resolves Maven properties in a values.yaml file.

Run the OpenShift Maven Plugin's resource and the Helm goal to regenerate the YAML manifests and Helm chart. I have added the plugin configuration in a separate fragment-configuration profile.

$ ./mvnw oc:resource oc:helm -Pfragment-configuration

This results in the following crontab template:

$ cat target/jkube/helm/jkube-helm-maven/openshift/templates/jkube-helm-maven-cr.yaml
---
apiVersion: stable.example.com/v1
kind: CronTab
metadata:
  labels:
    helm.sh/chart: "jkube-helm-maven-{{ .Chart.Version }}"
    app.kubernetes.io/managed-by: {{ .Values.crontab.managedby | default "jkube" }}
    app: jkube-helm-maven
    provider: jkube
    version: 1.0.0-SNAPSHOT
    group: org.eclipse.jkube.demos
  name: jkube-helm-maven
spec:
  cronSpec: {{ .spec | default "* * * * */5" | quote }}
  image: {{ .image | default "my-awesome-cron-image" | upper | quote }}

JKube has replaced ${...} placeholders with values specified in the parameter configurations. JKube also generated a values.yaml file for later use by Helm for resolving values. You can inspect the generated values.yaml file as follows:

$ cat target/jkube/helm/jkube-helm-maven/openshift/values.yaml
---
crontab:
  managedby: jkube

Next, install this Helm chart. You should see the crontab custom resource applied to the target cluster:

$ helm install --generate-name target/jkube/helm/jkube-helm-maven/openshift/
NAME: openshift-1657293004
LAST DEPLOYED: Fri Jul  8 20:40:05 2022
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: None

Check the applied crontab resource:

$ oc get crontab
NAME               AGE
jkube-helm-maven   86s

$ oc get crontab jkube-helm-maven -o yaml
apiVersion: stable.example.com/v1
kind: CronTab
metadata:
  annotations:
    meta.helm.sh/release-name: openshift-1657293004
    meta.helm.sh/release-namespace: default
  labels:
    app: jkube-helm-maven
    app.kubernetes.io/managed-by: Helm
    group: org.eclipse.jkube.demos
    helm.sh/chart: jkube-helm-maven-1.0.0-SNAPSHOT
    provider: jkube
    version: 1.0.0-SNAPSHOT
   name: jkube-helm-maven
  namespace: default
  resourceVersion: "43872"
  uid: c7b8547e-d0c1-404f-842c-f8e265340b34
spec:
  cronSpec: '* * * * */5'
  image: MY-AWESOME-CRON-IMAGE

Configuring the Helm registry

Apart from configuring Helm charts, you must configure the registry to which you will push your Helm chart. Like Helm charts, Helm registries can be configured via XML configuration or properties.

I used ChartMuseum for my Helm registry. I have set up a local instance on my machine. You need to change the examples that follow to reflect your Helm registry.

If your project version is a snapshot, use the snapshotRepository field for Helm registry configuration. Otherwise, use stableRepository. We will use snapshotRepository for this demo since it has a 1.0.0-SNAPSHOT Maven version:

      <plugin>
        <groupId>org.eclipse.jkube</groupId>
        <artifactId>kubernetes-maven-plugin</artifactId>
        <version>${jkube.version}</version>
        <configuration>
          <helm>
            <snapshotRepository>
              <name>ChartMuseum</name>
              <url>http://localhost:8080/api/charts</url>
              <type>CHARTMUSEUM</type>
              <username>user1</username>
            </snapshotRepository>
          </helm>
        </configuration>
      </plugin>

Once you have configured your Helm registry details, run the Helm push goal:

$ ./mvnw oc:helm-push -Djkube.helm.snapshotRepository.password=secret

This should upload the Helm chart to the specified registry. You can also provide all this configuration in the form of properties, as shown in the following command:

$ ./mvnw oc:helm-push -Djkube.helm.snapshotRepository.name=ChartMuseum \
> -Djkube.helm.snapshotRepository.url=http://localhost:8080/api/charts \
> -Djkube.helm.snapshotRepository.type=CHARTMUSEUM \
> -Djkube.helm.snapshotRepository.username=user1 \
> -Djkube.helm.snapshotRepository.password=secret

It is also possible to provide registry credentials in Maven settings (~/.m2/settings.xml) by specifying the Helm registry name and URL:

      <plugin>
        <groupId>org.eclipse.jkube</groupId>
        <artifactId>openshift-maven-plugin</artifactId>
        <version>${jkube.version}</version>
        <configuration>
          <helm>
            <snapshotRepository>
              <name>ChartMuseum</name>
              <url>http://localhost:8080/api/charts</url>
              <type>CHARTMUSEUM</type>
            </snapshotRepository>
          </helm>
        </configuration>
      </plugin>

You can provide Helm registry credentials in the server section of settings.xml. The server ID must match the Helm registry name specified in the plugin configuration. JKube can automatically infer credentials from Maven settings:

<?xml version="1.0" encoding="UTF-8"?>
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd">

  <servers>
    <server>
      <id>ChartMuseum</id>
      <username>user1</username>
      <password>secret</password>
    </server>
  </servers>

</settings>

Customized JKube configurations

So far, you have learned the different methods for generating and publishing Helm charts using Eclipse JKube plugins. We demonstrated how easy it is to customize various aspects of Helm charts and registries utilizing a rich set of configuration options. Please try one or more of these options and provide feedback regarding how we can improve your experience.

For more information, check out the Eclipse JKube website. Feel free to follow us on these channels:

Last updated: October 31, 2023