Skip to main content
ContainersIntermediate

Helm Charts: Packaging Kubernetes Applications

Master Helm charts for Kubernetes — chart structure, values, templates, repositories, environment management, and deployment best practices.

N
Neeraj Jha
·Updated September 11, 2026·5 min read
Helm Charts: Packaging Kubernetes Applications

Helm is the package manager for Kubernetes. It lets you define, install, and upgrade complex Kubernetes applications using reusable templates called charts.

Why Helm?

Without Helm, deploying an application means managing dozens of YAML files — Deployments, Services, ConfigMaps, Secrets, Ingress, and more. Helm packages all of these into a single chart with configurable values.

  • Templating — one chart, multiple environments
  • Versioning — track releases, rollback instantly
  • Dependency management — include sub-charts (e.g., PostgreSQL, Redis)
  • Sharing — publish charts to repositories

Installing Helm

bash
# macOS
brew install helm

# Linux
curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash

# Verify
helm version

Chart Structure

my-app/
  Chart.yaml          # Chart metadata (name, version, description)
  values.yaml         # Default configuration values
  templates/          # Kubernetes manifest templates
    deployment.yaml
    service.yaml
    ingress.yaml
    configmap.yaml
    _helpers.tpl      # Template helper functions
  charts/             # Sub-chart dependencies
  .helmignore         # Files to exclude from packaging

Chart.yaml

yaml
apiVersion: v2
name: my-app
description: A Helm chart for my application
type: application
version: 0.1.0        # Chart version
appVersion: "1.4.2"   # Application version

dependencies:
  - name: postgresql
    version: "13.x.x"
    repository: "https://charts.bitnami.com/bitnami"
    condition: postgresql.enabled

values.yaml

yaml
replicaCount: 2

image:
  repository: myorg/my-app
  tag: "1.4.2"
  pullPolicy: IfNotPresent

service:
  type: ClusterIP
  port: 80

ingress:
  enabled: true
  className: nginx
  hosts:
    - host: app.example.com
      paths:
        - path: /
          pathType: Prefix

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

postgresql:
  enabled: true
  auth:
    database: myapp
    username: appuser

Templates

yaml
# templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ include "my-app.fullname" . }}
  labels:
    {{- include "my-app.labels" . | nindent 4 }}
spec:
  replicas: {{ .Values.replicaCount }}
  selector:
    matchLabels:
      {{- include "my-app.selectorLabels" . | nindent 6 }}
  template:
    metadata:
      labels:
        {{- include "my-app.selectorLabels" . | nindent 8 }}
    spec:
      containers:
        - name: {{ .Chart.Name }}
          image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
          imagePullPolicy: {{ .Values.image.pullPolicy }}
          ports:
            - containerPort: 3000
          resources:
            {{- toYaml .Values.resources | nindent 12 }}
          livenessProbe:
            httpGet:
              path: /health
              port: 3000
            initialDelaySeconds: 10
          readinessProbe:
            httpGet:
              path: /ready
              port: 3000
            initialDelaySeconds: 5

Common Helm Commands

bash
# Install a chart
helm install my-release ./my-app

# Install with custom values
helm install my-release ./my-app -f production-values.yaml

# Override individual values
helm install my-release ./my-app --set replicaCount=5

# Upgrade a release
helm upgrade my-release ./my-app --set image.tag=1.5.0

# Rollback to previous version
helm rollback my-release 1

# List releases
helm list

# Uninstall
helm uninstall my-release

# Template rendering (debug)
helm template my-release ./my-app

# Dry run
helm install my-release ./my-app --dry-run --debug

Working with Repositories

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

# Search for charts
helm search repo nginx

# Update repositories
helm repo update

# Install from a repository
helm install my-nginx bitnami/nginx

Environment-Specific Values

Create separate value files per environment:

values.yaml              # Defaults
values-staging.yaml      # Staging overrides
values-production.yaml   # Production overrides
bash
# Deploy to staging
helm upgrade --install my-app ./my-app -f values-staging.yaml -n staging

# Deploy to production
helm upgrade --install my-app ./my-app -f values-production.yaml -n production

Best Practices

  • Always use helm template to preview generated manifests before installing
  • Pin chart dependency versions in Chart.yaml
  • Use helm upgrade --install for idempotent deploys
  • Store value files in Git alongside your chart
  • Use --atomic flag to auto-rollback on failure
  • Validate charts with helm lint
  • Package and publish charts to a private registry (Harbor, ChartMuseum, OCI)

Helm turns Kubernetes deployments from a YAML management nightmare into a structured, versioned, repeatable process. Combined with GitOps, it forms the backbone of modern Kubernetes delivery.

Tagged with

Enjoyed this article?

Get more DevOps insights delivered to your inbox.

Get new posts by email

Subscribe to get an email when a new blog post is published. Skip anytime.

No spam, unsubscribe anytime.

N

Written by

Neeraj Jha

Platform administrator and lead writer.

View all posts

Discussion

0 comments

Sign in to join the conversation.

Be the first to comment

Start a conversation about this post

Share: