Helm Chart Dependencies

In this blog, we will see about Helm Chart Dependencies or simply how a chart may depend on other charts.
For example, if we would build a chart that could launch a WordPress website, this would also depend on a chart for MySQL or MariaDB, and, possibly, also 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 letting Helm download necessary dependency files.
- Dropping dependency charts (the files and directories they contain), manually, in the charts directory.
Want a quick guide to Helm concepts and features? Check out this video.
1. Managing Dependencies with the Chart.yaml file
Let’s assume that for some reason, our chart would need MariaDB. How do we add the MariaDB chart as a dependency? First, let’s open up our Chart.yaml file for editing using an Editor.
Under the description
of our chart, we 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 important lines in the content we added. First,
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
helm repo add bitnami https://charts.bitnami.com/bitnami
The address we add to our repository:
field is the same one we would use in a helm repo add
command.
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. So this is a good way to make sure we pull in the latest chart version with a certain feature set that is currently compatible with our parent chart. 9.4 and 9.5 versions might introduce important feature changes that could make it incompatible with the current app(s) of our parent chart.
But we did not analyze the first line:
- name: mariadb
The name is pretty straightforward. We just use the name of the chart 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, but to make it easier to remember how to write this, you can think of it this way:
Since we list multiple 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. There 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! A command like helm template ./nginx
will show us that indeed, now the MariaDB dependency chart is included in our parent chart:
[email protected]:~$ 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
Managing dependencies through the Chart.yaml file is the more elegant solution. But, sometimes, that won’t be possible, or won’t be desired.
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.
[email protected]:~$ 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 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. But 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. For example, for Memcached we could do something like this; imagine this content 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.
If we build the chart with the following content in the values.yaml file:
memcached:
enabled: false
We can make sure that Memcached, by default, won’t be used. This 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 and give them a chance to enable optional content only if they really want it.
Checkout the Helm for the Absolute Beginners course here
Checkout the Complete Kubernetes learning path here