Helm
Kustomize transforms your manifests; Helm packages them. A chart contains everything needed to deploy an application (Deployments, Services, ConfigMaps, Ingress...) together with its configurable values, versioned and distributable. Each installation of a chart in the cluster is a release with its own name and revision history. That makes Helm the standard tool for installing third-party software (databases, monitoring, controllers) and for distributing your own applications across teams and environments.
In this lesson you'll walk through the full lifecycle with a chart you create yourself: it's the way to see the whole machinery without depending on external registries. Work from the dev-machine tab (Helm is already installed).
The world of repositories, in theory first
The most common use of Helm starts at a public chart repository:
How do I add a repository and keep it up to date?
helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo update
How do I search for a chart and study its configuration before installing it?
helm search repo postgresql
helm show values bitnami/postgresql
That show values is the mandatory first step of any installation: understanding what you can configure and which values it ships with out of the box.
💡 In this playground we'll practice with a local chart instead of Bitnami: its charts pull images from Docker Hub, whose anonymous pull limits we've been dodging all course long. The release mechanics you're about to learn are identical.
Mission 1: your first chart
Helm can build the skeleton of a complete chart:
cd /home/laborant
helm create tienda
Explore the result in the IDE tab: Chart.yaml (the package metadata), values.yaml (the configuration exposed to the user) and templates/ (the manifests you already know, sprinkled with {{ .Values... }} template expressions). That's the philosophical difference from Kustomize: here the manifests really are templates.
The generated chart uses the nginx image from Docker Hub and leaves the tag empty. Adjust both in values.yaml:
image:
repository: ghcr.io/iximiuz/labs/nginx
pullPolicy: IfNotPresent
tag: "alpine"
Why is it important to pin the tag rather than leave it empty?
Because the generated chart has a treacherous default: with an empty tag it uses the appVersion from Chart.yaml (1.16.0), and the image ghcr.io/iximiuz/labs/nginx:1.16.0 doesn't exist. It's a first Helm lesson in miniature: you always read a chart's defaults before installing.
Mission 2: install the release
Before touching the cluster, the habit you already have from kubectl applies just the same in Helm:
How do I render the final YAML a chart would generate without applying it?
helm template web ./tienda
It's the equivalent of kubectl diff before applying: the exact manifests that would be created, with the templates already resolved.
Before installing, one more thing. The values.yaml you just touched is the chart's own: the out-of-the-box values, the ones that travel inside the package. What a specific environment needs to change isn't edited there; it's passed separately. Create values-prod.yaml, outside the chart:
cat << 'EOF' > /home/laborant/values-prod.yaml
service:
type: NodePort
resources:
requests:
cpu: 50m
memory: 64Mi
EOF
How do I install a chart for the first time, with my values?
helm install web ./tienda -n tienda --create-namespace -f values-prod.yaml
And the inventory questions that answer what's installed and with which configuration:
helm list -A
helm get values web -n tienda
There they are, and only they: the two blocks of your values-prod.yaml. That's what get values answers, and it helps to be clear about it because almost everyone gets the surprise the other way around: it doesn't show the release's effective configuration, but what the user supplied on top of the chart. If you install with neither -f nor --set, the answer is a puzzling null even if the release has been running for months.
To see the full configuration (the chart's values with your overrides already merged on top) you have to ask for it:
helm get values web -n tienda --all
That pair of commands is what really answers the question "what was this installed with?" when you inherit a cluster: the first tells you what someone decided, the second what it ended up running with. Notice the created object too: the Deployment is called web-tienda (release plus chart), Helm's naming convention.
Mission 3: the idempotent upgrade
Time to go up to 3 replicas, and you'll do it with the command variant that rules the CI/CD world:
How do I upgrade an already installed release, or install it if it doesn't exist yet?
helm upgrade --install web ./tienda -n tienda -f values-prod.yaml --set replicaCount=3
upgrade --install is idempotent by definition: it fails neither when the release already exists nor when it doesn't exist yet, which is exactly what a pipeline needs. The --set overrides a single value, and the -f passes the usual file again.
Why repeat the -f if I already passed it at install time? Because an upgrade does not inherit the values of the previous revision: whatever you don't supply again disappears. If you leave out the -f here, the Service goes back to ClusterIP and the requests vanish, without a single warning. Check it afterward with helm get values web -n tienda. (There is --reuse-values to inherit them, but in a pipeline the healthy habit is the opposite: always pass the complete file, which lives in the repository, so the release's state never depends on what someone did last time.)
Mission 4: reverse gear
The new version turned out so-so (it was an even-numbered day; it was bound to happen). Check the history and roll back:
How do I see a release's history and roll it back to an earlier version?
helm history web -n tienda
helm rollback web 1 -n tienda
The number is the target revision. Just like rollout undo for Deployments, Helm's rollback doesn't erase history: it creates a revision 3 whose contents are those of revision 1. Check it by repeating the history.
Summary
- A chart packages manifests as templates plus values; a release is an installed chart with a history.
- Before installing:
show values(someone else's charts) andhelm template(always). - The chart's
values.yamlholds the out-of-the-box values; what each environment changes goes in a separate file passed with-f, and it has to be repeated on everyupgrade. get valuesshows what the user supplied;get values --all, the effective configuration.upgrade --installis the pipelines' command: idempotent by design.historyandrollbackgive any packaged application the same emergency button you learned with Deployments.- Helm and Kustomize don't compete as much as it seems: charts to package and distribute, overlays to adapt per environment. You'll see both coexist in the real world.
- Previous lesson
- Declarative kubectl
- Next lesson
- The commands that aren't in any manual