Merge @zempashi's Helm content 🎉

This commit is contained in:
Jerome Petazzoni
2021-04-12 18:28:56 +02:00
2 changed files with 529 additions and 0 deletions

View File

@@ -0,0 +1,338 @@
# 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 `redis` image)
- 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.yaml` file
- 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 the `dependencies` section:
```yaml
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 `condition` field gives us a way to enable/disable the dependency:
```yaml
conditions: redis.enabled
```
- Here, we can disable Redis with the Helm flag `--set redis.enabled=false`
(or set that value in a `values.yaml` file)
- 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:
```bash
helm dependency update
```
(Or `helm dep up`)
]
- This wil create `Chart.lock` and 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.lock` can (should!) be added to our source tree
- `Chart.lock` can (should!) regularly be updated
---
## Loose dependencies
- Here is an example of loose version requirement:
```yaml
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 in `Chart.lock`
`helm dependency update` = update `Chart.lock` (and run `build`)
- When the dependency gets updated, we can/should:
- `helm dep up` (update `Chart.lock` and fetch new chart)
- test!
- if everything is fine, `git add Chart.lock` and 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 `redis` Service to be named `redis`
- Our Redis chart uses a different Service name by default
- Service name is `{{ template "redis.fullname" . }}-master`
- `redis.fullname` looks 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 `fullnameOverride` to `redis`:
- the `{{ template ... }}` block will output `redis`
- the Service name will be `redis-master`
- A parent chart can set values for its dependencies
- For example, in the parent's `values.yaml`:
```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 `tpl` function, on the child side
- evaluated in the context of the child, with no access to parent variables
<!-- FIXME this probably deserves an example, but I can't imagine one right now 😅 -->
---
## Getting rid of the `-master`
- Even if we set that `fullnameOverride`, the Service name will be `redis-master`
- To remove the `-master` suffix, 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.yaml` accordingly
---
## Embedding a dependency
.exercise[
- Decompress the chart:
```yaml
cd charts
tar zxf redis-*.tgz
cd ..
```
- Edit `Chart.yaml` and update the `dependencies` section:
```yaml
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`:
```yaml
dependencies:
- name: redis
version: '*'
alias: querycache
- name: redis
version: '*'
alias: celeryqueue
```
- `.Chart.Name` will be set to the `alias`
---
class: extra-details
## Compatibility with Helm 2
- Chart `apiVersion: v1` is 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 in `requirements.yaml`
(and we should commit `requirements.lock` instead of `Chart.lock`)
???
:EN:- Depending on other charts
:EN:- Charts within charts
:FR:- Dépendances entre charts
:FR:- Un chart peut en cacher un autre

View File

@@ -0,0 +1,191 @@
# Helm and invalid values
- A lot of Helm charts let us specify an image tag like this:
```bash
helm install ... --set image.tag=v1.0
```
- What happens if we make a small mistake, like this:
```bash
helm install ... --set imagetag=v1.0
```
- Or even, like this:
```bash
helm install ... --set image=v1.0
```
🤔
---
## Making mistakes
- In the first case:
- we set `imagetag=v1.0` instead of `image.tag=v1.0`
- Helm will ignore that value (if it's not used anywhere in templates)
- the chart is deployed with the default value instead
- In the second case:
- we set `image=v1.0` instead of `image.tag=v1.0`
- `image` will be a string instead of an object
- Helm will *probably* fail when trying to evaluate `image.tag`
---
## Preventing mistakes
- To prevent the first mistake, we need to tell Helm:
*"let me know if any additional (unknonw) value was set!"*
- To prevent the second mistake, we need to tell Helm:
*"`image` should be an object, and `image.tag` should be a string!"*
- We can do this with *values schema validation*
---
## Helm values schema validation
- We can write a spec representing the possible values accepted by the chart
- Helm will check the validity of the values before trying to install/upgrade
- If it finds problems, it will stop immediately
- The spec uses [JSON Schema](https://json-schema.org/):
*JSON Schema is a vocabulary that allows you to annotate and validate JSON documents.*
- JSON Schema is designed for JSON, but can easily work with YAML too
(or any language with `map|dict|associativearray` and `list|array|sequence|tuple`)
---
## In practice
- We need to put the JSON Schema spec in a file called `values.schema.json`
(at the root of our chart; right next to `values.yaml` etc.)
- The file is optional
- We don't need to register or declare it in `Chart.yaml` or anywhere
- Let's write a schema that will verify that ...
- `image.repository` is an official image (string without slashes or dots)
- `image.pullPolicy` can only be `Always`, `Never`, `IfNotPresent`
---
## `values.schema.json`
```json
{
"$schema": "http://json-schema.org/schema#",
"type": "object",
"properties": {
"image": {
"type": "object",
"properties": {
"repository": {
"type": "string",
"pattern": "^[a-z0-9-_]+$"
},
"pullPolicy": {
"type": "string",
"pattern": "^(Always|Never|IfNotPresent)$"
}
}
}
}
}
```
---
## Testing our schema
- Let's try to install a couple releases with that schema!
.exercise[
- Try an invalid `pullPolicy`:
```bash
helm install broken --set image.pullPolicy=ShallNotPass
```
- Try an invalid value:
```bash
helm install should-break --set ImAgeTAg=toto
```
]
- The first one fails, but the second one still passes ...
- Why?
---
## Bailing out on unkown properties
- We told Helm what properties (values) were valid
- We didn't say what to do about additional (unknown) properties!
- We can fix that with `"additionalProperties": false`
.exercise[
- Edit `values.schema.json` to add `"additionalProperties": false`
```json
{
"$schema": "http://json-schema.org/schema#",
"type": "object",
"additionalProperties": false,
"properties": {
...
```
]
---
## Testing with unknown properties
.exercise[
- Try to pass an extra property:
```bash
helm install should-break --set ImAgeTAg=toto
```
- Try to pass an extra nested property:
```bash
helm install does-it-work --set image.hello=world
```
]
The first command should break.
The second will not.
`"additionalProperties": false` needs to be specified at each level.
???
:EN:- Helm schema validation
:FR:- Validation de schema Helm