Helm Subchart Pattern Using Git Submodules

Posted: April 26th, 2021 | Author: | Filed under: Technology | No Comments »

Helm has become the de facto tool for packaging and deploying applications in a Kubernetes environment not strictly due to its ease of use, but also because of its versatility. What once was a complex process for managing applications now can be facilitated with ease. In more complex deployments, an application may have one or more components that it relies on for normal operation, such as a database for a front end application. Helm uses the concept of dependencies to define a relationship between the current chart and any other chart that is required to be deployed in order for a release to be deemed both complete and successful. In most cases, dependencies are sourced from Helm repositories, where a chart has been packaged and served on an external web server. An example of how dependencies can be defined in a Chart.yaml file can be found below:

dependencies:
  - name: database
    repository: https://mychartrepository.example.com
    version: 1.0.0

However, another approach is to source dependent charts from the local file system. This method has several advantages including avoiding a reliance on any external resource (the chart repository) as well as the ability to test dependent charts that may also be in development without formal packaging to be complete.

Instead of specifying the location of the remote chart repository server using the http(s) protocol, the file protocol can be used instead:

dependencies:
  - name: database
    repository: file://./<path_to_chart>
    version: 1.0.0

The process of Installing a chart containing dependencies is the same regardless if they are sourced from a remote repository or the local file system. Dependent charts are referenced from the charts directory at install time and the helm dependency subcommand can be used to build or update the contents of this directory.

While the file system approach of managing dependent charts sounds appetizing, it does introduce challenges when it is time to version the Chart in a source code management tool, such as a Git repository. Do you want to include the entire contents of each dependent chart in your repository? As your git repository evolves with the content of your own chart (or others), including the contents from other dependencies within the same repository may cause unwanted and excessive bloat. As most charts that would be consumed as dependencies are stored in their own Git repository, an alternate method for sourcing dependent charts is to reference them from their own Git repositories using Git submodules. A submodule allows for a separate Git repository to be embedded within another repository. Some of the benefits using this approach is that only a reference to the associated repository is tracked instead of the entire contents. In addition, since the repository referenced in the submodule uses the fixed SHA of a given commit, it is akin to a tag that is commonly associated with a chart packaged within a helm repository. This ensures that the contents used today will be the same as in the future.

Dependencies also enable another approach used in the Helm ecosystem called subcharts. A subchart is a mechanism of providing inheritance to one or more charts as the parent of the associated subchart(s) can provide overriding values along with additional content (templates) of their own. To demonstrate an end to end overview of using Git submodules in Helm, let’s walk through an example to highlight how this approach can be accomplished.

The following repository contains the associated resources

https://github.com/sabre1041/helm-dependency-submodules

By using the subchart approach, we are going to make use of the Quarkus Helm chart found within the Red Hat Developers Helm Chart repository as the subchart and specify overriding values within our parent chart.

Installing the Helm Chart

Before beginning, ensure that you have the following prerequisites satisfied:

  • Git
  • Helm CLI
  • Kubernetes CLI

First, clone the repository to your local machine and change into the repository directory:

git clone https://github.com/sabre1041/helm-dependency-submodules.git
cd helm-dependency-submodules

This chart provides many of the common attributes that you would find in any other chart including a values.yaml and Chart.yaml files.

The git submodule is located in the dependencies directory named redhat-helm-charts. However, if you list the contents of this directory, it will be empty. 

ls -l dependencies/redhat-helm-charts/

This is due the fact that submodules are not initialized or updated to bring in the contents of the referenced repository when a repository is cloned by default. To clone the content of the submodule, initialize and update the submodule:

Initialize the submodule

git submodule init

Submodule 'dependencies/redhat-helm-charts' (https://github.com/redhat-developer/redhat-helm-charts) registered for path 'dependencies/redhat-helm-charts'

Update the submodule

git submodule update

Cloning into '<base_directory>/helm-dependency-submodules/dependencies/redhat-helm-charts'...
Submodule path 'dependencies/redhat-helm-charts': checked out '47ae04c40a4e75b33ad6a2ae84b09a173f739781'

If you inspect the contents of the Chart.yaml file, you will note the dependency referencing the quarkus helm chart within the submodule path:

dependencies:
- name: quarkus
  version: 0.0.3
  repository: file://./dependencies/redhat-helm-charts/alpha/quarkus-chart

Use the helm dependency update subcommand to package the dependency chart into the charts directory.

helm dependency update

Saving 1 charts
Deleting outdated charts

Now, install the chart to your Kubernetes environment into a new namespace called helm-dependency-submodules.

helm-dependency-submodules.

helm upgrade -i -n helm-dependency-submodules --create-namespace helm-dependency-submodules 

Note: By default, the Quarkus Helm chart assumes a deployment to an OpenShift environment and therefore creates a Route resource. To skip the creation of the Route, pass in the --set quarkus.deploy.route.enabled=false flag to the helm update command.

A new namespace called helm-dependency-submodules will be created if it did not exist previously and the Quarkus application will be deployed. If running in an OpenShift, a new Route will be created exposing the application. Execute the following command to obtain the URL of the application.

kubectl get routes -n helm-dependency-submodules helm-dependency-submodules -o jsonpath=https://’{ .spec.host }’

Finally, uninstall the application by using the helm uninstall command as shown below

helm uninstall -n helm-dependency-submodules helm-dependency-submodules

GitOps Support Using Argo CD

More and more organizations are adopting GitOps as a mechanism for managing applications. Argo CD is one such tool that implements GitOps principles and it provides support for not only Helm charts, but submodules found within Git repositories. Using the Git repository covered in the last section, let’s describe how Argo CD can facilitate deployment of the Quarkus application within the Helm chart to the Kubernetes cluster. 

First, deploy an instance of Argo CD to the environment and ensure that the Argo CD controller has the necessary permissions to create a namespace and resources in a project called helm-dependency-submodules-argocd. There are multiple ways that Argo CD can be deployed including the community based operator, OpenShift GitOps when operating in an OpenShift environment, as well as static manifest files. 

Once Argo CD has been deployed and is operational, create the Application using the manifest found in the argocd directory of the git repository.

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: quarkus
spec:
  destination:
    namespace: helm-dependency-submodules-argocd
    server: https://kubernetes.default.svc
  project: default
  source:
    path: .
    repoURL: https://github.com/sabre1041/helm-dependency-submodules
    targetRevision: HEAD
  syncPolicy:
    automated:
      prune: false
      selfHeal: true
    syncOptions:
    - CreateNamespace=true

Argo CD will take care of all the heavy lifting for us that we had to perform manually previously including:

  • Cloning the repository
  • Initializing and updating the submodule
  • Updating the chart dependencies
  • Installing the chart

Navigating to the quarkus Argo CD will illustrate the resources that were deployed and synchronized to the newly created helm-dependency-submodules-argocd namespace.

Application deployed using Argo CD

When changes are made to the repository, Argo CD will pick up the modifications and apply them based on the settings of the application. 

By either using the Helm CLI or a GitOps based tool like Argo CD as described during this discussion, Git submodules can provide yet another approach by which Helm can be used to streamline the deployment and management of applications in a kubernetes environment.