Helm Charts — Package Manager for Kubernetes

Sanjeev SharmaSanjeev Sharma
4 min read

Advertisement

Helm Charts — Package Manager for Kubernetes

Helm is the package manager for Kubernetes. Learn to create, manage, and deploy applications using Helm charts.

Introduction

Helm simplifies Kubernetes deployments by templating, versioning, and managing releases. It enables reproducible, shareable application packages.

Installation

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

# Verify
helm version

# Add Helm repositories
helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo add stable https://charts.helm.sh/stable
helm repo update

# Search for charts
helm search repo nginx

Using Existing Charts

Installing Charts

# Install nginx from Helm Hub
helm install my-nginx bitnami/nginx

# Install with custom values
helm install my-nginx bitnami/nginx \
  --set replicaCount=3 \
  --set service.type=LoadBalancer

# Install in specific namespace
helm install my-nginx bitnami/nginx \
  --namespace web \
  --create-namespace

Managing Releases

# List releases
helm list

# Get release status
helm status my-nginx

# View release values
helm get values my-nginx

# Upgrade release
helm upgrade my-nginx bitnami/nginx \
  --set replicaCount=5

# Rollback release
helm rollback my-nginx 1

# Uninstall release
helm uninstall my-nginx

Creating Your First Chart

# Create chart scaffold
helm create mychart

# Chart structure:
# mychart/
# ├── Chart.yaml
# ├── values.yaml
# ├── templates/
# │   ├── deployment.yaml
# │   ├── service.yaml
# │   ├── ingress.yaml
# │   └── _helpers.tpl
# └── charts/

# Directory details
tree mychart/

Chart.yaml

apiVersion: v2
name: mychart
description: A Helm chart for my application
type: application
version: 0.1.0
appVersion: "1.0"

values.yaml

replicaCount: 3

image:
  repository: myapp
  tag: "1.0"
  pullPolicy: IfNotPresent

service:
  type: LoadBalancer
  port: 80
  targetPort: 3000

ingress:
  enabled: true
  hosts:
    - host: myapp.example.com
      paths:
        - path: /

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

autoscaling:
  enabled: true
  minReplicas: 2
  maxReplicas: 10
  targetCPUUtilizationPercentage: 80

Templating

Basic Templates

# templates/deployment.yaml
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:
    metadata:
      labels:
        {{- include "mychart.selectorLabels" . | nindent 8 }}
    spec:
      containers:
      - name: {{ .Chart.Name }}
        image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
        imagePullPolicy: {{ .Values.image.pullPolicy }}
        ports:
        - name: http
          containerPort: {{ .Values.service.targetPort }}
        resources:
          {{- toYaml .Values.resources | nindent 12 }}

Conditional Logic

{{- if .Values.ingress.enabled }}
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: {{ include "mychart.fullname" . }}
spec:
  rules:
  {{- range .Values.ingress.hosts }}
  - host: {{ .host }}
    http:
      paths:
      {{- range .paths }}
      - path: {{ .path }}
        pathType: Prefix
        backend:
          service:
            name: {{ include "mychart.fullname" $ }}
            port:
              number: {{ $.Values.service.port }}
      {{- end }}
  {{- end }}
{{- end }}

Loops

env:
{{- range $key, $value := .Values.env }}
- name: {{ $key }}
  value: {{ $value | quote }}
{{- end }}

Packaging and Distribution

Package Chart

# Create chart package
helm package mychart/

# Creates: mychart-0.1.0.tgz

# Create repository index
helm repo index .

# List chart versions
ls -la mychart-*.tgz

Publish to Helm Hub

# Create GitHub repository for chart
# Add index.yaml and chart packages

# Users can then:
helm repo add myrepo https://github.com/user/helm-charts/raw/main
helm repo update
helm install mychart myrepo/mychart

Advanced Features

Subchart Dependencies

# Chart.yaml
dependencies:
- name: postgresql
  version: "11.0.0"
  repository: https://charts.bitnami.com/bitnami
  condition: postgresql.enabled

- name: redis
  version: "17.0.0"
  repository: https://charts.bitnami.com/bitnami
  condition: redis.enabled
# values.yaml
postgresql:
  enabled: true
  auth:
    password: secretpassword

redis:
  enabled: true
  auth:
    password: redispassword

Update dependencies:

helm dependency update mychart/

Hooks

Execute actions at specific release stages:

# templates/backup-hook.yaml
apiVersion: batch/v1
kind: Job
metadata:
  name: backup-db
  annotations:
    "helm.sh/hook": pre-upgrade
    "helm.sh/hook-weight": "-5"
spec:
  template:
    spec:
      containers:
      - name: backup
        image: backup:1.0
      restartPolicy: Never

Testing Charts

# Validate chart
helm lint mychart/

# Dry run
helm install my-release mychart/ --dry-run

# Generate templates
helm template my-release mychart/

# Test installation
helm install my-release mychart/ --verify

Best Practices

  1. Use semantic versioning for chart versions
  2. Keep values.yaml simple and well-commented
  3. Use helper templates for consistency
  4. Test charts thoroughly before release
  5. Document chart usage in README
  6. Pin dependency versions precisely
  7. Use init containers for setup tasks

FAQ

Q: What's the difference between Helm and Kustomize? A: Helm uses templating with a package manager; Kustomize uses overlays. Helm is more suitable for distributing applications; Kustomize for customizing deployments.

Q: Can I override values from command line? A: Yes, use --set key=value or --values file.yaml to override values.

Q: How do I version my charts? A: Use semantic versioning in Chart.yaml. Increment version for releases, and appVersion for application updates.

Advertisement

Sanjeev Sharma

Written by

Sanjeev Sharma

Full Stack Engineer · E-mopro