mirror of
https://github.com/jpetazzo/container.training.git
synced 2026-02-14 17:49:59 +00:00
Big Helm update
Revamp most of the Helm content: - overview of Helm moved to helm-intro.md - explanation of chart format in helm-chart-format.md - the very crude chart example is now in helm-create-basic-chart.md - the more advanced chart (with templates etc) is now in helm-create-better-chart.md - deep dive into Helm internals (how it stores it's data) in helm-secrets.md This is all for Helm 3. Helm 2 is not supported anymore.
This commit is contained in:
@@ -1,114 +0,0 @@
|
||||
## Creating a chart
|
||||
|
||||
- We are going to show a way to create a *very simplified* chart
|
||||
|
||||
- In a real chart, *lots of things* would be templatized
|
||||
|
||||
(Resource names, service types, number of replicas...)
|
||||
|
||||
.exercise[
|
||||
|
||||
- Create a sample chart:
|
||||
```bash
|
||||
helm create dockercoins
|
||||
```
|
||||
|
||||
- Move away the sample templates and create an empty template directory:
|
||||
```bash
|
||||
mv dockercoins/templates dockercoins/default-templates
|
||||
mkdir dockercoins/templates
|
||||
```
|
||||
|
||||
]
|
||||
|
||||
---
|
||||
|
||||
## Exporting the YAML for our application
|
||||
|
||||
- The following section assumes that DockerCoins is currently running
|
||||
|
||||
.exercise[
|
||||
|
||||
- Create one YAML file for each resource that we need:
|
||||
.small[
|
||||
```bash
|
||||
|
||||
while read kind name; do
|
||||
kubectl get -o yaml $kind $name > dockercoins/templates/$name-$kind.yaml
|
||||
done <<EOF
|
||||
deployment worker
|
||||
deployment hasher
|
||||
daemonset rng
|
||||
deployment webui
|
||||
deployment redis
|
||||
service hasher
|
||||
service rng
|
||||
service webui
|
||||
service redis
|
||||
EOF
|
||||
```
|
||||
]
|
||||
|
||||
]
|
||||
|
||||
---
|
||||
|
||||
## Testing our helm chart
|
||||
|
||||
.exercise[
|
||||
|
||||
- Let's install our helm chart! (`dockercoins` is the path to the chart)
|
||||
```
|
||||
helm install dockercoins
|
||||
```
|
||||
]
|
||||
|
||||
--
|
||||
|
||||
- Since the application is already deployed, this will fail:<br>
|
||||
`Error: release loitering-otter failed: services "hasher" already exists`
|
||||
|
||||
- To avoid naming conflicts, we will deploy the application in another *namespace*
|
||||
|
||||
---
|
||||
|
||||
## Switching to another namespace
|
||||
|
||||
- We can create a new namespace and switch to it
|
||||
|
||||
(Helm will automatically use the namespace specified in our context)
|
||||
|
||||
- We can also tell Helm which namespace to use
|
||||
|
||||
.exercise[
|
||||
|
||||
- Tell Helm to use a specific namespace:
|
||||
```bash
|
||||
helm install dockercoins --namespace=magenta
|
||||
```
|
||||
|
||||
]
|
||||
|
||||
---
|
||||
|
||||
## Checking our new copy of DockerCoins
|
||||
|
||||
- We can check the worker logs, or the web UI
|
||||
|
||||
.exercise[
|
||||
|
||||
- Retrieve the NodePort number of the web UI:
|
||||
```bash
|
||||
kubectl get service webui --namespace=magenta
|
||||
```
|
||||
|
||||
- Open it in a web browser
|
||||
|
||||
- Look at the worker logs:
|
||||
```bash
|
||||
kubectl logs deploy/worker --tail=10 --follow --namespace=magenta
|
||||
```
|
||||
|
||||
]
|
||||
|
||||
Note: it might take a minute or two for the worker to start.
|
||||
@@ -1,367 +0,0 @@
|
||||
# Creating Helm charts
|
||||
|
||||
- We are going to create a generic Helm chart
|
||||
|
||||
- We will use that Helm chart to deploy DockerCoins
|
||||
|
||||
- Each component of DockerCoins will have its own *release*
|
||||
|
||||
- In other words, we will "install" that Helm chart multiple times
|
||||
|
||||
(one time per component of DockerCoins)
|
||||
|
||||
---
|
||||
|
||||
## Creating a generic chart
|
||||
|
||||
- Rather than starting from scratch, we will use `helm create`
|
||||
|
||||
- This will give us a basic chart that we will customize
|
||||
|
||||
.exercise[
|
||||
|
||||
- Create a basic chart:
|
||||
```bash
|
||||
cd ~
|
||||
helm create helmcoins
|
||||
```
|
||||
|
||||
]
|
||||
|
||||
This creates a basic chart in the directory `helmcoins`.
|
||||
|
||||
---
|
||||
|
||||
## What's in the basic chart?
|
||||
|
||||
- The basic chart will create a Deployment and a Service
|
||||
|
||||
- Optionally, it will also include an Ingress
|
||||
|
||||
- If we don't pass any values, it will deploy the `nginx` image
|
||||
|
||||
- We can override many things in that chart
|
||||
|
||||
- Let's try to deploy DockerCoins components with that chart!
|
||||
|
||||
---
|
||||
|
||||
## Writing `values.yaml` for our components
|
||||
|
||||
- We need to write one `values.yaml` file for each component
|
||||
|
||||
(hasher, redis, rng, webui, worker)
|
||||
|
||||
- We will start with the `values.yaml` of the chart, and remove what we don't need
|
||||
|
||||
- We will create 5 files:
|
||||
|
||||
hasher.yaml, redis.yaml, rng.yaml, webui.yaml, worker.yaml
|
||||
|
||||
---
|
||||
|
||||
## Getting started
|
||||
|
||||
- For component X, we want to use the image dockercoins/X:v0.1
|
||||
|
||||
(for instance, for rng, we want to use the image dockercoins/rng:v0.1)
|
||||
|
||||
- Exception: for redis, we want to use the official image redis:latest
|
||||
|
||||
.exercise[
|
||||
|
||||
- Write minimal YAML files for the 5 components, specifying only the image
|
||||
|
||||
]
|
||||
|
||||
--
|
||||
|
||||
*Hint: our YAML files should look like this.*
|
||||
|
||||
```yaml
|
||||
### rng.yaml
|
||||
image:
|
||||
repository: dockercoins/`rng`
|
||||
tag: v0.1
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Deploying DockerCoins components
|
||||
|
||||
- For convenience, let's work in a separate namespace
|
||||
|
||||
.exercise[
|
||||
|
||||
- Create a new namespace:
|
||||
```bash
|
||||
kubectl create namespace helmcoins
|
||||
```
|
||||
|
||||
- Switch to that namespace:
|
||||
```bash
|
||||
kns helmcoins
|
||||
```
|
||||
|
||||
]
|
||||
|
||||
---
|
||||
|
||||
## Deploying the chart
|
||||
|
||||
- To install a chart, we can use the following command:
|
||||
```bash
|
||||
helm install [--name `X`] <chart>
|
||||
```
|
||||
|
||||
- We can also use the following command, which is idempotent:
|
||||
```bash
|
||||
helm upgrade --install `X` chart
|
||||
```
|
||||
|
||||
.exercise[
|
||||
|
||||
- Install the 5 components of DockerCoins:
|
||||
```bash
|
||||
for COMPONENT in hasher redis rng webui worker; do
|
||||
helm upgrade --install $COMPONENT helmcoins/ --values=$COMPONENT.yaml
|
||||
done
|
||||
```
|
||||
|
||||
]
|
||||
|
||||
---
|
||||
|
||||
## Checking what we've done
|
||||
|
||||
- Let's see if DockerCoins is working!
|
||||
|
||||
.exercise[
|
||||
|
||||
- Check the logs of the worker:
|
||||
```bash
|
||||
stern worker
|
||||
```
|
||||
|
||||
- Look at the resources that were created:
|
||||
```bash
|
||||
kubectl get all
|
||||
```
|
||||
|
||||
]
|
||||
|
||||
There are *many* issues to fix!
|
||||
|
||||
---
|
||||
|
||||
## Service names
|
||||
|
||||
- Our services should be named `rng`, `hasher`, etc., but they are named differently
|
||||
|
||||
- Look at the YAML template used for the services
|
||||
|
||||
- Does it look like we can override the name of the services?
|
||||
|
||||
--
|
||||
|
||||
- *Yes*, we can use `.Values.nameOverride`
|
||||
|
||||
- This means setting `nameOverride` in the values YAML file
|
||||
|
||||
---
|
||||
|
||||
## Setting service names
|
||||
|
||||
- Let's add `nameOverride: X` in each values YAML file!
|
||||
|
||||
(where X is hasher, redis, rng, etc.)
|
||||
|
||||
.exercise[
|
||||
|
||||
- Edit the 5 YAML files to add `nameOverride: X`
|
||||
|
||||
- Deploy the updated Chart:
|
||||
```bash
|
||||
for COMPONENT in hasher redis rng webui worker; do
|
||||
helm upgrade --install $COMPONENT helmcoins/ --values=$COMPONENT.yaml
|
||||
done
|
||||
```
|
||||
(Yes, this is exactly the same command as before!)
|
||||
|
||||
]
|
||||
|
||||
---
|
||||
|
||||
## Checking what we've done
|
||||
|
||||
.exercise[
|
||||
|
||||
- Check the service names:
|
||||
```bash
|
||||
kubectl get services
|
||||
```
|
||||
Great! (We have a useless service for `worker`, but let's ignore it for now.)
|
||||
|
||||
- Check the state of the pods:
|
||||
```bash
|
||||
kubectl get pods
|
||||
```
|
||||
Not so great... Some pods are *not ready.*
|
||||
|
||||
]
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting pods
|
||||
|
||||
- The easiest way to troubleshoot pods is to look at *events*
|
||||
|
||||
- We can look at all the events on the cluster (with `kubectl get events`)
|
||||
|
||||
- Or we can use `kubectl describe` on the objects that have problems
|
||||
|
||||
(`kubectl describe` will retrieve the events related to the object)
|
||||
|
||||
.exercise[
|
||||
|
||||
- Check the events for the redis pods:
|
||||
```bash
|
||||
kubectl describe pod -l app.kubernetes.io/name=redis
|
||||
```
|
||||
|
||||
]
|
||||
|
||||
What's going on?
|
||||
|
||||
---
|
||||
|
||||
## Healthchecks
|
||||
|
||||
- The default chart defines healthchecks doing HTTP requests on port 80
|
||||
|
||||
- That won't work for redis and worker
|
||||
|
||||
(redis is not HTTP, and not on port 80; worker doesn't even listen)
|
||||
|
||||
--
|
||||
|
||||
- We could comment out the healthchecks
|
||||
|
||||
- We could also make them conditional
|
||||
|
||||
- This sounds more interesting, let's do that!
|
||||
|
||||
---
|
||||
|
||||
## Conditionals
|
||||
|
||||
- We need to enclose the healthcheck block with:
|
||||
|
||||
`{{ if CONDITION }}` at the beginning
|
||||
|
||||
`{{ end }}` at the end
|
||||
|
||||
- For the condition, we will use `.Values.healthcheck`
|
||||
|
||||
---
|
||||
|
||||
## Updating the deployment template
|
||||
|
||||
.exercise[
|
||||
|
||||
- Edit `helmcoins/templates/deployment.yaml`
|
||||
|
||||
- Before the healthchecks section (it starts with `livenessProbe:`), add:
|
||||
|
||||
`{{ if .Values.healthcheck }}`
|
||||
|
||||
- After the healthchecks section (just before `resources:`), add:
|
||||
|
||||
`{{ end }}`
|
||||
|
||||
- Edit `hasher.yaml`, `rng.yaml`, `webui.yaml` to add:
|
||||
|
||||
`healthcheck: true`
|
||||
|
||||
]
|
||||
|
||||
---
|
||||
|
||||
## Update the deployed charts
|
||||
|
||||
- We can now apply the new templates (and the new values)
|
||||
|
||||
.exercise[
|
||||
|
||||
- Use the same command as earlier to upgrade all five components
|
||||
|
||||
- Use `kubectl describe` to confirm that `redis` starts correctly
|
||||
|
||||
- Use `kubectl describe` to confirm that `hasher` still has healthchecks
|
||||
|
||||
]
|
||||
|
||||
---
|
||||
|
||||
## Is it working now?
|
||||
|
||||
- If we look at the worker logs, it appears that the worker is still stuck
|
||||
|
||||
- What could be happening?
|
||||
|
||||
--
|
||||
|
||||
- The redis service is not on port 80!
|
||||
|
||||
- We need to update the port number in redis.yaml
|
||||
|
||||
- We also need to update the port number in deployment.yaml
|
||||
|
||||
(it is hard-coded to 80 there)
|
||||
|
||||
---
|
||||
|
||||
## Setting the redis port
|
||||
|
||||
.exercise[
|
||||
|
||||
- Edit `redis.yaml` to add:
|
||||
```yaml
|
||||
service:
|
||||
port: 6379
|
||||
```
|
||||
|
||||
- Edit `helmcoins/templates/deployment.yaml`
|
||||
|
||||
- The line with `containerPort` should be:
|
||||
```yaml
|
||||
containerPort: {{ .Values.service.port }}
|
||||
```
|
||||
|
||||
]
|
||||
|
||||
---
|
||||
|
||||
## Apply changes
|
||||
|
||||
- Re-run the for loop to execute `helm upgrade` one more time
|
||||
|
||||
- Check the worker logs
|
||||
|
||||
- This time, it should be working!
|
||||
|
||||
---
|
||||
|
||||
## Extra steps
|
||||
|
||||
- We don't need to create a service for the worker
|
||||
|
||||
- We can put the whole service block in a conditional
|
||||
|
||||
(this will require additional changes in other files referencing the service)
|
||||
|
||||
- We can set the webui to be a NodePort service
|
||||
|
||||
- We can change the number of workers with `replicaCount`
|
||||
|
||||
- And much more!
|
||||
239
slides/k8s/helm-chart-format.md
Normal file
239
slides/k8s/helm-chart-format.md
Normal file
@@ -0,0 +1,239 @@
|
||||
# Helm chart format
|
||||
|
||||
- What exactly is a chart?
|
||||
|
||||
- What's in it?
|
||||
|
||||
- What would be involved in creating a chart?
|
||||
|
||||
(we won't create a chart, but we'll see the required steps)
|
||||
|
||||
---
|
||||
|
||||
## What is a chart
|
||||
|
||||
- A chart is a set of files
|
||||
|
||||
- Some of these files are mandatory for the chart to be viable
|
||||
|
||||
(more on that later)
|
||||
|
||||
- These files are typically packed in a tarball
|
||||
|
||||
- These tarballs are stored in "repos"
|
||||
|
||||
(which can be static HTTP servers)
|
||||
|
||||
- We can install from a repo, from a local tarball, or an unpacked tarball
|
||||
|
||||
(the latter option is preferred when developing a chart)
|
||||
|
||||
---
|
||||
|
||||
## What's in a chart
|
||||
|
||||
- A chart must have at least:
|
||||
|
||||
- a `templates` directory, with YAML manifests for Kubernetes resources
|
||||
|
||||
- a `values.yaml` file, containing (tunable) parameters for the chart
|
||||
|
||||
- a `Chart.yaml` file, containing metadata (name, version, description ...)
|
||||
|
||||
- Let's look at a simple chart, `stable/tomcat`
|
||||
|
||||
---
|
||||
|
||||
## Downloading a chart
|
||||
|
||||
- We can use `helm pull` to download a chart from a repo
|
||||
|
||||
.exercise[
|
||||
|
||||
- Download the tarball for `stable/tomcat`:
|
||||
```bash
|
||||
helm pull stable/tomcat
|
||||
```
|
||||
(This will create a file named `tomcat-X.Y.Z.tgz`.)
|
||||
|
||||
- Or, download + untar `stable/tomcat`:
|
||||
```bash
|
||||
helm pull stable/tomcat --untar
|
||||
```
|
||||
(This will create a directory named `tomcat`.)
|
||||
|
||||
]
|
||||
|
||||
---
|
||||
|
||||
## Looking at the chart's content
|
||||
|
||||
- Let's look at the files and directories in the `tomcat` chart
|
||||
|
||||
.exercise[
|
||||
|
||||
- Display the tree structure of the chart we just downloaded:
|
||||
```bash
|
||||
tree tomcat
|
||||
```
|
||||
|
||||
]
|
||||
|
||||
We see the components mentioned above: `Chart.yaml`, `templates/`, `values.yaml`.
|
||||
|
||||
---
|
||||
|
||||
## Templates
|
||||
|
||||
- The `templates/` directory contains YAML manifests for Kubernetes resources
|
||||
|
||||
(Deployments, Services, etc.)
|
||||
|
||||
- These manifests can contain template tags
|
||||
|
||||
(using the standard Go template library)
|
||||
|
||||
|
||||
.exercise[
|
||||
|
||||
- Look at the template file for the tomcat Service resource:
|
||||
```bash
|
||||
cat tomcat/templates/appsrv-svc.yaml
|
||||
```
|
||||
|
||||
]
|
||||
|
||||
---
|
||||
|
||||
## Analyzing the template file
|
||||
|
||||
- Tags are identified by `{{ ... }}`
|
||||
|
||||
- `{{ template "x.y" }}` expands a [named template](https://helm.sh/docs/chart_template_guide/named_templates/#declaring-and-using-templates-with-define-and-template)
|
||||
|
||||
(previously defined with `{{ define "x.y "}}...stuff...{{ end }}`)
|
||||
|
||||
- The `.` in `{{ template "x.y" . }}` is the *context* for that named template
|
||||
|
||||
(so that the named template block can access variables from the local context)
|
||||
|
||||
- `{{ .Release.xyz }}` refers to [built-in variables](https://helm.sh/docs/chart_template_guide/builtin_objects/) initialized by Helm
|
||||
|
||||
(indicating the chart name, version, whether we are installing or upgrading ...)
|
||||
|
||||
- `{{ .Values.xyz }}` refers to tunable/settable [values](https://helm.sh/docs/chart_template_guide/values_files/)
|
||||
|
||||
(more on that in a minute)
|
||||
|
||||
---
|
||||
|
||||
## Values
|
||||
|
||||
- Each chart comes with a
|
||||
[values file](https://helm.sh/docs/chart_template_guide/values_files/)
|
||||
|
||||
- It's a YAML file containing a set of default parameters for the chart
|
||||
|
||||
- The values can be accessed in templates with e.g. `{{ .Values.x.y }}`
|
||||
|
||||
(corresponding to field `y` in map `x` in the values file)
|
||||
|
||||
- The values can be set or overridden when installing or ugprading a chart:
|
||||
|
||||
- with `--set x.y=z` (can be used multiple times to set multiple values)
|
||||
|
||||
- with `--values some-yaml-file.yaml` (set a bunch of values from a file)
|
||||
|
||||
- Charts following best practices will have values following specific patterns
|
||||
|
||||
(e.g. having a `service` map allowing to set `service.type` etc.)
|
||||
|
||||
---
|
||||
|
||||
## Other useful tags
|
||||
|
||||
- `{{ if x }} y {{ end }}` allows to include `y` if `x` evaluates to `true`
|
||||
|
||||
(can be used for e.g. healthchecks, annotations, or even an entire resource)
|
||||
|
||||
- `{{ range x }} y {{ end }}` iterates over `x`, evaluating `y` each time
|
||||
|
||||
(the elements of `x` are assigned to `.` in the range scope)
|
||||
|
||||
- `{{- x }}`/`{{ x -}}` will remove whitespace on the left/right
|
||||
|
||||
- The whole [Sprig](http://masterminds.github.io/sprig/) library, with additions:
|
||||
|
||||
`lower` `upper` `quote` `trim` `default` `b64enc` `b64dec` `sha256sum` `indent` `toYaml` ...
|
||||
|
||||
---
|
||||
|
||||
## Pipelines
|
||||
|
||||
- `{{ quote blah }}` can also be expressed as `{{ blah | quote }}`
|
||||
|
||||
- With multiple arguments, `{{ x y z }}` can be expressed as `{{ z | x y }}`)
|
||||
|
||||
- Example: `{{ .Values.annotations | toYaml | indent 4 }}`
|
||||
|
||||
- transforms the map under `annotations` into a YAML string
|
||||
|
||||
- indents it with 4 spaces (to match the surrounding context)
|
||||
|
||||
- Pipelines are not specific to Helm, but a feature of Go templates
|
||||
|
||||
(check the [Go text/template documentation](https://golang.org/pkg/text/template/) for more details and examples)
|
||||
|
||||
---
|
||||
|
||||
## README and NOTES.txt
|
||||
|
||||
- At the top-level of the chart, it's a good idea to have a README
|
||||
|
||||
- It will be viewable with e.g. `helm show readme stable/tomcat`
|
||||
|
||||
- In the `templates/` directory, we can also have a `NOTES.txt` file
|
||||
|
||||
- When the template is installed (or upgraded), `NOTES.txt` is processed too
|
||||
|
||||
(i.e. its `{{ ... }}` tags are evaluated)
|
||||
|
||||
- It gets displayed after the install or upgrade
|
||||
|
||||
- It's a great place to generate messages to tell the user:
|
||||
|
||||
- how to connect to the release they just deployed
|
||||
|
||||
- any passwords or other thing that we generated for them
|
||||
|
||||
---
|
||||
|
||||
## Additional files
|
||||
|
||||
- We can place arbitrary files in the chart (outside of the `templates/` directory)
|
||||
|
||||
- They can be accessed in templates with `.Files`
|
||||
|
||||
- They can be transformed into ConfigMaps or Secrets with `AsConfig` and `AsSecrets`
|
||||
|
||||
(see [this example](https://helm.sh/docs/chart_template_guide/accessing_files/#configmap-and-secrets-utility-functions) in the Helm docs)
|
||||
|
||||
---
|
||||
|
||||
## Hooks and tests
|
||||
|
||||
- We can define *hooks* in our templates
|
||||
|
||||
- Hooks are resources annotated with `"helm.sh/hook": NAME-OF-HOOK`
|
||||
|
||||
- Hook names include `pre-install`, `post-install`, `test`, [and much more](https://helm.sh/docs/topics/charts_hooks/#the-available-hooks)
|
||||
|
||||
- The resources defined in hooks are loaded at a specific time
|
||||
|
||||
- Hook execution is *synchronous*
|
||||
|
||||
(if the resource is a Job or Pod, Helm will wait for its completion)
|
||||
|
||||
- This can be use for database migrations, backups, notifications, smoke tests ...
|
||||
|
||||
- Hooks named `test` are executed only when running `helm test RELEASE-NAME`
|
||||
220
slides/k8s/helm-create-basic-chart.md
Normal file
220
slides/k8s/helm-create-basic-chart.md
Normal file
@@ -0,0 +1,220 @@
|
||||
# Creating a basic chart
|
||||
|
||||
- We are going to show a way to create a *very simplified* chart
|
||||
|
||||
- In a real chart, *lots of things* would be templatized
|
||||
|
||||
(Resource names, service types, number of replicas...)
|
||||
|
||||
.exercise[
|
||||
|
||||
- Create a sample chart:
|
||||
```bash
|
||||
helm create dockercoins
|
||||
```
|
||||
|
||||
- Move away the sample templates and create an empty template directory:
|
||||
```bash
|
||||
mv dockercoins/templates dockercoins/default-templates
|
||||
mkdir dockercoins/templates
|
||||
```
|
||||
|
||||
]
|
||||
|
||||
---
|
||||
|
||||
## Exporting the YAML for our application
|
||||
|
||||
- The following section assumes that DockerCoins is currently running
|
||||
|
||||
- If DockerCoins is not running, see next slide
|
||||
|
||||
.exercise[
|
||||
|
||||
- Create one YAML file for each resource that we need:
|
||||
.small[
|
||||
```bash
|
||||
|
||||
while read kind name; do
|
||||
kubectl get -o yaml $kind $name > dockercoins/templates/$name-$kind.yaml
|
||||
done <<EOF
|
||||
deployment worker
|
||||
deployment hasher
|
||||
daemonset rng
|
||||
deployment webui
|
||||
deployment redis
|
||||
service hasher
|
||||
service rng
|
||||
service webui
|
||||
service redis
|
||||
EOF
|
||||
```
|
||||
]
|
||||
|
||||
]
|
||||
|
||||
---
|
||||
|
||||
## Obtaining DockerCoins YAML
|
||||
|
||||
- If DockerCoins is not running, we can also obtain the YAML from a public repository
|
||||
|
||||
.exercise[
|
||||
|
||||
- Clone the kubercoins repository:
|
||||
```bash
|
||||
git clone https://github.com/jpetazzo/kubercoins
|
||||
```
|
||||
|
||||
- Copy the YAML files to the `templates/` directory:
|
||||
```bash
|
||||
cp kubercoins/*.yaml dockercoins/templates/
|
||||
```
|
||||
|
||||
]
|
||||
|
||||
---
|
||||
|
||||
## Testing our helm chart
|
||||
|
||||
.exercise[
|
||||
|
||||
- Let's install our helm chart!
|
||||
```
|
||||
helm install helmcoins dockercoins
|
||||
```
|
||||
(`helmcoins` is the name of the release; `dockercoins` is the local path of the chart)
|
||||
|
||||
]
|
||||
|
||||
--
|
||||
|
||||
- Since the application is already deployed, this will fail:
|
||||
```
|
||||
Error: rendered manifests contain a resource that already exists.
|
||||
Unable to continue with install: existing resource conflict:
|
||||
kind: Service, namespace: default, name: hasher
|
||||
```
|
||||
|
||||
- To avoid naming conflicts, we will deploy the application in another *namespace*
|
||||
|
||||
---
|
||||
|
||||
## Switching to another namespace
|
||||
|
||||
- We need create a new namespace
|
||||
|
||||
(Helm 2 creates namespaces automatically; Helm 3 doesn't anymore)
|
||||
|
||||
- We need to tell Helm which namespace to use
|
||||
|
||||
.exercise[
|
||||
|
||||
- Create a new namespace:
|
||||
```bash
|
||||
kubectl create namespace helmcoins
|
||||
```
|
||||
|
||||
- Deploy our chart in that namespace:
|
||||
```bash
|
||||
helm install helmcoins dockercoins --namespace=helmcoins
|
||||
```
|
||||
|
||||
]
|
||||
|
||||
---
|
||||
|
||||
## Helm releases are namespaced
|
||||
|
||||
- Let's try to see the release that we just deployed
|
||||
|
||||
.exercise[
|
||||
|
||||
- List Helm releases:
|
||||
```bash
|
||||
helm list
|
||||
```
|
||||
|
||||
]
|
||||
|
||||
Our release doesn't show up!
|
||||
|
||||
We have to specify its namespace (or switch to that namespace).
|
||||
|
||||
---
|
||||
|
||||
## Specifying the namespace
|
||||
|
||||
- Try again, with the correct namespace
|
||||
|
||||
.exercise[
|
||||
|
||||
- List Helm releases in `helmcoins`:
|
||||
```bash
|
||||
helm list --namespace=helmcoins
|
||||
```
|
||||
|
||||
]
|
||||
|
||||
---
|
||||
|
||||
## Checking our new copy of DockerCoins
|
||||
|
||||
- We can check the worker logs, or the web UI
|
||||
|
||||
.exercise[
|
||||
|
||||
- Retrieve the NodePort number of the web UI:
|
||||
```bash
|
||||
kubectl get service webui --namespace=helmcoins
|
||||
```
|
||||
|
||||
- Open it in a web browser
|
||||
|
||||
- Look at the worker logs:
|
||||
```bash
|
||||
kubectl logs deploy/worker --tail=10 --follow --namespace=helmcoins
|
||||
```
|
||||
|
||||
]
|
||||
|
||||
Note: it might take a minute or two for the worker to start.
|
||||
|
||||
---
|
||||
|
||||
## Discussion, shortcomings
|
||||
|
||||
- Helm (and Kubernetes) best practices recommend to add a number of annotations
|
||||
|
||||
(e.g. `app.kubernetes.io/name`, `helm.sh/chart`, `app.kubernetes.io/instance` ...)
|
||||
|
||||
- Our basic chart doesn't have any of these
|
||||
|
||||
- Our basic chart doesn't use any template tag
|
||||
|
||||
- Does it make sense to use Helm in that case?
|
||||
|
||||
- *Yes,* because Helm will:
|
||||
|
||||
- track the resources created by the chart
|
||||
|
||||
- save successive revisions, allowing us to rollback
|
||||
|
||||
[Helm docs](https://helm.sh/docs/topics/chart_best_practices/labels/)
|
||||
and [Kubernetes docs](https://kubernetes.io/docs/concepts/overview/working-with-objects/common-labels/)
|
||||
have details about recommended annotations and labels.
|
||||
|
||||
---
|
||||
|
||||
## Cleaning up
|
||||
|
||||
- Let's remove that chart before moving on
|
||||
|
||||
.exercise[
|
||||
|
||||
- Delete the release (don't forget to specify the namespace):
|
||||
```bash
|
||||
helm delete helmcoins --namespace=helmcoins
|
||||
```
|
||||
|
||||
]
|
||||
579
slides/k8s/helm-create-better-chart.md
Normal file
579
slides/k8s/helm-create-better-chart.md
Normal file
@@ -0,0 +1,579 @@
|
||||
# Creating better Helm charts
|
||||
|
||||
- We are going to create a chart with the helper `helm create`
|
||||
|
||||
- This will give us a chart implementing lots of Helm best practices
|
||||
|
||||
(labels, annotations, structure of the `values.yaml` file ...)
|
||||
|
||||
- We will use that chart as a generic Helm chart
|
||||
|
||||
- We will use it to deploy DockerCoins
|
||||
|
||||
- Each component of DockerCoins will have its own *release*
|
||||
|
||||
- In other words, we will "install" that Helm chart multiple times
|
||||
|
||||
(one time per component of DockerCoins)
|
||||
|
||||
---
|
||||
|
||||
## Creating a generic chart
|
||||
|
||||
- Rather than starting from scratch, we will use `helm create`
|
||||
|
||||
- This will give us a basic chart that we will customize
|
||||
|
||||
.exercise[
|
||||
|
||||
- Create a basic chart:
|
||||
```bash
|
||||
cd ~
|
||||
helm create helmcoins
|
||||
```
|
||||
|
||||
]
|
||||
|
||||
This creates a basic chart in the directory `helmcoins`.
|
||||
|
||||
---
|
||||
|
||||
## What's in the basic chart?
|
||||
|
||||
- The basic chart will create a Deployment and a Service
|
||||
|
||||
- Optionally, it will also include an Ingress
|
||||
|
||||
- If we don't pass any values, it will deploy the `nginx` image
|
||||
|
||||
- We can override many things in that chart
|
||||
|
||||
- Let's try to deploy DockerCoins components with that chart!
|
||||
|
||||
---
|
||||
|
||||
## Writing `values.yaml` for our components
|
||||
|
||||
- We need to write one `values.yaml` file for each component
|
||||
|
||||
(hasher, redis, rng, webui, worker)
|
||||
|
||||
- We will start with the `values.yaml` of the chart, and remove what we don't need
|
||||
|
||||
- We will create 5 files:
|
||||
|
||||
hasher.yaml, redis.yaml, rng.yaml, webui.yaml, worker.yaml
|
||||
|
||||
- In each file, we want to have:
|
||||
```yaml
|
||||
image:
|
||||
repository: IMAGE-REPOSITORY-NAME
|
||||
tag: IMAGE-TAG
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Getting started
|
||||
|
||||
- For component X, we want to use the image dockercoins/X:v0.1
|
||||
|
||||
(for instance, for rng, we want to use the image dockercoins/rng:v0.1)
|
||||
|
||||
- Exception: for redis, we want to use the official image redis:latest
|
||||
|
||||
.exercise[
|
||||
|
||||
- Write YAML files for the 5 components, with the following model:
|
||||
```yaml
|
||||
image:
|
||||
repository: `IMAGE-REPOSITORY-NAME` (e.g. dockercoins/worker)
|
||||
tag: `IMAGE-TAG` (e.g. v0.1)
|
||||
```
|
||||
|
||||
]
|
||||
|
||||
---
|
||||
|
||||
## Deploying DockerCoins components
|
||||
|
||||
- For convenience, let's work in a separate namespace
|
||||
|
||||
.exercise[
|
||||
|
||||
- Create a new namespace (if it doesn't already exist):
|
||||
```bash
|
||||
kubectl create namespace helmcoins
|
||||
```
|
||||
|
||||
- Switch to that namespace:
|
||||
```bash
|
||||
kns helmcoins
|
||||
```
|
||||
|
||||
]
|
||||
|
||||
---
|
||||
|
||||
## Deploying the chart
|
||||
|
||||
- To install a chart, we can use the following command:
|
||||
```bash
|
||||
helm install COMPONENT-NAME CHART-DIRECTORY
|
||||
```
|
||||
|
||||
- We can also use the following command, which is idempotent:
|
||||
```bash
|
||||
helm upgrade COMPONENT-NAME CHART-DIRECTORY --install
|
||||
```
|
||||
|
||||
.exercise[
|
||||
|
||||
- Install the 5 components of DockerCoins:
|
||||
```bash
|
||||
for COMPONENT in hasher redis rng webui worker; do
|
||||
helm upgrade $COMPONENT helmcoins --install --values=$COMPONENT.yaml
|
||||
done
|
||||
```
|
||||
|
||||
]
|
||||
|
||||
---
|
||||
|
||||
## Checking what we've done
|
||||
|
||||
- Let's see if DockerCoins is working!
|
||||
|
||||
.exercise[
|
||||
|
||||
- Check the logs of the worker:
|
||||
```bash
|
||||
stern worker
|
||||
```
|
||||
|
||||
- Look at the resources that were created:
|
||||
```bash
|
||||
kubectl get all
|
||||
```
|
||||
|
||||
]
|
||||
|
||||
There are *many* issues to fix!
|
||||
|
||||
---
|
||||
|
||||
## Can't pull image
|
||||
|
||||
- It looks like our images can't be found
|
||||
|
||||
.exercise[
|
||||
|
||||
- Use `kubectl describe` on any of the pods in error
|
||||
|
||||
]
|
||||
|
||||
- We're trying to pull `rng:1.16.0` instead of `rng:v0.1`!
|
||||
|
||||
- Where does that `1.16.0` tag come from?
|
||||
|
||||
---
|
||||
|
||||
## Inspecting our template
|
||||
|
||||
- Let's look at the `templates/` directory
|
||||
|
||||
(and try to find the one generating the Deployment resource)
|
||||
|
||||
.exercise[
|
||||
|
||||
- Show the structure of the `helmcoins` chart that Helm generated:
|
||||
```bash
|
||||
tree helmcoins
|
||||
```
|
||||
|
||||
- Check the file `helmcoins/templates/deployment.yaml`
|
||||
|
||||
- Look for the `image:` parameter
|
||||
|
||||
]
|
||||
|
||||
*The image tag references `{{ .Chart.AppVersion }}`. Where does that come from?*
|
||||
|
||||
---
|
||||
|
||||
## The `.Chart` variable
|
||||
|
||||
- `.Chart` is a map corresponding to the values in `Chart.yaml`
|
||||
|
||||
- Let's look for `AppVersion` there!
|
||||
|
||||
.exercise[
|
||||
|
||||
- Check the file `helmcoins/Chart.yaml`
|
||||
|
||||
- Look for the `appVersion:` parameter
|
||||
|
||||
]
|
||||
|
||||
(Yes, the case is different between the template and the Chart file.)
|
||||
|
||||
---
|
||||
|
||||
## Using the correct tags
|
||||
|
||||
- If we change `AppVersion` to `v0.1`, it will change for *all* deployments
|
||||
|
||||
(including redis)
|
||||
|
||||
- Instead, let's change the *template* to use `{{ .Values.image.tag }}`
|
||||
|
||||
(to match what we've specified in our values YAML files)
|
||||
|
||||
.exercise[
|
||||
|
||||
- Edit `helmcoins/templates/deployment.yaml`
|
||||
|
||||
- Replace `{{ .Chart.AppVersion }}` with `{{ .Values.image.tag }}`
|
||||
|
||||
]
|
||||
|
||||
---
|
||||
|
||||
## Upgrading to use the new template
|
||||
|
||||
- Technically, we just made a new version of the *chart*
|
||||
|
||||
- To use the new template, we need to *upgrade* the release to use that chart
|
||||
|
||||
.exercise[
|
||||
|
||||
- Upgrade all components:
|
||||
```bash
|
||||
for COMPONENT in hasher redis rng webui worker; do
|
||||
helm upgrade $COMPONENT helmcoins
|
||||
done
|
||||
```
|
||||
|
||||
- Check how our pods are doing:
|
||||
```bash
|
||||
kubectl get pods
|
||||
```
|
||||
|
||||
]
|
||||
|
||||
We should see all pods "Running". But ... not all of them are READY.
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting readiness
|
||||
|
||||
- `hasher`, `rng`, `webui` should show up as `1/1 READY`
|
||||
|
||||
- But `redis` and `worker` should show up as `0/1 READY`
|
||||
|
||||
- Why?
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting pods
|
||||
|
||||
- The easiest way to troubleshoot pods is to look at *events*
|
||||
|
||||
- We can look at all the events on the cluster (with `kubectl get events`)
|
||||
|
||||
- Or we can use `kubectl describe` on the objects that have problems
|
||||
|
||||
(`kubectl describe` will retrieve the events related to the object)
|
||||
|
||||
.exercise[
|
||||
|
||||
- Check the events for the redis pods:
|
||||
```bash
|
||||
kubectl describe pod -l app.kubernetes.io/name=redis
|
||||
```
|
||||
|
||||
]
|
||||
|
||||
It's failing both its liveness and readiness probes!
|
||||
|
||||
---
|
||||
|
||||
## Healthchecks
|
||||
|
||||
- The default chart defines healthchecks doing HTTP requests on port 80
|
||||
|
||||
- That won't work for redis and worker
|
||||
|
||||
(redis is not HTTP, and not on port 80; worker doesn't even listen)
|
||||
|
||||
--
|
||||
|
||||
- We could remove or comment out the healthchecks
|
||||
|
||||
- We could also make them conditional
|
||||
|
||||
- This sounds more interesting, let's do that!
|
||||
|
||||
---
|
||||
|
||||
## Conditionals
|
||||
|
||||
- We need to enclose the healthcheck block with:
|
||||
|
||||
`{{ if false }}` at the beginning (we can change the condition later)
|
||||
|
||||
`{{ end }}` at the end
|
||||
|
||||
.exercise[
|
||||
|
||||
- Edit `helmcoins/templates/deployment.yaml`
|
||||
|
||||
- Add `{{ if false }}` on the line before `livenessProbe`
|
||||
|
||||
- Add `{{ end }}` after the `readinessProbe` section
|
||||
|
||||
(see next slide for details)
|
||||
|
||||
]
|
||||
|
||||
---
|
||||
|
||||
This is what the new YAML should look like (added lines in yellow):
|
||||
|
||||
```yaml
|
||||
ports:
|
||||
- name: http
|
||||
containerPort: 80
|
||||
protocol: TCP
|
||||
`{{ if false }}`
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /
|
||||
port: http
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /
|
||||
port: http
|
||||
`{{ end }}`
|
||||
resources:
|
||||
{{- toYaml .Values.resources | nindent 12 }}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Testing the new chart
|
||||
|
||||
- We need to upgrade all the services again to use the new chart
|
||||
|
||||
.exercise[
|
||||
|
||||
- Upgrade all components:
|
||||
```bash
|
||||
for COMPONENT in hasher redis rng webui worker; do
|
||||
helm upgrade $COMPONENT helmcoins
|
||||
done
|
||||
```
|
||||
|
||||
- Check how our pods are doing:
|
||||
```bash
|
||||
kubectl get pods
|
||||
```
|
||||
|
||||
]
|
||||
|
||||
Everything should now be running!
|
||||
|
||||
---
|
||||
|
||||
## What's next?
|
||||
|
||||
- Is this working now?
|
||||
|
||||
.exercise[
|
||||
|
||||
- Let's check the logs of the worker:
|
||||
```bash
|
||||
stern worker
|
||||
```
|
||||
|
||||
]
|
||||
|
||||
This error might look familiar ... The worker can't resolve `redis`.
|
||||
|
||||
Typically, that error means that the `redis` service doesn't exist.
|
||||
|
||||
---
|
||||
|
||||
## Checking services
|
||||
|
||||
- What about the services created by our chart?
|
||||
|
||||
.exercise[
|
||||
|
||||
- Check the list of services:
|
||||
```bash
|
||||
kubectl get services
|
||||
```
|
||||
|
||||
]
|
||||
|
||||
They are named `COMPONENT-helmcoins` instead of just `COMPONENT`.
|
||||
|
||||
We need to change that!
|
||||
|
||||
---
|
||||
|
||||
## Where do the service names come from?
|
||||
|
||||
- Look at the YAML template used for the services
|
||||
|
||||
- It should be using `{{ include "helmcoins.fullname" }}`
|
||||
|
||||
- `include` indicates a *template block* defined somewhere else
|
||||
|
||||
.exercise[
|
||||
|
||||
- Find where that `fullname` thing is defined:
|
||||
```bash
|
||||
grep define.*fullname helmcoins/templates/*
|
||||
```
|
||||
|
||||
]
|
||||
|
||||
It should be in `_helpers.tpl`.
|
||||
|
||||
We can look at the definition, but it's fairly complex ...
|
||||
|
||||
---
|
||||
|
||||
## Changing service names
|
||||
|
||||
- Instead of that `{{ include }}` tag, let's use the name of the release
|
||||
|
||||
- The name of the release is available as `{{ .Release.Name }}`
|
||||
|
||||
.exercise[
|
||||
|
||||
- Edit `helmcoins/templates/service.yaml`
|
||||
|
||||
- Replace the service name with `{{ .Release.Name }}`
|
||||
|
||||
- Upgrade all the releases to use the new chart
|
||||
|
||||
- Confirm that the services now have the right names
|
||||
|
||||
]
|
||||
|
||||
---
|
||||
|
||||
## Is it working now?
|
||||
|
||||
- If we look at the worker logs, it appears that the worker is still stuck
|
||||
|
||||
- What could be happening?
|
||||
|
||||
--
|
||||
|
||||
- The redis service is not on port 80!
|
||||
|
||||
- Let's see how the port number is set
|
||||
|
||||
- We need to look at both the *deployment* template and the *service* template
|
||||
|
||||
---
|
||||
|
||||
## Service template
|
||||
|
||||
- In the service template, we have the following section:
|
||||
```yaml
|
||||
ports:
|
||||
- port: {{ .Values.service.port }}
|
||||
targetPort: http
|
||||
protocol: TCP
|
||||
name: http
|
||||
```
|
||||
|
||||
- `port` is the port on which the service is "listening"
|
||||
|
||||
(i.e. to which our code needs to connect)
|
||||
|
||||
- `targetPort` is the port on which the pods are listening
|
||||
|
||||
- The `name` is not important (it's OK if it's `http` even for non-HTTP traffic)
|
||||
|
||||
---
|
||||
|
||||
## Setting the redis port
|
||||
|
||||
- Let's add a `service.port` value to the redis release
|
||||
|
||||
.exercise[
|
||||
|
||||
- Edit `redis.yaml` to add:
|
||||
```yaml
|
||||
service:
|
||||
port: 6379
|
||||
```
|
||||
|
||||
- Apply the new values file:
|
||||
```bash
|
||||
helm upgrade redis helmcoins --values=redis.yaml
|
||||
```
|
||||
|
||||
]
|
||||
|
||||
---
|
||||
|
||||
## Deployment template
|
||||
|
||||
- If we look at the deployment template, we see this section:
|
||||
```yaml
|
||||
ports:
|
||||
- name: http
|
||||
containerPort: 80
|
||||
protocol: TCP
|
||||
```
|
||||
|
||||
- The container port is hard-coded to 80
|
||||
|
||||
- We'll change it to use the port number specified in the values
|
||||
|
||||
---
|
||||
|
||||
## Changing the deployment template
|
||||
|
||||
.exercise[
|
||||
|
||||
- Edit `helmcoins/templates/deployment.yaml`
|
||||
|
||||
- The line with `containerPort` should be:
|
||||
```yaml
|
||||
containerPort: {{ .Values.service.port }}
|
||||
```
|
||||
|
||||
]
|
||||
|
||||
---
|
||||
|
||||
## Apply changes
|
||||
|
||||
- Re-run the for loop to execute `helm upgrade` one more time
|
||||
|
||||
- Check the worker logs
|
||||
|
||||
- This time, it should be working!
|
||||
|
||||
---
|
||||
|
||||
## Extra steps
|
||||
|
||||
- We don't need to create a service for the worker
|
||||
|
||||
- We can put the whole service block in a conditional
|
||||
|
||||
(this will require additional changes in other files referencing the service)
|
||||
|
||||
- We can set the webui to be a NodePort service
|
||||
|
||||
- We can change the number of workers with `replicaCount`
|
||||
|
||||
- And much more!
|
||||
234
slides/k8s/helm-secrets.md
Normal file
234
slides/k8s/helm-secrets.md
Normal file
@@ -0,0 +1,234 @@
|
||||
# Helm secrets
|
||||
|
||||
- Helm can do *rollbacks*:
|
||||
|
||||
- to previously installed charts
|
||||
|
||||
- to previous sets of values
|
||||
|
||||
- How and where does it store the data needed to do that?
|
||||
|
||||
- Let's investigate!
|
||||
|
||||
---
|
||||
|
||||
## We need a release
|
||||
|
||||
- We need to install something with Helm
|
||||
|
||||
- Let's use the `stable/tomcat` chart as an example
|
||||
|
||||
.exercise[
|
||||
|
||||
- Install a release called `tomcat` with the chart `stable/tomcat`:
|
||||
```bash
|
||||
helm upgrade tomcat stable/tomcat --install
|
||||
```
|
||||
|
||||
- Let's upgrade that release, and change a value:
|
||||
```bash
|
||||
helm upgrade tomcat stable/tomcat --set ingress.enabled=true
|
||||
```
|
||||
|
||||
]
|
||||
|
||||
---
|
||||
|
||||
## Release history
|
||||
|
||||
- Helm stores successive revisions of each release
|
||||
|
||||
.exercise[
|
||||
|
||||
- View the history for that release:
|
||||
```bash
|
||||
helm history tomcat
|
||||
```
|
||||
|
||||
]
|
||||
|
||||
Where does that come from?
|
||||
|
||||
---
|
||||
|
||||
## Investigate
|
||||
|
||||
- Possible options:
|
||||
|
||||
- local filesystem (no, because history is visible from other machines)
|
||||
|
||||
- persistent volumes (no, Helm works even without them)
|
||||
|
||||
- ConfigMaps, Secrets?
|
||||
|
||||
.exercise[
|
||||
|
||||
- Look for ConfigMaps and Secrets:
|
||||
```bash
|
||||
kuebectl get configmaps,secrets
|
||||
```
|
||||
|
||||
]
|
||||
|
||||
--
|
||||
|
||||
We should see a number of secrets with TYPE `helm.sh/release.v1`.
|
||||
|
||||
---
|
||||
|
||||
## Unpacking a secret
|
||||
|
||||
- Let's find out what is in these Helm secrets
|
||||
|
||||
.exercise[
|
||||
|
||||
- Examine the secret corresponding to the second release of `tomcat`:
|
||||
```bash
|
||||
kubectl describe secret sh.helm.release.v1.tomcat.v2
|
||||
```
|
||||
(`v1` is the secret format; `v2` means revision 2 of the `tomcat` release)
|
||||
|
||||
]
|
||||
|
||||
There is a key named `release`.
|
||||
|
||||
---
|
||||
|
||||
## Unpacking the release data
|
||||
|
||||
- Let's see what's in this `release` thing!
|
||||
|
||||
.exercise[
|
||||
|
||||
- Dump the secret:
|
||||
```bash
|
||||
kubectl get secret sh.helm.release.v1.tomcat.v2 \
|
||||
-o go-template='{{ .data.release }}'
|
||||
```
|
||||
|
||||
]
|
||||
|
||||
Secrets are encoded in base64. We need to decode that!
|
||||
|
||||
---
|
||||
|
||||
## Decoding base64
|
||||
|
||||
- We can pipe the output through `base64 -d` or use go-template's `base64decode`
|
||||
|
||||
.exercise[
|
||||
|
||||
- Decode the secret:
|
||||
```bash
|
||||
kubectl get secret sh.helm.release.v1.tomcat.v2 \
|
||||
-o go-template='{{ .data.release | base64decode }}'
|
||||
```
|
||||
|
||||
]
|
||||
|
||||
--
|
||||
|
||||
... Wait, this *still* looks like base64. What's going on?
|
||||
|
||||
--
|
||||
|
||||
Let's try one more round of decoding!
|
||||
|
||||
---
|
||||
|
||||
## Decoding harder
|
||||
|
||||
- Just add one more base64 decode filter
|
||||
|
||||
.exercise[
|
||||
|
||||
- Decode it twice:
|
||||
```bash
|
||||
kubectl get secret sh.helm.release.v1.tomcat.v2 \
|
||||
-o go-template='{{ .data.release | base64decode | base64decode }}'
|
||||
```
|
||||
|
||||
]
|
||||
|
||||
--
|
||||
|
||||
... OK, that was *a lot* of binary data. What sould we do with it?
|
||||
|
||||
---
|
||||
|
||||
## Guessing data type
|
||||
|
||||
- We could use `file` to figure out the data type
|
||||
|
||||
.exercise[
|
||||
|
||||
- Pipe the decoded release through `file -`:
|
||||
```bash
|
||||
kubectl get secret sh.helm.release.v1.tomcat.v2 \
|
||||
-o go-template='{{ .data.release | base64decode | base64decode }}' \
|
||||
| file -
|
||||
```
|
||||
|
||||
]
|
||||
|
||||
--
|
||||
|
||||
Gzipped data! It can be decoded with `gunzip -c`.
|
||||
|
||||
---
|
||||
|
||||
## Uncompressing the data
|
||||
|
||||
- Let's uncompress the data and save it to a file
|
||||
|
||||
.exercise[
|
||||
|
||||
- Rerun the previous command, but with `| gunzip -c > release-info` :
|
||||
```bash
|
||||
kubectl get secret sh.helm.release.v1.tomcat.v2 \
|
||||
-o go-template='{{ .data.release | base64decode | base64decode }}' \
|
||||
| gunzip -c > release-info
|
||||
```
|
||||
|
||||
- Look at `release-info`:
|
||||
```bash
|
||||
cat release-info
|
||||
```
|
||||
|
||||
]
|
||||
|
||||
--
|
||||
|
||||
It's a bundle of ~~YAML~~ JSON.
|
||||
|
||||
---
|
||||
|
||||
## Looking at the JSON
|
||||
|
||||
If we inspect that JSON (e.g. with `jq keys release-info`), we see:
|
||||
|
||||
- `chart` (contains the entire chart used for that release)
|
||||
- `config` (contains the values that we've set)
|
||||
- `info` (date of deployment, status messages)
|
||||
- `manifest` (YAML generated from the templates)
|
||||
- `name` (name of the release, so `tomcat`)
|
||||
- `namespace` (namespace where we deployed the release)
|
||||
- `version` (revision number within that release; starts at 1)
|
||||
|
||||
The chart is in a structured format, but it's entirely captured in this JSON.
|
||||
|
||||
---
|
||||
|
||||
## Conclusions
|
||||
|
||||
- Helm stores each release information in a Secret in the namespace of the release
|
||||
|
||||
- The secret is JSON object (gzipped and encoded in base64)
|
||||
|
||||
- It contains the manifests generated for that release
|
||||
|
||||
- ... And everything needed to rebuild these manifests
|
||||
|
||||
(including the full source of the chart, and the values used)
|
||||
|
||||
- This allows arbitrary rollbacks, as well as tweaking values even without having access to the source of the chart (or the chart repo) used for deployment
|
||||
@@ -64,7 +64,11 @@ chapters:
|
||||
- k8s/namespaces.md
|
||||
- k8s/ingress.md
|
||||
#- k8s/kustomize.md
|
||||
#- k8s/helm.md
|
||||
#- k8s/helm-intro.md
|
||||
#- k8s/helm-chart-format.md
|
||||
#- k8s/helm-create-basic-chart.md
|
||||
#- k8s/helm-create-better-chart.md
|
||||
#- k8s/helm-secrets.md
|
||||
#- k8s/create-chart.md
|
||||
#- k8s/create-more-charts.md
|
||||
#- k8s/netpol.md
|
||||
|
||||
@@ -59,9 +59,11 @@ chapters:
|
||||
# Bridget hasn't added EFK yet
|
||||
#- k8s/logs-centralized.md
|
||||
- k8s/namespaces.md
|
||||
- k8s/helm.md
|
||||
- k8s/create-chart.md
|
||||
#- k8s/create-more-charts.md
|
||||
- k8s/helm-intro.md
|
||||
#- k8s/helm-chart-format.md
|
||||
- k8s/helm-create-basic-chart.md
|
||||
#- k8s/helm-create-better-chart.md
|
||||
#- k8s/helm-secrets.md
|
||||
#- k8s/kustomize.md
|
||||
#- k8s/netpol.md
|
||||
- k8s/whatsnext.md
|
||||
|
||||
@@ -67,9 +67,11 @@ chapters:
|
||||
-
|
||||
- k8s/ingress.md
|
||||
- k8s/kustomize.md
|
||||
- k8s/helm.md
|
||||
- k8s/create-chart.md
|
||||
- k8s/create-more-charts.md
|
||||
- k8s/helm-intro.md
|
||||
- k8s/helm-chart-format.md
|
||||
- k8s/helm-create-basic-chart.md
|
||||
- k8s/helm-create-better-chart.md
|
||||
- k8s/helm-secrets.md
|
||||
-
|
||||
- k8s/netpol.md
|
||||
- k8s/authn-authz.md
|
||||
|
||||
@@ -65,9 +65,11 @@ chapters:
|
||||
- k8s/namespaces.md
|
||||
- k8s/ingress.md
|
||||
- k8s/kustomize.md
|
||||
- k8s/helm.md
|
||||
- k8s/create-chart.md
|
||||
#- k8s/create-more-charts.md
|
||||
- k8s/helm-intro.md
|
||||
- k8s/helm-chart-format.md
|
||||
- k8s/helm-create-basic-chart.md
|
||||
- k8s/helm-create-better-chart.md
|
||||
- k8s/helm-secrets.md
|
||||
-
|
||||
- k8s/netpol.md
|
||||
- k8s/authn-authz.md
|
||||
|
||||
Reference in New Issue
Block a user