Helm is a package manager for packaging, deploying, and version management of Kubernetes applications. It was first developed by Deis (now Microsoft) in 2015, joined CNCF (Cloud Native Computing Foundation) in 2018, and has become the most widely used deployment tool in the Kubernetes ecosystem. Helm performs a similar role in Kubernetes as apt or yum in Linux or Homebrew in macOS. It bundles complex Kubernetes manifest files into packages called Charts, enabling installation, upgrade, and rollback with a single command while automating environment-specific configuration management and dependency handling to significantly reduce deployment complexity.

Helm Overview

What is Helm?

Helm is a package manager for Kubernetes that defines, installs, and upgrades Kubernetes applications through packages called Charts. Known as “apt/yum for Kubernetes,” it enables deploying complex applications with a single command.

Helm Development History

YearEventSignificance
2015Helm v1 released (Deis)Introduced Kubernetes package management concept
2016Helm v2 releasedIntroduced Tiller server, expanded production use
2018Joined CNCFRecognized as official Kubernetes ecosystem project
2019Helm v3 releasedRemoved Tiller, enhanced security, 3-way merge
CurrentHelm v3.xCNCF Graduated project

Helm v2 vs Helm v3

FeatureHelm v2Helm v3
TillerRequired (server component)Removed
SecurityTiller needed broad permissionsUses user kubeconfig permissions
Release StorageConfigMap (Tiller namespace)Secret (release namespace)
3-way MergeNot supportedSupported (reflects live state)
NamespaceManaged by TillerPer-release namespace
Chart ValidationBasic validationJSON Schema support

Core Concepts

Chart

What is a Chart?

A Chart is a collection of files describing Kubernetes resources, consisting of templated YAML manifests, metadata (Chart.yaml), and default configuration values (values.yaml). It is Helm’s basic deployment unit.

Release

A release is a running instance of a Chart. The same Chart can be installed multiple times with different configurations, and each installation has a unique release name. For example, a MySQL Chart can be installed as two releases named mysql-production and mysql-staging.

Repository

A place to store and share Charts, hosted on HTTP servers with chart listings managed through an index.yaml file. Notable repositories include Artifact Hub (formerly Helm Hub) and Bitnami Charts.

Values

Configuration values that override Chart defaults, defined in values.yaml or passed as command-line arguments.

Helm Installation

Installation Methods by Operating System

Operating SystemInstallation Command
macOS (Homebrew)brew install helm
Linux (Script)curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash
Windows (Chocolatey)choco install kubernetes-helm

Verify installation:

helm version

Basic Commands

Repository Management

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

# List repositories
helm repo list

# Update repositories (sync latest chart info)
helm repo update

# Remove repository
helm repo remove bitnami

Chart Search and Information

# Search charts in repository
helm search repo nginx

# Search in Artifact Hub
helm search hub nginx

# View chart information
helm show chart bitnami/nginx
helm show values bitnami/nginx
helm show readme bitnami/nginx

Release Management

CommandDescription
helm install <release> <chart>Install chart
helm upgrade <release> <chart>Upgrade release
helm rollback <release> <revision>Rollback to previous version
helm uninstall <release>Delete release
helm listList installed releases
helm history <release>Release history
helm status <release>Check release status
# Install chart
helm install my-nginx bitnami/nginx

# Install with custom values
helm install my-nginx bitnami/nginx -f custom-values.yaml

# Specify values from command line
helm install my-nginx bitnami/nginx --set service.type=LoadBalancer

# Install in specific namespace
helm install my-nginx bitnami/nginx -n production --create-namespace

# Upgrade (install if not exists)
helm upgrade --install my-nginx bitnami/nginx

# Rollback
helm rollback my-nginx 1

# Uninstall
helm uninstall my-nginx

Chart Structure

Standard Helm Chart directory structure:

mychart/
├── Chart.yaml          # Chart metadata
├── Chart.lock          # Dependency version lock
├── values.yaml         # Default configuration values
├── values.schema.json  # Values schema (optional)
├── charts/             # Dependency charts (subcharts)
├── crds/               # Custom Resource Definitions
├── templates/          # Template files
│   ├── NOTES.txt       # Post-install message
│   ├── _helpers.tpl    # Reusable template definitions
│   ├── deployment.yaml
│   ├── service.yaml
│   └── ...
└── README.md

Chart.yaml

apiVersion: v2           # Helm 3 uses v2
name: mychart
version: 1.0.0           # Chart version (SemVer)
appVersion: "1.16.0"     # Application version
description: My application Helm chart
type: application        # application or library
keywords:
  - web
  - nginx
maintainers:
  - name: DevOps Team
    email: [email protected]
dependencies:
  - name: redis
    version: "17.x.x"
    repository: "https://charts.bitnami.com/bitnami"
    condition: redis.enabled

values.yaml

replicaCount: 1

image:
  repository: nginx
  tag: "1.21"
  pullPolicy: IfNotPresent

service:
  type: ClusterIP
  port: 80

resources:
  limits:
    cpu: 100m
    memory: 128Mi
  requests:
    cpu: 50m
    memory: 64Mi

nodeSelector: {}
tolerations: []
affinity: {}

Template Writing

Helm templates are based on the Go template language, dynamically generating Kubernetes manifests by referencing values from values.yaml.

Basic Syntax

apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ .Release.Name }}-{{ .Chart.Name }}
  labels:
    app: {{ .Chart.Name }}
    release: {{ .Release.Name }}
spec:
  replicas: {{ .Values.replicaCount }}
  selector:
    matchLabels:
      app: {{ .Chart.Name }}
  template:
    spec:
      containers:
        - name: {{ .Chart.Name }}
          image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
          ports:
            - containerPort: {{ .Values.service.port }}

Key Built-in Objects

ObjectDescription
.ValuesValues from values.yaml or passed via –set
.ReleaseRelease information (Name, Namespace, IsInstall, etc.)
.ChartContents of Chart.yaml
.FilesAccess to files in the chart
.CapabilitiesCluster information (API versions, etc.)
.TemplateCurrent template information

Control Structures

# Conditional
{{- if .Values.ingress.enabled }}
apiVersion: networking.k8s.io/v1
kind: Ingress
...
{{- end }}

# Loop
{{- range .Values.extraEnvVars }}
- name: {{ .name }}
  value: {{ .value | quote }}
{{- end }}

# with (scope change)
{{- with .Values.nodeSelector }}
nodeSelector:
  {{- toYaml . | nindent 2 }}
{{- end }}

Useful Functions

FunctionDescriptionExample
defaultSet default value{{ .Values.name | default "nginx" }}
quoteQuote string{{ .Values.name | quote }}
upper / lowerCase conversion{{ .Values.name | upper }}
toYamlConvert to YAML{{ toYaml .Values.labels | nindent 4 }}
indent / nindentIndentation{{ include "mychart.labels" . | nindent 4 }}
b64encBase64 encoding{{ .Values.secret | b64enc }}

Reusable Templates (_helpers.tpl)

{{/* Common labels definition */}}
{{- define "mychart.labels" -}}
helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version }}
app.kubernetes.io/name: {{ .Chart.Name }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}

{{/* Usage */}}
metadata:
  labels:
    {{- include "mychart.labels" . | nindent 4 }}

Chart Development and Testing

# Create new chart
helm create mychart

# Lint chart
helm lint mychart

# Render templates (without installing)
helm template my-release mychart

# Render with specific values
helm template my-release mychart -f prod-values.yaml

# Dry run (API server validation)
helm install my-release mychart --dry-run --debug

# Package chart
helm package mychart

# Update dependencies
helm dependency update mychart

Hooks

Helm Hooks allow defining resources that execute at specific points in the release lifecycle.

HookExecution Point
pre-installAfter template rendering, before resource creation
post-installAfter all resources created
pre-upgradeAfter template rendering during upgrade, before resource update
post-upgradeAfter upgrade completion
pre-deleteOn delete request, before resource deletion
post-deleteAfter all resources deleted
pre-rollbackAfter template rendering during rollback, before resource restoration
post-rollbackAfter rollback completion

Hook definition example:

apiVersion: batch/v1
kind: Job
metadata:
  name: "{{ .Release.Name }}-db-migrate"
  annotations:
    "helm.sh/hook": pre-upgrade
    "helm.sh/hook-weight": "5"
    "helm.sh/hook-delete-policy": hook-succeeded
spec:
  template:
    spec:
      containers:
        - name: migrate
          image: myapp:{{ .Values.image.tag }}
          command: ["./migrate.sh"]
      restartPolicy: Never

CI/CD Integration

Helm integrates easily into CI/CD pipelines. GitLab CI example:

stages:
  - lint
  - test
  - deploy

lint:
  stage: lint
  script:
    - helm lint ./charts/myapp

test:
  stage: test
  script:
    - helm template myapp ./charts/myapp
    - helm install myapp ./charts/myapp --dry-run --debug

deploy:
  stage: deploy
  script:
    - helm upgrade --install myapp ./charts/myapp
      --namespace production
      --create-namespace
      -f values-prod.yaml
      --wait
      --timeout 5m
  only:
    - main

Security Considerations

ItemRecommendation
Sensitive InformationDo not include directly in values.yaml; use Kubernetes Secrets or external secret management tools
Chart ValidationOnly use charts from trusted repositories; review contents before installation
RBACApply principle of least privilege; separate permissions by namespace
Signature VerificationVerify chart signatures with helm verify command

Conclusion

Helm is a core tool that standardizes packaging, deployment, and version management of Kubernetes applications. Since its initial development in 2015, it has become the de facto standard package manager in the Kubernetes ecosystem. It enables managing complex applications as single deployment units through Charts, environment-specific configuration management using templates and values, rollback functionality through release history, and sharing and reuse through chart repositories, significantly reducing the complexity of Kubernetes operations.