Lesson  in  Kubernetes 101

Helm

The Kubernetes package manager: create your own chart, install it as a release, upgrade it, check its history and roll it back, going through the full lifecycle you will use in CI/CD.

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.

Note

💡 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) and helm template (always).
  • The chart's values.yaml holds 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 every upgrade.
  • get values shows what the user supplied; get values --all, the effective configuration.
  • upgrade --install is the pipelines' command: idempotent by design.
  • history and rollback give 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