Stage 5 · Platform
Platform Engineering & Multi-Tenancy
Helm Charts & Packaging
Templates, values, dependencies, Chart Releaser, and OCI registries.
Helm Overview
Helm is the package manager for Kubernetes. It packages YAML manifests into reusable charts with parameterized templates, dependency management, and release lifecycle operations. Helm charts are the standard way to distribute and deploy Kubernetes applications.
# Install a chart
helm install my-release oci://registry.example.com/charts/my-app \
--namespace production \
--values values-prod.yaml \
--wait
# Upgrade a release
helm upgrade my-release oci://registry.example.com/charts/my-app \
--values values-prod.yaml \
--reuse-values # Keep previous values, override only specified
# Rollback a release
helm rollback my-release 1 # Rollback to revision 1
# List releases
helm list --all-namespaces
# Show release status
helm status my-release -n productionHelm manages releases — named installations of a chart. Each upgrade/rollback creates a new revision. --wait ensures all resources are ready before the command returns. --reuse-values keeps existing values for unspecified keys.
Chart Structure
my-chart/
Chart.yaml # Chart metadata (name, version, appVersion)
Chart.lock # Dependency lock file
values.yaml # Default configuration values
charts/ # Dependency charts (packed)
templates/ # Template files
deployment.yaml
service.yaml
ingress.yaml
configmap.yaml
_helpers.tpl # Template helpers
NOTES.txt # Post-install instructions
.helmignore # Files to ignore when packagingChart.yaml is required — it defines the chart name, version, and dependencies. values.yaml provides defaults that users can override. templates/ contains the Kubernetes manifests with template syntax.
Template Syntax
Helm templates use Go template syntax. Values are accessed via .Values. Functions like default, toYaml, and nindent transform data. The helper template (_helpers.tpl) defines reusable template snippets.
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "my-chart.fullname" . }}
labels:
{{- include "my-chart.labels" . | nindent 4 }}
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
{{- include "my-chart.selectorLabels" . | nindent 6 }}
template:
metadata:
labels:
{{- include "my-chart.selectorLabels" . | nindent 8 }}
spec:
containers:
- name: {{ .Chart.Name }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
ports:
- containerPort: {{ .Values.service.targetPort }}
{{- if .Values.resources }}
resources:
{{- toYaml .Values.resources | nindent 10 }}
{{- end }}The include function renders a named template. nindent adds a newline and indents the output. The if conditionally includes sections. .Values references values.yaml; .Chart references Chart.yaml.
Define common labels, selectors, and names in _helpers.tpl. This prevents copy-paste errors and ensures consistency across templates. Use the define and include functions to create and use helpers.
Values and Overrides
Values provide configuration without modifying templates. The default values.yaml is overridden by user-supplied files. Values files are merged: user values override defaults. Multiple values files can be specified in order of precedence.
# values.yaml (defaults)
replicaCount: 2
image:
repository: my-app
tag: "1.0"
pullPolicy: IfNotPresent
service:
port: 80
targetPort: 8080
resources:
requests:
cpu: "100m"
memory: "128Mi"
---
# values-prod.yaml (production overrides)
replicaCount: 5
image:
tag: "1.2.1"
resources:
requests:
cpu: "500m"
memory: "512Mi"
limits:
cpu: "1"
memory: "1Gi"
autoscaling:
enabled: true
minReplicas: 3
maxReplicas: 20Production values override defaults for replica count, image tag, and resources. The --values flag specifies the override file. --set can override individual values: --set replicaCount=10.
Chart Dependencies
Charts can depend on other charts. Dependencies are defined in Chart.yaml and downloaded to charts/ or pulled from OCI registries. This is used for shared libraries, databases, and monitoring agents.
apiVersion: v2
name: my-app
description: My application chart
type: application
version: 0.1.0
appVersion: "1.0.0"
dependencies:
- name: postgresql
version: "13.2.24"
repository: "https://charts.bitnami.com/bitnami"
condition: postgresql.enabled
- name: redis
version: "18.6.1"
repository: "https://charts.bitnami.com/bitnami"
condition: redis.enabled
- name: prometheus
version: "25.11.0"
repository: "oci://registry.example.com/charts"
alias: monitoring-prometheusThe condition field enables/disables dependencies via values. alias renames the dependency in templates. Run helm dependency update to download dependencies to charts/. Chart.lock pins exact versions.
OCI Registries
Helm supports OCI (Open Container Initiative) registries for chart storage. Charts are stored as OCI artifacts alongside container images. This eliminates the need for a separate chart repository server.
# Login to registry
helm registry login ghcr.io -u <username>
# Package a chart
helm package my-chart
# Push to OCI registry
helm push my-chart-0.1.0.tgz oci://ghcr.io/my-org/charts
# Install from OCI registry
helm install my-release oci://ghcr.io/my-org/charts/my-chart \
--version 0.1.0
# Search OCI registry (limited support)
helm search oci://ghcr.io/my-org/charts/OCI registries provide authentication, authorization, and immutability. Charts are versioned and tagged like container images. GitHub Container Registry, Docker Hub, and Azure Container Registry all support OCI artifacts.
Run helm lint my-chart to check for common mistakes: missing required values, invalid YAML, template errors. Add helm lint to CI pipelines to catch issues before deployment. Use --strict for additional checks.
Mark this lesson complete to store local progress and unlock a cleaner resume path the next time you visit.