Helm Chart Dependencies
Helm charts serve as a package manager for Kubernetes, facilitating the definition, installation, and upgrade of Kubernetes applications. One of the most important components in Helm is chart dependencies. Instead of writing all configurations from scratch, you can use pre-existing charts as dependencies to extend the functionality of a new chart.
In this blog, we will learn what Helm Chart Dependencies are and how to use them.
Want to learn more about creating Helm Charts? Read this blog: Writing a Helm Chart: A Comprehensive Guide for Beginners.
What are Helm Chart Dependencies?
Helm chart dependencies are other charts that a Helm chart relies on to function correctly. These dependencies are specified in the chart directory's requirements.yaml file, which lists the chart name, version, and repository URL that the main chart requires.
If a chart has dependencies, Helm will automatically download and install them before installing the main chart. This guarantees that all necessary elements are available and correctly configured.
Updating dependencies is also possible by using the helm dependency update
command, which downloads the latest version of each dependency and updates the Chart.lock
file accordingly. This ensures that the chart is current and all dependencies are compatible with one another.
How to Add a Dependency to Helm Chart
If we were to build a chart to launch a WordPress website, it would also depend on a chart for MySQL or MariaDB and, possibly, Memcached if we want to add a way to speed up the website.
There are two ways to add dependency charts to our main parent chart:
- Listing dependencies in our Chart.yaml file and then let Helm download the necessary dependency files.
- Dropping dependency charts (the files and directories they contain) manually in the charts directory.
1. Listing dependencies in Chart.yaml
Let’s assume that, for some reason, our chart would need MariaDB. To add it as a dependency, open up our Chart.yaml file in an Editor.
Under the description
of our chart, we need to add this content:
dependencies:
- name: mariadb
repository: https://charts.bitnami.com/bitnami
version: ~9.3
Our Chart.yaml file now looks like this:
apiVersion: v2
name: nginx
description: Basic Nginx website for our company
dependencies:
- name: mariadb
repository: https://charts.bitnami.com/bitnami
version: ~9.3
# A chart can be either an 'application' or a 'library' chart.
#
# Application charts are a collection of templates that can be packaged into versioned archives
# to be deployed.
#
# Library charts provide useful utilities or functions for the chart developer. They're included as
# a dependency of application charts to inject those utilities and functions into the rendering
# pipeline. Library charts do not define any templates and therefore cannot be deployed.
type: application
# This is the chart version. This version number should be incremented each time you make changes
# to the chart and its templates, including the app version.
# Versions are expected to follow Semantic Versioning (https://semver.org/)
version: 0.1.0
# This is the version number of the application being deployed. This version number should be
# incremented each time you make changes to the application. Versions are not expected to
# follow Semantic Versioning. They should reflect the version the application is using.
# It is recommended to use it with quotes.
appVersion: "1.16.0"
maintainers:
- email: [email protected]
name: John Smith
Let’s analyze two components in the content we added: repository and version.
repository: https://charts.bitnami.com/bitnami
How do we get that address? Well, in our case, we looked up a chart on the Artifact Hub website and ended up choosing this as a proper candidate. We can see there that the command to add this repository to Helm is:
The address we add to our repository:
field is the same one we would use in a helm repo add
command.
helm repo add bitnami https://charts.bitnami.com/bitnami
Now, the second interesting line:
version: ~9.3
What does ~9.3
mean, and why did we choose to use this version?
At the time of creating this blog, when we opened up this, we noticed that this chart’s latest version was 9.3.16.
Using the notation ~9.3
in our version:
field ensures that our chart will pull in the latest version of the MariaDB chart, which starts with 9.3. This could be 9.3.16 today and 9.3.18 a few weeks later. But it won’t pull in a version that starts with 9.4.
This is a good way to make sure we pull the latest chart version with a certain feature set that is currently compatible with our parent chart. Versions 9.4 and 9.5 might introduce feature changes that make them incompatible with the current parent chart.
But we did not analyze the first line:
- name: mariadb
The name is pretty straightforward. We just use the chart name we want to use as a dependency. It’s the same name we would use when installing such a chart with a command like:
helm install my-release bitnami/mariadb
But the -
sign might be a bit weird. It’s just standard YAML stuff to delimit multiple children of the dependencies:
section. To make it easier to remember how to write this, you can think of it this way:
Since we list multiple chart dependencies here, we need a way to delimit where one dependency declaration ends and another begins. So, we use the “-” sign to separate the details of each dependency chart.
Here’s an example with multiple dependencies:
dependencies:
- condition: mariadb.enabled
name: mariadb
repository: https://charts.bitnami.com/bitnami
version: 9.x.x
- condition: memcached.enabled
name: memcached
repository: https://charts.bitnami.com/bitnami
version: 5.x.x
- name: common
repository: https://charts.bitnami.com/bitnami
tags:
- bitnami-common
version: 1.x.x
(The “-“ in the tags:
section is different. You could think of “-” as separating children of the tags:
section)
All in all, it was pretty easy to add our MariaDB dependency. But the job is not done, though. This just tells Helm about the dependency charts, but the dependency charts themselves are still missing from our project. Fortunately, there is a simple command that makes Helm look at our dependency list (in Chart.yaml) and automatically pull in all of the required charts (their files):
helm dependency update ./nginx
And that’s it, job done! The command helm template ./nginx
will show us that, indeed, now the MariaDB dependency chart is included in our parent chart:
user@debian:~$ helm template ./nginx
---
# Source: nginx/charts/mariadb/templates/serviceaccount.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: RELEASE-NAME-mariadb
namespace: default
labels:
app.kubernetes.io/name: mariadb
helm.sh/chart: mariadb-9.3.16
app.kubernetes.io/instance: RELEASE-NAME
app.kubernetes.io/managed-by: Helm
annotations:
---
# Source: nginx/charts/mariadb/templates/secrets.yaml
apiVersion: v1
kind: Secret
metadata:
name: RELEASE-NAME-mariadb
namespace: default
labels:
app.kubernetes.io/name: mariadb
helm.sh/chart: mariadb-9.3.16
app.kubernetes.io/instance: RELEASE-NAME
app.kubernetes.io/managed-by: Helm
type: Opaque
data:
mariadb-root-password: "Q0tHdHJMTE5xdw=="
mariadb-password: "anE1bmJ6TEhwYg=="
---
To prepare for our next exercise, let’s remove MariaDB from the list of dependencies in Chart.yaml as
dependencies:
- name: mariadb
repository: https://charts.bitnami.com/bitnami
version: ~9.3
The final content will be:
apiVersion: v2
name: nginx
description: Basic Nginx website for our company
# A chart can be either an 'application' or a 'library' chart.
#
# Application charts are a collection of templates that can be packaged into versioned archives
# to be deployed.
#
# Library charts provide useful utilities or functions for the chart developer. They're included as
# a dependency of application charts to inject those utilities and functions into the rendering
# pipeline. Library charts do not define any templates and therefore cannot be deployed.
type: application
# This is the chart version. This version number should be incremented each time you make changes
# to the chart and its templates, including the app version.
# Versions are expected to follow Semantic Versioning (https://semver.org/)
version: 0.1.0
# This is the version number of the application being deployed. This version number should be
# incremented each time you make changes to the application. Versions are not expected to
# follow Semantic Versioning. They should reflect the version the application is using.
# It is recommended to use it with quotes.
appVersion: "1.16.0"
maintainers:
- email: [email protected]
name: John Smith
2. Adding Dependencies Manually in the “charts” Directory
Although managing chart dependencies through the Chart.yaml file is the more elegant solution it is sometimes not possible.
We mentioned that dependencies can be dropped in the charts directory. In fact, when we ran helm dependency update ./nginx
all Helm did was download an archived MariaDB chart and drop it into that location.
Let’s move this out of our parent chart.
mv nginx/charts/* .
And extract the archive’s contents.
tar xzf mariadb*.tgz
The MariaDB chart will be extracted into the mariadb directory. This will serve its purpose for our next scenario.
We can imagine this is a chart we worked hard on. And now we want to include it as a dependency. To do that, all that is required is to move (or copy) it to the charts directory of our parent chart. But before we do that, let’s check the status of our Nginx chart.
helm template ./nginx
As expected, there is no MariaDB-related content anymore. Now, let’s move the MariaDB chart to our parent chart’s charts directory.
mv mariadb nginx/charts
Now, if we run helm template ./nginx
again, we will see that the MariaDB chart is now included.
user@debian:~$ helm template ./nginx
---
# Source: nginx/charts/mariadb/templates/serviceaccount.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: RELEASE-NAME-mariadb
namespace: default
labels:
app.kubernetes.io/name: mariadb
helm.sh/chart: mariadb-9.3.16
app.kubernetes.io/instance: RELEASE-NAME
app.kubernetes.io/managed-by: Helm
annotations:
---
# Source: nginx/charts/mariadb/templates/secrets.yaml
apiVersion: v1
kind: Secret
metadata:
name: RELEASE-NAME-mariadb
namespace: default
labels:
app.kubernetes.io/name: mariadb
helm.sh/chart: mariadb-9.3.16
app.kubernetes.io/instance: RELEASE-NAME
app.kubernetes.io/managed-by: Helm
type: Opaque
data:
mariadb-root-password: "Rm5jT2gwa2VBTQ=="
mariadb-password: "VGVmVXRtak00RQ=="
---
Allowing the User to Switch Chart Dependencies On/Off
Like charts, dependencies can be smart, too, meaning they can adapt to the user’s needs instead of statically being included all the time, no matter what.
For example, a WordPress website can be sped up with Memcached. However, not all users will want to use Memcached for their own reasons. Maybe it doesn’t work well for their scenario, or it breaks something. In such cases, we can let our users control what dependency charts will be used and which won’t be used. In our case, we can make the use of Memcached optional by doing something like this in the Charts.yaml file.
dependencies:
- name: mariadb
repository: https://charts.bitnami.com/bitnami
version: 9.x.x
- name: memcached
condition: memcached.enabled
repository: https://charts.bitnami.com/bitnami
version: 5.x.x
The line condition: memcached.enabled
makes sure that the Memcached dependency chart will be used only if the user sets memcached.enabled
to true
in his values.yaml file.
Suppose we build the chart with the following content in the values.yaml file:
memcached:
enabled: false
This makes sure that Memcached, by default, won’t be used.
This on/off feature gives the user a chance to enable it only if they manually set enabled:
to true
. This way, we don’t intrude on our user’s preferences. Instead, we allow them to enable optional content only if they want it.
Check out the Helm for the Absolute Beginners course.
Conclusion
Helm chart dependencies refer to other charts that the Helm chart relies on to function correctly. Prior to installing the primary chart, Helm will automatically download and install any necessary dependencies.
Users can choose which dependency charts to use by setting them as optional in Charts.yaml with a condition. This allows users to enable or disable dependencies based on their specific requirements.
More on Helm: