Once you have more than one Kubernetes application to manage, raw YAML manifests start to show their limits. Every environment needs slightly different values — different image tags, replica counts, resource limits, ingress hostnames — and maintaining separate copies of near-identical files is error-prone. Helm is the package manager for Kubernetes that solves this with charts: reusable, parameterized application packages.

What is a Helm Chart?

A chart is a directory of templates and a values file. Helm renders the templates using the values, then applies the resulting manifests to your cluster. The same chart can deploy to dev, staging, and production with different configurations.

mychart/
├── Chart.yaml          # chart metadata (name, version, description)
├── values.yaml         # default configuration values
└── templates/
    ├── deployment.yaml
    ├── service.yaml
    └── ingress.yaml

Installing Helm

# macOS
$ brew install helm

$ helm version
version.BuildInfo{Version:"v3.15.0", ...}

Using Community Charts

Before writing your own, check the Artifact Hub — there are production-ready charts for PostgreSQL, Redis, Nginx, Prometheus, and hundreds of other tools.

# add the Bitnami repository
$ helm repo add bitnami https://charts.bitnami.com/bitnami
"bitnami" has been added to your repositories

$ helm repo update
Hang tight while we grab the latest from your chart repositories...
...Successfully got an update from the "bitnami" chart repository

# search for a chart
$ helm search repo bitnami/postgresql
NAME                  CHART VERSION   APP VERSION   DESCRIPTION
bitnami/postgresql    15.5.3          16.3.0        PostgreSQL...

# install with custom values
$ helm install my-db bitnami/postgresql \
  --set auth.postgresPassword=secret \
  --set primary.persistence.size=20Gi \
  --namespace databases \
  --create-namespace

# check the release
$ helm list -n databases
NAME    NAMESPACE   REVISION  STATUS    CHART                 APP VERSION
my-db   databases   1         deployed  postgresql-15.5.3     16.3.0

Writing Your Own Chart

$ helm create myapp
Creating myapp

This scaffolds the directory structure. Edit values.yaml to define your defaults:

replicaCount: 2

image:
  repository: myuser/myapp
  tag: "1.0.0"
  pullPolicy: IfNotPresent

service:
  type: ClusterIP
  port: 80
  targetPort: 8000

ingress:
  enabled: false
  host: ""

resources:
  requests:
    cpu: 100m
    memory: 128Mi
  limits:
    cpu: 500m
    memory: 256Mi

In templates/deployment.yaml, reference values with the `` syntax:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: 
spec:
  replicas: 
  selector:
    matchLabels:
      app: 
  template:
    metadata:
      labels:
        app: 
    spec:
      containers:
        - name: 
          image: ":"
          imagePullPolicy: 
          ports:
            - containerPort: 
          resources:

Installing and Upgrading Your Chart

# install from local directory
$ helm install myapp ./myapp

# override values at install time
$ helm install myapp ./myapp \
  --set image.tag=1.1.0 \
  --set replicaCount=3

# or pass a values file (preferred for many overrides)
$ helm install myapp ./myapp -f production-values.yaml

# upgrade an existing release
$ helm upgrade myapp ./myapp --set image.tag=1.2.0

# upgrade or install if it doesn't exist
$ helm upgrade --install myapp ./myapp -f production-values.yaml

Per-Environment Values Files

Keep a values file per environment and commit them to git:

helm/
├── myapp/           # the chart
└── values/
    ├── dev.yaml
    ├── staging.yaml
    └── production.yaml
# production.yaml
replicaCount: 5

image:
  tag: "1.4.2"

ingress:
  enabled: true
  host: api.mycompany.com

resources:
  requests:
    cpu: 500m
    memory: 512Mi
$ helm upgrade --install myapp ./helm/myapp -f helm/values/production.yaml

Useful Commands

# render templates without applying (great for debugging)
$ helm template myapp ./myapp -f production.yaml

# list all releases
$ helm list -A

# check release history
$ helm history myapp
REVISION  STATUS     CHART        DESCRIPTION
1         superseded myapp-0.1.0  Install complete
2         deployed   myapp-0.1.0  Upgrade complete

# roll back to a previous revision
$ helm rollback myapp 1

# uninstall a release (removes all Kubernetes objects)
$ helm uninstall myapp

Conclusion

Helm turns a pile of environment-specific YAML files into a single parameterized package. Community charts let you deploy complex software like databases and monitoring stacks in minutes without writing hundreds of lines of manifest. For your own applications, a chart with a well-designed values.yaml makes the difference between deploying to a new environment in five minutes versus an afternoon of copy-paste and find-replace. Pair Helm with a GitOps tool like ArgoCD and you get automated, auditable deployments on top of that.