Stage 5 · Platform
Release Packaging with Helm & Kustomize
Chart Structure
Chart.yaml, templates, helpers, dependencies, library charts, and OCI registries.
Chart Anatomy
A Helm chart is a directory of files that describe a set of Kubernetes resources. The minimum chart requires Chart.yaml and templates/. Everything else is optional. Understanding the structure helps you create maintainable charts.
my-chart/
Chart.yaml # Required: chart metadata
Chart.lock # Dependency lock file
values.yaml # Default configuration
values.schema.json # JSON Schema for values validation
charts/ # Dependency charts
postgresql-13.2.24.tgz
templates/ # Kubernetes manifests
_helpers.tpl # Template helpers
deployment.yaml
service.yaml
ingress.yaml
configmap.yaml
serviceaccount.yaml
hpa.yaml
NOTES.txt # Post-install instructions
tests/ # Test files
test-connection.yaml
.helmignore # Files to ignoreEach file serves a purpose. _helpers.tpl defines reusable templates. NOTES.txt shows post-install instructions. values.schema.json validates user input. charts/ holds packed dependencies.
Chart.yaml Deep Dive
apiVersion: v2
name: my-app
description: A production-ready application chart
type: application
version: 0.1.0
appVersion: "1.0.0"
kubeVersion: ">=1.25.0"
keywords:
- web
- api
- production
maintainers:
- name: Platform Team
email: platform@example.com
url: https://example.com
home: https://github.com/my-org/my-app-chart
sources:
- https://github.com/my-org/my-app
icon: https://example.com/icon.png
deprecated: false
annotations:
artifacthub.io/category: integration-delivery
artifacthub.io/license: MITapiVersion: v2 is Helm 3. type: application for deployable charts, library for shared functions. kubeVersion ensures compatibility. annotations provide metadata for Artifact Hub and other registries.
Template Files
Templates are Kubernetes manifests with Go template syntax. They access values, reference other templates, and use functions to transform data. Every file in templates/ is rendered and applied.
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "my-chart.fullname" . }}
labels:
{{- include "my-chart.labels" . | nindent 4 }}
spec:
{{- if not .Values.autoscaling.enabled }}
replicas: {{ .Values.replicaCount }}
{{- end }}
selector:
matchLabels:
{{- include "my-chart.selectorLabels" . | nindent 6 }}
template:
metadata:
labels:
{{- include "my-chart.selectorLabels" . | nindent 8 }}
annotations:
checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }}
spec:
containers:
- name: {{ .Chart.Name }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
ports:
- name: http
containerPort: {{ .Values.service.targetPort }}
{{- with .Values.resources }}
resources:
{{- toYaml . | nindent 10 }}
{{- end }}The template uses include for reusable labels, conditionals for autoscaling, and with for resource blocks. The checksum annotation triggers restarts on config changes. default uses appVersion if tag is not set.
Helper Templates
Helper templates (_helpers.tpl) define reusable template snippets. They prevent duplication and ensure consistency across templates. Use define to create helpers and include to use them.
{{/*
Expand the name of the chart.
*/}}
{{- define "my-chart.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/*
Create a default fully qualified app name.
*/}}
{{- define "my-chart.fullname" -}}
{{- if .Values.fullnameOverride }}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- $name := default .Chart.Name .Values.nameOverride }}
{{- if contains $name .Release.Name }}
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- end }}
{{- end }}
{{/*
Common labels
*/}}
{{- define "my-chart.labels" -}}
helm.sh/chart: {{ include "my-chart.chart" . }}
{{ include "my-chart.selectorLabels" . }}
{{- if .Chart.AppVersion }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
{{- end }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}
{{/*
Selector labels
*/}}
{{- define "my-chart.selectorLabels" -}}
app.kubernetes.io/name: {{ include "my-chart.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}Helpers define: name (chart name), fullname (release + chart name), labels (standard Kubernetes labels), and selectorLabels (matching labels). These ensure every resource has consistent naming and labeling.
Library Charts
Library charts provide reusable templates without deploying any resources. They are imported by application charts. Use them to share common templates across multiple charts (e.g., standard labels, security contexts).
apiVersion: v2
name: common
description: Shared Helm templates
type: library
version: 0.1.0
---
# In the consuming chart:
apiVersion: v2
name: my-app
dependencies:
- name: common
version: "0.1.0"
repository: "oci://ghcr.io/my-org/charts"Library charts are type: library. They don't create resources — they only provide templates. Application charts import them as dependencies. Use {{ include "common.labels" . }} to use library templates.
OCI Registries
Helm 3 supports OCI 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 OCI registry
helm registry login ghcr.io -u $GITHUB_USER
# Package 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
helm install my-release oci://ghcr.io/my-org/charts/my-chart --version 0.1.0
# List versions
helm search oci://ghcr.io/my-org/charts/my-chart/OCI registries provide authentication, authorization, and immutability. Charts are versioned and tagged like container images. GitHub Container Registry, Docker Hub, and Azure Container Registry support OCI artifacts.
Add helm lint, kubeconform validation, and helm template testing to your CI pipeline. Use chart-testing (ct) for automated testing against multiple Kubernetes versions.
Mark this lesson complete to store local progress and unlock a cleaner resume path the next time you visit.