6.9 KiB
Charts using other charts
-
Helm charts can have dependencies on other charts
-
These dependencies will help us to share or reuse components
(so that we write and maintain less manifests, less templates, less code!)
-
As an example, we will use a community chart for Redis
-
This will help people who write charts, and people who use them
-
... And potentially remove a lot of code! ✌️
Redis in DockerCoins
-
In the DockerCoins demo app, we have 5 components:
- 2 internal webservices
- 1 worker
- 1 public web UI
- 1 Redis data store
-
Every component is running some custom code, except Redis
-
Every component is using a custom image, except Redis
(which is using the official
redisimage) -
Could we use a standard chart for Redis?
-
Yes! Dependencies to the rescue!
Adding our dependency
-
First, we will add the dependency to the
Chart.yamlfile -
Then, we will ask Helm to download that dependency
-
We will also lock the dependency
(lock it to a specific version, to ensure reproducibility)
Declaring the dependency
- First, let's edit
Chart.yaml
.exercise[
- In
Chart.yaml, fill thedependenciessection:dependencies: - name: redis version: 11.0.5 repository: https://charts.bitnami.com/bitnami condition: redis.enabled
]
Where do that repository and version come from?
We're assuming here that we did our reserach, or that our resident Helm expert advised us to use Bitnami's Redis chart.
Conditions
-
The
conditionfield gives us a way to enable/disable the dependency:conditions: redis.enabled -
Here, we can disable Redis with the Helm flag
--set redis.enabled=false(or set that value in a
values.yamlfile) -
Of course, this is mostly useful for optional dependencies
(otherwise, the app ends up being broken since it'll miss a component)
Lock & Load!
- After adding the dependency, we ask Helm to pin an download it
.exercise[
-
Ask Helm:
helm dependency update(Or
helm dep up)
]
- This wil create
Chart.lockand fetch the dependency
What's Chart.lock?
-
This is a common pattern with dependencies
(see also:
Gemfile.lock,package.json.lock, and many others) -
This lets us define loose dependencies in
Chart.yaml(e.g. "version 11.whatever, but below 12")
-
But have the exact version used in
Chart.lock -
This ensures reproducible deployments
-
Chart.lockcan (should!) be added to our source tree -
Chart.lockcan (should!) regularly be updated
Loose dependencies
-
Here is an example of loose version requirement:
dependencies: - name: redis version: ">=11, <12" repository: https://charts.bitnami.com/bitnami -
This makes sure that we have the most recent version in the 11.x train
-
... But without upgrading to version 12.x
(because it might be incompatible)
build vs update
-
Helm actually offers two commands to manage dependencies:
helm dependency build= fetch dependencies listed inChart.lockhelm dependency update= updateChart.lock(and runbuild) -
When the dependency gets updated, we can/should:
-
helm dep up(updateChart.lockand fetch new chart) -
test!
-
if everything is fine,
git add Chart.lockand commit
-
Where are my dependencies?
-
Dependencies are downloaded to the
charts/subdirectory -
When they're downloaded, they stay in compressed format (
.tgz) -
Should we commit them to our code repository?
-
Pros:
- more resilient to internet/mirror failures/decomissioning
-
Cons:
-
can add a lot of weight to the repo if charts are big or change often
-
this can be solved by extra tools like git-lfs
-
Dependency tuning
-
DockerCoins expects the
redisService to be namedredis -
Our Redis chart uses a different Service name by default
-
Service name is
{{ template "redis.fullname" . }}-master -
redis.fullnamelooks like this:{{- define "redis.fullname" -}} {{- if .Values.fullnameOverride -}} {{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} {{- else -}} [...] {{- end }} {{- end }} -
How do we fix this?
Setting dependency variables
-
If we set
fullnameOverridetoredis:-
the
{{ template ... }}block will outputredis -
the Service name will be
redis-master
-
-
A parent chart can set values for its dependencies
-
For example, in the parent's
values.yaml:redis: # Name of the dependency fullnameOverride: redis # Value passed to redis cluster: # Other values passed to redis enabled: false -
User can also set variables with
--set=or with--values=
class: extra-details
Passing templates
-
We can even pass template
{{ include "template.name" }}, but warning:-
need to be evaluated with the
tplfunction, on the child side -
evaluated in the context of the child, with no access to parent variables
-
Getting rid of the -master
-
Even if we set that
fullnameOverride, the Service name will beredis-master -
To remove the
-mastersuffix, we need to edit the chart itself -
To edit the Redis chart, we need to embed it in our own chart
-
We need to:
-
decompress the chart
-
adjust
Chart.yamlaccordingly
-
Embedding a dependency
.exercise[
-
Decompress the chart:
cd charts tar zxf redis-*.tgz cd .. -
Edit
Chart.yamland update thedependenciessection:dependencies: - name: redis version: '*' # No need to constraint version, from local files -
Run
helm dep update
]
Updating the dependency
-
Now we can edit the Service name
(it should be in
charts/redis/templates/redis-master-svc.yaml) -
Then try to deploy the whole chart!
Embedding a dependency multiple times
-
What if we need multiple copies of the same subchart?
(for instance, if we need two completely different Redis servers)
-
We can declare a dependency multiple times, and specify an
alias:dependencies: - name: redis version: '*' alias: querycache - name: redis version: '*' alias: celeryqueue -
.Chart.Namewill be set to thealias
class: extra-details
Compatibility with Helm 2
-
Chart
apiVersion: v1is the only version supported by Helm 2 -
Chart v1 is also supported by Helm 3
-
Use v1 if you want to be compatible with Helm 2
-
Instead of
Chart.yaml, dependencies are defined inrequirements.yaml(and we should commit
requirements.lockinstead ofChart.lock)
???
:EN:- Depending on other charts :EN:- Charts within charts
:FR:- Dépendances entre charts :FR:- Un chart peut en cacher un autre