What is Helm? Kubernetes Package Manager Explained
Raw Kubernetes YAML is powerful but repetitive. A typical application deployment involves a Deployment manifest, a Service, an Ingress, a ConfigMap, one or more Secrets, and possibly a HorizontalPodAutoscaler and PodDisruptionBudget. Copy-pasting and manually editing those files for every environment -- development, staging, production -- is a maintenance burden and a source of drift.
Helm solves this by treating a set of Kubernetes manifests as a single installable, configurable, versioned package called a chart. Helm is the officially recommended package manager for Kubernetes and is a CNCF graduated project.
How Helm Works
A Helm chart is a directory with a fixed structure:
mychart/
Chart.yaml # Chart metadata (name, version, appVersion)
values.yaml # Default configuration values
templates/ # Kubernetes manifest templates
deployment.yaml
service.yaml
ingress.yaml
_helpers.tpl # Reusable template snippets
charts/ # Dependency charts (subcharts)
The templates use Go's text/template syntax to inject values. Here is a simplified deployment template:
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "mychart.fullname" . }}
labels:
{{- include "mychart.labels" . | nindent 4 }}
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
{{- include "mychart.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 }}
The values.yaml sets defaults:
replicaCount: 2
image:
repository: mycompany/api-server
tag: "v1.4.2"
service:
port: 3000
resources:
requests:
cpu: "100m"
memory: "128Mi"
limits:
cpu: "500m"
memory: "512Mi"
To deploy with the defaults: helm install api-server ./mychart. To override for production: helm install api-server ./mychart -f production-values.yaml where the override file only contains the fields that differ.
Core Helm Commands
# Add the Bitnami chart repository
helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo update
# Search for a chart
helm search repo bitnami/postgresql
# Install a chart with custom values
helm install my-postgres bitnami/postgresql \
--namespace databases \
--create-namespace \
--set auth.postgresPassword=supersecret \
--set primary.persistence.size=50Gi
# List installed releases
helm list -A
# Upgrade an existing release
helm upgrade my-postgres bitnami/postgresql \
--reuse-values \
--set primary.persistence.size=100Gi
# Roll back to a previous release revision
helm rollback my-postgres 1
# Uninstall a release
helm uninstall my-postgres -n databases
The rollback capability is one of Helm's most valuable features. Every helm upgrade creates a new release revision. Rolling back to the previous working version is a single command that Helm executes against the stored manifest history.
Helm in a GitOps Workflow
Helm and GitOps work together naturally. ArgoCD has native Helm support -- you point an ArgoCD Application at a chart (either a local path or a chart repository), provide a values file, and ArgoCD handles rendering and syncing. This means your production-values.yaml lives in Git, goes through code review, and any change to it triggers a sync.
A typical pattern in a GitOps repository:
# argocd-application.yaml
spec:
source:
repoURL: https://charts.bitnami.com/bitnami
chart: postgresql
targetRevision: 13.2.24
helm:
valueFiles:
- values/postgresql-production.yaml
Pinning targetRevision to an exact chart version is important -- helm repo update can otherwise silently pull a new chart version with breaking changes.
Helm vs. Kustomize
The comparison comes up frequently. Helm excels when you need rich parameterization -- conditional blocks, loops over lists of values, cross-environment configuration from a single template. The Go templating can become hard to read for complex charts, but the abstraction is powerful.
Kustomize (built into kubectl since v1.14) takes a different approach: base manifests plus environment-specific overlays. There is no templating -- just patches. It is simpler to reason about and avoids the "templating hell" that poorly written Helm charts can produce.
In practice, many organizations use Helm for third-party dependencies (databases, monitoring stacks, ingress controllers) and Kustomize for their own application manifests. ArgoCD supports both.
For more on the broader Kubernetes ecosystem, see the Kubernetes guide for beginners and the DevOps tools guide.
