Lesson 01 Introduction to Helm
Theme:

Theory

Reading time: ~15 minutes  ·  Prerequisites: Basic Kubernetes and kubectl familiarity

1. The Problem: Managing Kubernetes Manifests at Scale

Every Kubernetes application is defined by a collection of YAML manifests — Deployments, Services, ConfigMaps, Secrets, Ingresses, and more. For a simple "hello world" application, you might write two or three files. But real-world applications quickly balloon: a typical microservice might need a Deployment, a Service, an Ingress, a ConfigMap, a Secret, a ServiceAccount, a HorizontalPodAutoscaler, and a PodDisruptionBudget. Multiply that across a dozen services and three environments (dev, staging, production), and you are managing hundreds of YAML files.

Worse, these files are often nearly identical across environments — differing only in a replica count, an image tag, or a domain name. Without a templating or packaging layer, teams resort to copy-pasting manifests and making manual edits, a process that is both error-prone and impossible to audit reliably.

This is the problem Helm was created to solve.

2. What Is Helm?

Helm is the package manager for Kubernetes. It packages Kubernetes manifests into a unit called a chart, applies user-provided configuration through values, and tracks every deployment as a versioned release. The analogy to traditional package managers is deliberate: a Helm chart is to Kubernetes what a .deb package is to Debian, or a Homebrew formula is to macOS.

With Helm, you can:

Key Insight

Helm does not replace kubectl. Under the hood, Helm renders templates into standard Kubernetes YAML and submits them to the API server. You can always inspect the rendered output with helm template before applying anything to your cluster.

3. Helm 3 Architecture

Helm went through a major architectural change between versions 2 and 3. Understanding this history helps explain design decisions you will encounter.

Helm 2 and Tiller

Helm 2 used a two-component architecture: the helm CLI on the client side, and a server-side component called Tiller that ran as a pod inside the cluster. When you ran helm install, the CLI sent the chart to Tiller, which rendered the templates and applied the resulting manifests to Kubernetes.

Tiller was problematic for several reasons. It required broad permissions (often cluster-admin) to function, creating a significant security surface. In multi-tenant clusters, any user who could reach Tiller effectively had cluster-wide access. Release metadata was stored as ConfigMaps, which were difficult to secure and manage.

Helm 3: Client-Only

Helm 3, released in November 2019, removed Tiller entirely. The helm CLI now talks directly to the Kubernetes API server using the credentials from your kubeconfig file. This means Helm respects your existing RBAC policies — if your user account cannot create Ingresses, then helm install will fail when it tries to create one, just as kubectl apply would.

Release metadata is now stored as Kubernetes Secrets (type helm.sh/release.v1) in the same namespace as the release. This makes them easier to secure with standard Kubernetes RBAC and encryption-at-rest. You can inspect them directly:

# List Helm release secrets in the default namespace
kubectl get secrets -l owner=helm

# Inspect a specific release secret (base64-encoded, gzipped)
kubectl get secret sh.helm.release.v1.my-nginx.v1 -o yaml

Helm 2 End of Life

Helm 2 reached end of life in November 2020. All new projects should use Helm 3. If you encounter Helm 2 charts or documentation, be aware that the Tiller-based architecture no longer applies.

4. Core Concepts in Detail

Charts

A chart is a directory (or a .tgz archive of that directory) containing everything needed to deploy an application. The minimum structure is:

mychart/
  Chart.yaml        # Required: name, version, description, apiVersion
  values.yaml       # Default configuration values
  templates/        # Go templates that render to Kubernetes manifests
    deployment.yaml
    service.yaml
    _helpers.tpl    # Reusable template snippets (partials)

The Chart.yaml file is the chart's identity. It declares the chart name, version (following SemVer), an optional appVersion (the version of the application being deployed), and any dependencies on other charts.

Releases

Every time you run helm install, Helm creates a release — a named instance of a chart running in a specific namespace. You can install the same chart multiple times with different release names (e.g., nginx-staging and nginx-production), each with its own values and independent lifecycle.

Each helm upgrade creates a new revision of the release. You can view the history and roll back to any previous revision:

# View release history
helm history my-nginx

# Roll back to revision 2
helm rollback my-nginx 2

Repositories

A chart repository is an HTTP server that hosts an index.yaml file listing available charts and their download URLs. Helm supports adding multiple repositories and searching across them:

# Add a repository
helm repo add bitnami https://charts.bitnami.com/bitnami

# Refresh the local index cache
helm repo update

# Search for charts matching "redis"
helm search repo redis

Helm 3 also supports OCI registries as chart repositories. This means you can store charts in the same container registries (Docker Hub, GitHub Container Registry, Amazon ECR) that you use for container images.

Values

Values are the primary mechanism for customizing a chart. Every chart ships with a values.yaml that defines sensible defaults. Users override these defaults at install or upgrade time using -f (values files) or --set (individual key-value pairs).

# values-production.yaml
replicaCount: 3
image:
  tag: "1.25.3"
service:
  type: LoadBalancer
resources:
  limits:
    cpu: 500m
    memory: 256Mi
# Install with production values
helm install my-nginx bitnami/nginx -f values-production.yaml

# Override a single value on top of the file
helm install my-nginx bitnami/nginx -f values-production.yaml --set replicaCount=5

Inspecting Default Values

Before installing any chart, review its default values to understand what can be configured: helm show values bitnami/nginx. This prints the entire values.yaml with comments explaining each parameter.

5. Artifact Hub: Discovering Charts

Artifact Hub is the official CNCF-hosted registry for discovering Kubernetes packages, including Helm charts. It indexes charts from hundreds of repositories and provides a searchable web interface with documentation, version history, and security reports.

You can also search Artifact Hub from the CLI:

# Search Artifact Hub for WordPress charts
helm search hub wordpress

When evaluating a chart from Artifact Hub, look for:

6. Raw kubectl apply vs Helm: A Practical Comparison

To make the value proposition concrete, consider deploying a web application that needs a Deployment, Service, and Ingress across two environments.

The kubectl Approach

You create six YAML files (three per environment) or use Kustomize overlays. To deploy, you run kubectl apply -f ./staging/. To update the image tag, you edit the file (or use kubectl set image). To roll back, you either keep old files in Git and re-apply, or use kubectl rollout undo (which only covers Deployments, not Services or Ingresses). There is no single command that captures the entire state of your deployed application.

The Helm Approach

You create one chart with templates. Environment differences live in values-staging.yaml and values-production.yaml. To deploy staging, you run helm install myapp ./mychart -f values-staging.yaml. To update the image tag, you change the value and run helm upgrade. To roll back all resources atomically, you run helm rollback myapp 1. The entire release history — including which values were used for each revision — is stored in the cluster and can be inspected at any time.

Capabilitykubectl applyHelm
ParameterizationKustomize or manual editsBuilt-in Go templates + values
Atomic rollbackNot supported nativelyhelm rollback
Release versioningRequires external toolingAutomatic revision tracking
Dependency managementManualChart dependencies in Chart.yaml
Sharing & reuseCopy YAML filesChart repositories / OCI registries

7. Why Templates Matter

At the heart of every Helm chart is the templates/ directory, where Go template syntax transforms static YAML into dynamic, parameterized manifests. A simple example:

# templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ .Release.Name }}-app
spec:
  replicas: {{ .Values.replicaCount }}
  selector:
    matchLabels:
      app: {{ .Release.Name }}
  template:
    spec:
      containers:
        - name: app
          image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"

The double-brace expressions ({{ }}) are replaced at render time with values from the release context and the user-provided values file. This single template can produce different manifests for every environment, every release name, and every configuration variant — without duplicating a single line of YAML.

Preview Before You Apply

You can render templates locally without touching a cluster: helm template my-release ./mychart -f values.yaml. This outputs the fully rendered YAML to stdout, which is invaluable for debugging and code review.

Further Reading

Next lesson: Lesson 02 — we will build our first Helm chart from scratch, exploring the template language and chart structure in depth.