Helm — Deep Dive

Level: Intermediate
Pre-reading: 09 · Deployment & Infrastructure


What is Helm?

Helm is a package manager for Kubernetes. It packages K8s manifests into reusable charts.


Helm Concepts

Concept Description
Chart Package of K8s templates
Values Configuration parameters
Release Deployed instance of a chart
Repository Chart storage (like npm registry)

Chart Structure

order-service/
├── Chart.yaml          # Chart metadata
├── values.yaml         # Default values
├── templates/
│   ├── deployment.yaml
│   ├── service.yaml
│   ├── configmap.yaml
│   ├── _helpers.tpl    # Template helpers
│   └── NOTES.txt       # Post-install notes
└── charts/             # Dependencies

Chart.yaml

apiVersion: v2
name: order-service
version: 1.0.0
appVersion: "1.2.3"
description: Order service deployment
dependencies:
  - name: postgresql
    version: 12.x.x
    repository: https://charts.bitnami.com/bitnami
    condition: postgresql.enabled

Templates

# templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ include "order-service.fullname" . }}
  labels:
    {{- include "order-service.labels" . | nindent 4 }}
spec:
  replicas: {{ .Values.replicaCount }}
  selector:
    matchLabels:
      {{- include "order-service.selectorLabels" . | nindent 6 }}
  template:
    spec:
      containers:
        - name: {{ .Chart.Name }}
          image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
          ports:
            - containerPort: {{ .Values.service.port }}
          resources:
            {{- toYaml .Values.resources | nindent 12 }}
          {{- if .Values.env }}
          env:
            {{- range $key, $value := .Values.env }}
            - name: {{ $key }}
              value: {{ $value | quote }}
            {{- end }}
          {{- end }}

values.yaml

replicaCount: 2

image:
  repository: myregistry/order-service
  tag: "1.2.3"
  pullPolicy: IfNotPresent

service:
  type: ClusterIP
  port: 8080

resources:
  requests:
    memory: "256Mi"
    cpu: "250m"
  limits:
    memory: "512Mi"
    cpu: "500m"

env:
  SPRING_PROFILES_ACTIVE: production

Helm Commands

# Install
helm install order-release ./order-service -f values-prod.yaml

# Upgrade
helm upgrade order-release ./order-service -f values-prod.yaml

# Rollback
helm rollback order-release 1

# List releases
helm list

# Show history
helm history order-release

# Uninstall
helm uninstall order-release

# Template (dry-run)
helm template ./order-service -f values-prod.yaml

Environment Overrides

# Base values + environment-specific
helm install order-release ./order-service \
  -f values.yaml \
  -f values-prod.yaml \
  --set image.tag=1.2.4

values-prod.yaml

replicaCount: 5
resources:
  requests:
    memory: "512Mi"
    cpu: "500m"

Helm vs Kustomize

Aspect Helm Kustomize
Templating Go templates Patches/overlays
Complexity Higher Lower
Packaging Charts Bases + overlays
Built into kubectl No Yes

When should you use Helm vs raw manifests?

Use Helm when: (1) Deploying to multiple environments. (2) Need parameterization. (3) Managing complex applications. (4) Using third-party charts. Use raw manifests for simple, single-environment deployments.

How do you manage secrets with Helm?

(1) helm-secrets plugin — encrypts values files. (2) External Secrets Operator — reference secrets by name. (3) Sealed Secrets — encrypt for GitOps. Don't put secrets in plain values files in Git.

Helm vs Kustomize — which to choose?

Helm: Better for complex parameterization, third-party charts, release management. Kustomize: Simpler, built into kubectl, good for environment overlays. Many teams use both: Helm for base charts, Kustomize for environment-specific overlays.