Helm Charts Skill
Overview
Helm is the package manager for Kubernetes. It packages Kubernetes manifests into reusable charts that can be versioned, shared, and deployed with customizable values.
Core Concepts
What is a Helm Chart?
A chart is a collection of files that describe a related set of Kubernetes resources:
code
mychart/ ├── Chart.yaml # Chart metadata (name, version, dependencies) ├── values.yaml # Default configuration values ├── charts/ # Dependency charts ├── templates/ # Kubernetes manifest templates │ ├── deployment.yaml │ ├── service.yaml │ ├── ingress.yaml │ ├── configmap.yaml │ ├── secret.yaml │ ├── _helpers.tpl # Template helpers │ └── NOTES.txt # Post-install notes └── .helmignore # Files to ignore when packaging
Key Files
| File | Purpose |
|---|---|
Chart.yaml | Metadata: name, version, appVersion, dependencies |
values.yaml | Default configuration values (overridable) |
templates/ | Go-templated Kubernetes manifests |
_helpers.tpl | Reusable template snippets |
Chart.yaml Structure
yaml
apiVersion: v2 # Helm 3 uses v2
name: taskflow # Chart name
description: TaskFlow Platform # Short description
type: application # application or library
version: 1.0.0 # Chart version (SemVer)
appVersion: "1.0.0" # Application version
# Dependencies (optional)
dependencies:
- name: postgresql
version: "12.x.x"
repository: "https://charts.bitnami.com/bitnami"
condition: postgresql.enabled
values.yaml Pattern
yaml
# Global settings
global:
imageRegistry: ""
imagePullSecrets: []
# Per-service configuration
api:
replicaCount: 1
image:
repository: taskflow/api
tag: "latest"
pullPolicy: IfNotPresent
service:
type: ClusterIP
port: 8000
resources:
limits:
cpu: 500m
memory: 512Mi
requests:
cpu: 100m
memory: 128Mi
env:
DATABASE_URL: ""
SSO_URL: "http://sso:3001"
# Feature flags
postgresql:
enabled: true
auth:
postgresPassword: "postgres"
database: "taskflow"
Template Syntax
Accessing Values
yaml
# templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "taskflow.fullname" . }}
labels:
{{- include "taskflow.labels" . | nindent 4 }}
spec:
replicas: {{ .Values.api.replicaCount }}
selector:
matchLabels:
{{- include "taskflow.selectorLabels" . | nindent 6 }}
template:
spec:
containers:
- name: {{ .Chart.Name }}
image: "{{ .Values.api.image.repository }}:{{ .Values.api.image.tag }}"
ports:
- containerPort: {{ .Values.api.service.port }}
env:
- name: DATABASE_URL
value: {{ .Values.api.env.DATABASE_URL | quote }}
Helper Templates (_helpers.tpl)
yaml
{{/*
Expand the name of the chart.
*/}}
{{- define "taskflow.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/*
Create a default fully qualified app name.
*/}}
{{- define "taskflow.fullname" -}}
{{- if .Values.fullnameOverride }}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- $name := default .Chart.Name .Values.nameOverride }}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- end }}
{{/*
Common labels
*/}}
{{- define "taskflow.labels" -}}
helm.sh/chart: {{ include "taskflow.chart" . }}
{{ include "taskflow.selectorLabels" . }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}
{{/*
Selector labels
*/}}
{{- define "taskflow.selectorLabels" -}}
app.kubernetes.io/name: {{ include "taskflow.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}
Essential Commands
Create New Chart
bash
helm create mychart
Install Chart
bash
# From local directory helm install my-release ./mychart # With custom values file helm install my-release ./mychart --values custom-values.yaml # With inline value overrides helm install my-release ./mychart \ --set api.replicaCount=3 \ --set api.image.tag=v2.0.0 # To specific namespace (create if needed) helm install my-release ./mychart \ --namespace production \ --create-namespace # Dry run (preview without installing) helm install my-release ./mychart --dry-run --debug
Upgrade Release
bash
helm upgrade my-release ./mychart --values new-values.yaml
Rollback
bash
helm rollback my-release 1 # Rollback to revision 1
Uninstall
bash
helm uninstall my-release
List Releases
bash
helm list helm list --all-namespaces
Debug Templates
bash
# Render templates without installing helm template my-release ./mychart # Debug with computed values helm template my-release ./mychart --debug
Multi-Service Chart Pattern
For TaskFlow (api, sso, web, mcp-server), use a single chart with multiple templates:
code
helm/taskflow/ ├── Chart.yaml ├── values.yaml ├── templates/ │ ├── _helpers.tpl │ ├── NOTES.txt │ ├── api/ │ │ ├── deployment.yaml │ │ ├── service.yaml │ │ └── configmap.yaml │ ├── sso/ │ │ ├── deployment.yaml │ │ └── service.yaml │ ├── web/ │ │ ├── deployment.yaml │ │ └── service.yaml │ ├── mcp-server/ │ │ ├── deployment.yaml │ │ └── service.yaml │ └── ingress.yaml
ConfigMap and Secrets
ConfigMap Template
yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ include "taskflow.fullname" . }}-config
data:
SSO_URL: {{ .Values.sso.url | quote }}
API_URL: {{ .Values.api.url | quote }}
Secret Template (from values)
yaml
apiVersion: v1
kind: Secret
metadata:
name: {{ include "taskflow.fullname" . }}-secrets
type: Opaque
data:
database-url: {{ .Values.secrets.databaseUrl | b64enc | quote }}
openai-api-key: {{ .Values.secrets.openaiApiKey | b64enc | quote }}
Health Checks Pattern
yaml
spec:
containers:
- name: api
livenessProbe:
httpGet:
path: /health
port: 8000
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /health
port: 8000
initialDelaySeconds: 5
periodSeconds: 5
Ingress Pattern
yaml
{{- if .Values.ingress.enabled -}}
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: {{ include "taskflow.fullname" . }}
annotations:
{{- toYaml .Values.ingress.annotations | nindent 4 }}
spec:
ingressClassName: {{ .Values.ingress.className }}
rules:
- host: {{ .Values.ingress.host }}
http:
paths:
- path: /api
pathType: Prefix
backend:
service:
name: {{ include "taskflow.fullname" . }}-api
port:
number: 8000
- path: /
pathType: Prefix
backend:
service:
name: {{ include "taskflow.fullname" . }}-web
port:
number: 3000
{{- end }}
Common Gotchas
- •Quote strings in templates: Use
{{ .Values.foo | quote }}for strings - •Indentation matters: Use
nindentfor proper YAML formatting - •Resource names: Keep under 63 characters (K8s limit)
- •Image pull policy: Use
IfNotPresentin production,Alwaysin dev - •Secrets: Never commit real secrets to values.yaml
Resources
Refer to references/ for:
- •
chart-patterns.md- Advanced templating patterns - •
values-structure.md- Values.yaml organization guide
Refer to assets/ for:
- •
base-chart/- Complete starter chart template