Back to Helm & Charts
Q1Question 1 of 2

What Helm adds over raw Kubernetes manifests: templating, values, upgrade --install, rollback, per-environment values: and when to reach for it

Key Concepts
  • Helm wraps Kubernetes manifests into a versioned, parameterized chart with Go templates and a values file.
  • Per-environment values files (values-prod.yaml) override only what differs, eliminating copy-paste drift across environments.
  • helm upgrade --install is idempotent: it installs if absent, upgrades if present, and records a numbered revision.
  • helm rollback restores a previous revision in one command; --atomic auto-rolls back if readiness checks fail.
  • Reach for Helm when deploying across multiple environments, when you need rollback, or when consuming third-party charts.
  • For a single simple app in one environment, raw manifests or Kustomize may be simpler.

Definition

Helm turns static per-environment YAML copies into one templated chart plus small values overrides, with atomic upgrade --install releases and one-command rollback.
  • Chart – a versioned, parameterized package of Kubernetes manifests with Go templates.
  • Values – a YAML file that fills template placeholders; a base values file plus small per-environment overrides.
  • upgrade --install – idempotent: installs if absent, upgrades if present, recording a numbered revision.
  • Rollback – restores a previous revision in one command; --atomic auto-rolls back on failure.
  • Named templates – reusable helpers to avoid repetition across manifests.
  • Chart dependencies – a chart can bundle sub-charts (e.g., a service plus its Redis).

Imagine National Bank of India opens branches in many cities. Raw manifests are like handing each branch a thick stack of fully filled-out forms, copying the whole stack for each city and manually white-outing the city name and vault size. Helm is one master template with blanks, plus a small city-specific sheet that fills only the blanks. One template, a tiny per-city override, and every branch is set up consistently. Helm also keeps a logbook of every version, so you can flip back to a previous version in one step.

Understanding the Concepts

What problem does Helm solve?

With raw manifests you write static YAML and apply with kubectl apply. At scale this creates copy-paste drift: the same service in dev, staging, and production means three copies of the manifests with hand-edited differences that silently diverge.

YAML
# Raw manifest problem: three copies that drift apart
# dev/deployment.yaml:   replicas: 1, image: bank/loan-service:dev
# staging/deployment.yaml: replicas: 2, image: bank/loan-service:staging
# prod/deployment.yaml:    replicas: 5, image: bank/loan-service:v1.2.3
# A memory-limit change in prod but not staging causes crashes nobody can reproduce

How does Helm templating work?

A chart contains templates with placeholders. A values file fills them. One template serves every environment.

YAML
# chart/templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ .Release.Name }}
spec:
  replicas: {{ .Values.replicaCount }}
  selector:
    matchLabels:
      app: {{ .Release.Name }}
  template:
    metadata:
      labels:
        app: {{ .Release.Name }}
    spec:
      containers:
      - name: app
        image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
        resources:
          requests:
            memory: {{ .Values.resources.requests.memory }}
            cpu: {{ .Values.resources.requests.cpu }}
          limits:
            memory: {{ .Values.resources.limits.memory }}
            cpu: {{ .Values.resources.limits.cpu }}
        env:
        - name: JAVA_OPTS
          value: {{ .Values.javaOpts | quote }}
YAML
# chart/values.yaml (base defaults)
replicaCount: 1
image:
  repository: bank/loan-service
  tag: latest
resources:
  requests:
    memory: "512Mi"
    cpu: "500m"
  limits:
    memory: "1Gi"
    cpu: "1000m"
javaOpts: "-XX:MaxRAMPercentage=75.0 -XX:+UseG1GC"
YAML
# chart/values-prod.yaml (production overrides -- only what differs)
replicaCount: 5
image:
  tag: abc123
resources:
  requests:
    memory: "2Gi"
    cpu: "2000m"
  limits:
    memory: "2Gi"
    cpu: "2000m"
javaOpts: "-XX:MaxRAMPercentage=75.0 -XX:+UseG1GC -XX:+ExitOnOutOfMemoryError"

How does upgrade --install work?

helm upgrade --install is idempotent: it installs if the release does not exist, upgrades if it does. It records each deploy as a numbered revision.

BASH
# Deploy to production
helm upgrade --install loan-service ./chart \
  -f chart/values-prod.yaml \
  --set image.tag=abc123 \
  --timeout 5m

# First run: installs (revision 1)
# Second run: upgrades (revision 2)
# Third run: upgrades (revision 3)
BASH
# View release history
helm history loan-service
# REVISION  STATUS      DESCRIPTION
# 1         deployed    Install complete
# 2         deployed    Upgrade complete
# 3         deployed    Upgrade complete

How does rollback work?

Because Helm keeps revision history, you can restore a previous known-good revision in one command.

BASH
# Rollback to revision 2
helm rollback loan-service 2
# Kubernetes is restored to exactly the manifests of revision 2
BASH
# Atomic upgrade: auto-rollback if readiness checks fail
helm upgrade --install loan-service ./chart \
  -f chart/values-prod.yaml \
  --set image.tag=bad-image \
  --timeout 5m \
  --atomic
# If pods fail readiness within 5 minutes:
# Helm automatically rolls back to the previous good revision
# Cluster is in a known-good state, not half-upgraded

What is the difference between Helm and raw manifests?

| Aspect | Raw kubectl apply | Helm |
|--------|-------------------|------|
| Templating | None (static YAML) | Go templates + values |
| Multi-environment | Copy and edit each file | One chart + small value overrides |
| Release concept | None (just objects) | Named release with revision history |
| Rollback | Reconstruct old YAML from Git | helm rollback |
| Idempotent deploy | kubectl apply (partial) | helm upgrade --install (full) |
| Drift prevention | Manual discipline | Shared templates prevent divergence |

What is the difference between Helm and Kustomize?

| Aspect | Helm | Kustomize |
|--------|------|-----------|
| Approach | Go templates + values | Base + overlays (patching) |
| Templating | Full Go template language | No templates, patch-based |
| Release management | Built-in (revisions, rollback) | None (just manifest generation) |
| Complexity | Higher (template language) | Lower (YAML patches) |
| Best for | Multi-env deploys with rollback | Simple overlays without release mgmt |

BASH
# Helm: template-based
helm upgrade --install loan-service ./chart -f values-prod.yaml

# Kustomize: overlay-based
kubectl apply -k overlays/production/

When do you reach for Helm?

TEXT
 Use Helm when:
 - Deploying the same app across multiple environments (dev/staging/prod)
 - You need atomic releases with revision history and one-command rollback
 - You package your service for others to install
 - You consume third-party software distributed as charts (Prometheus, Nginx)

 Consider alternatives when:
 - Single simple app in one environment (raw manifests or Kustomize)
 - Team dislikes Go templating (Kustomize overlays)
 - GitOps with ArgoCD (either works, but Kustomize is lighter)

What are common mistakes with Helm?

YAML
# WRONG: hard-coding values in templates instead of using values.yaml
# chart/templates/deployment.yaml:
spec:
  replicas: 5  # Hard-coded -- defeats the purpose of templating

# CORRECT: use values
spec:
  replicas: {{ .Values.replicaCount }}
BASH
# WRONG: deploying without --atomic (half-upgraded state on failure)
helm upgrade --install loan-service ./chart
# If new pods crash, cluster is left half-upgraded

# CORRECT: use --atomic for safe upgrades
helm upgrade --install loan-service ./chart --atomic --timeout 5m
# Failed upgrade auto-rolls back to the last good revision

What should a senior engineer know?

Helm is not always the answer. For a single simple app in a single environment, raw manifests or Kustomize can be simpler. But for a bank running many services across dev, staging, and production with strict rollback requirements, Helm's release and rollback model earns its keep. The --atomic flag is essential in production because it ensures a failed upgrade does not leave the cluster in a broken state.

Visual Overview

DIAGRAM
 Raw Manifests vs Helm
 ======================

 Raw manifests:
   ┌──────────┐  ┌──────────┐  ┌──────────┐
   │ dev/     │  │ staging/ │  │ prod/    │
   │ deploy.  │  │ deploy.  │  │ deploy.  │
   │ yaml     │  │ yaml     │  │ yaml     │
   │ (copy)   │  │ (copy)   │  │ (copy)   │
   └──────────┘  └──────────┘  └──────────┘
   Three copies that silently drift apart

 Helm:
   ┌──────────────────────┐
   │  chart/              │
   │  templates/          │  One template
   │  values.yaml         │  Base defaults
   │  values-dev.yaml     │  Tiny override
   │  values-staging.yaml │  Tiny override
   │  values-prod.yaml    │  Tiny override
   └──────────────────────┘
   Shared templates prevent divergence

 Helm Release Lifecycle
 =======================

 helm upgrade --install
       │
       ▼
 Revision 1 ──▶ Revision 2 ──▶ Revision 3
                                    │
                              (bad image)
                                    │
                              helm rollback 2
                                    │
                                    ▼
                              Revision 4 (= state of rev 2)
                              Cluster is healthy

Key Takeaway

Helm wraps Kubernetes manifests into a versioned, parameterized chart. Instead of copying YAML for each environment and editing by hand, you maintain one chart with templates and small per-environment value files that override only what differs. This eliminates copy-paste drift where a change lands in production but not staging.

Helm's release management means upgrade --install is idempotent with a revision history, and rollback restores a previous known-good state in one command. The --atomic flag is essential in production: if new pods fail readiness checks, Helm automatically rolls back instead of leaving the cluster half-upgraded.

Reach for Helm when deploying across multiple environments, when you need atomic releases with rollback, or when consuming third-party charts. For a single app in one environment, raw manifests or Kustomize may be simpler. At National Bank of India, converting our payments-service to Helm eliminated config drift between environments and turned a 15-minute manual rollback into a one-command operation.

Remember one sentence: Helm turns per-environment YAML copies into one templated chart with values overrides, giving you atomic releases and one-command rollback.

---

Share
Use ← → arrow keys to navigate