helm chart
Helm is the package manager for Kubernetes, and a Chart is the packaging format Helm uses to define, install, and manage cloud-native applications. A single Chart typically describes a collection of related Kubernetes resources—such as Deployments, Services, ConfigMaps, and Ingresses—bundled together as one installable unit. By parameterizing templates through values.yaml, the same Chart can be reused across development, staging, and production environments without duplicating manifests.
Core Concepts
Before working with Charts, it helps to understand the fundamental vocabulary of the Helm ecosystem:
- Chart: A Helm package that contains Kubernetes manifest templates, default configuration values, and descriptive metadata.
- Release: A running instance of a Chart installed in a Kubernetes cluster. One Chart can be installed many times, producing multiple independent Releases.
- Repository: A location where Charts are stored and shared, either as a traditional HTTP chart repository or an OCI-compliant registry.
- Values: Configuration data injected into templates at render time, allowing operators to customize behavior without editing template files directly.
Chart Directory Structure
Running helm create generates a standard directory layout. Below is a typical example:
mychart/
├── Chart.yaml
├── values.yaml
├── charts/
├── templates/
│ ├── deployment.yaml
│ ├── service.yaml
│ ├── ingress.yaml
│ ├── _helpers.tpl
│ └── NOTES.txt
└── .helmignore
Each component serves a distinct purpose:
Chart.yamlholds metadata such as the Chart name, version, and the version of the application it deploys.values.yamlprovides default configuration values that templates can reference.templates/contains Kubernetes resource manifests written as Go templates.charts/stores dependent sub-Charts._helpers.tpldefines reusable template snippets and named templates.NOTES.txtdisplays post-installation instructions to the user..helmignorelists files to exclude when packaging the Chart.
Creating and Installing a Chart
The Helm CLI offers a straightforward workflow for scaffolding, validating, and deploying Charts:
helm create mychart
helm lint mychart
helm template my-release ./mychart
helm install my-release ./mychart
helm upgrade --install my-release ./mychart
helm list
helm uninstall my-release
Here is what each command does:
helm lintchecks the Chart for syntax errors and structural issues.helm templaterenders templates locally without contacting a cluster, which simplifies debugging.helm installcreates a new Release in the cluster.helm upgrade --installinstalls the Chart if no Release exists, or upgrades it if one already does.helm listshows currently deployed Releases.helm uninstallremoves a Release and its associated resources.
Working with Values and Templates
Templates use Go template syntax to dynamically generate Kubernetes manifests. Consider the following values.yaml:
replicaCount: 2
image:
repository: nginx
tag: "1.25"
service:
type: ClusterIP
port: 80
A corresponding templates/deployment.yaml might look like this:
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 }}"
ports:
- containerPort: {{ .Values.service.port }}
Helm exposes several built-in objects inside templates:
.Valuesreads values fromvalues.yamlor from flags passed on the command line..Release.Nameprovides the name of the current Release..Chart.Namereturns the name of the Chart..Capabilitiescontains information about the Kubernetes cluster version and API support.
Common template functions include include, quote, default, toYaml, and nindent. Conditional rendering is also supported:
{{- if .Values.ingress.enabled }}
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: {{ include "mychart.fullname" . }}
{{- end }}
Managing Dependencies
Complex applications often rely on other Charts, such as databases or message queues. Dependencies are declared in Chart.yaml:
dependencies:
- name: mysql
version: 9.x.x
repository: https://charts.bitnami.com/bitnami
condition: mysql.enabled
After editing the dependency list, run:
helm dependency update
This command downloads the referenced Charts into the charts/ directory. When the parent Chart is installed, its dependencies are installed alongside it unless disabled through their corresponding condition flags.
Packaging and Publishing Charts
Once a Chart is ready for distribution, it can be packaged into a versioned archive:
helm package mychart
To make the Chart available through a repository, generate an index file:
helm repo index .
Modern Helm also supports pushing Charts directly to OCI registries:
helm push mychart-0.1.0.tgz oci://registry.example.com/charts
In Chart.yaml, the version field identifies the Chart release itself, while appVersion identifies the version of the application being deployed. Both fields should follow semantic versioning to simplify upgrades, rollbacks, and dependency resolution.
Best Practices
Operating Helm Charts at scale benefits from a few disciplined habits:
- Validate Charts with
helm lintand inspect rendered output usinghelm template --debug. - Pin image tags to specific versions instead of using
latest, which prevents unexpected updates in production. - Define
resources.requestsandresources.limitsfor every container to support stable scheduling and autoscaling. - Use
values.schema.jsonto enforce the structure and types of user-supplied values. - Centralize labels, annotations, and selector logic in
_helpers.tplso they remain consistent across all templates. - Never store secrets or sensitive credentials in plain text inside
values.yaml; use Kubernetes Secrets or an external secret manager instead. - Adhere to Semantic Versioning when changing Chart versions, making it easier to track changes and roll back when necessary.
Conclusion
Helm Charts bring templating, versioning, and reusability to Kubernetes application management. By mastering Chart structure, value injection, template syntax, dependency handling, and distribution workflows, teams can operate complex workloads with greater consistency and less manual effort. Combining these capabilities with linting, local rendering, and disciplined versioning ensures that Charts remain maintainable, stable, and easy to operate across environments.