Helm Chart Development Best Practices
Chart Structure & Naming
- •Chart names: lowercase letters, numbers, and dashes only (e.g.,
nginx-ingress). - •No uppercase, underscores, or dots in chart names.
- •
Chart.yaml(capitalized), all template files lowercase. - •Template files:
.yamlfor YAML output,.tplfor non-formatted content. - •Template file names: dashed notation (
my-example-configmap.yaml), not camelCase. - •Each resource definition in its own template file, named after the resource kind.
- •Standard directory structure:
code
mychart/ Chart.yaml values.yaml templates/ deployment.yaml service.yaml _helpers.tpl tests/ charts/ crds/ .helmignore
Chart.yaml Metadata
- •Always
apiVersion: v2for Helm 3. - •Semantic versioning for
version, separateappVersionfor the application. - •Required:
name,description,type,version. - •Include
maintainers,home,sources,keywordsfor discoverability. - •
dependencieswith version constraints (e.g.,~> 1.2.0). - •Chart
type:application(deployable) orlibrary(reusable).
Values & Configuration
- •camelCase for variable names starting lowercase (e.g.,
chickenNoodleSoup). - •Never use hyphens or initial caps in value names.
- •Prefer flat over nested values when possible.
- •Use maps over arrays for
--setcompatibility. - •Quote all strings to avoid YAML type coercion.
- •Store large integers as strings, use
{{ int $value }}in templates. - •Every value must have a comment starting with the property name:
yaml
# serverHost is the host name for the webserver serverHost: example
- •Group related configs (e.g.,
image.*,service.*,ingress.*). - •Use
globalsparingly. Support env-specific value files (values-dev.yaml,values-prod.yaml).
Templates & Functions
- •Use
{{- }}for whitespace control. - •Two spaces for indentation, never tabs.
- •Whitespace after
{{and before}}:{{ .foo }}not{{.foo}}. - •Namespace defined templates:
{{- define "nginx.fullname" }}not{{- define "fullname" }}. - •Always quote string values:
{{ .Values.image.tag | quote }}. - •Use
requiredfor mandatory values:{{ required "Image repository required" .Values.image.repository }}. - •Prefer
includeovertemplatefor better error handling. - •Use
_helpers.tplfor reusable snippets. - •Template comments:
{{- /* comment */ -}}. YAML comments:#for user-visible info.
Labels & Annotations
- •Labels for K8s identification/querying, annotations for non-queryable metadata.
- •Required labels:
yaml
app.kubernetes.io/name: {{ include "chart.name" . }} app.kubernetes.io/instance: {{ .Release.Name }} helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} app.kubernetes.io/managed-by: {{ .Release.Service }} - •Helm hooks: always annotations, never labels.
- •Keep label selectors consistent across all resources.
Security & RBAC
- •Default
rbac.create: trueandserviceAccount.create: true. - •Use standardized ServiceAccount helper template.
- •Security contexts at both pod and container levels.
- •Run as non-root when possible. Use
readOnlyRootFilesystem: truewhere applicable. - •Default
automountServiceAccountToken: falseunless required. - •Never hardcode secrets.
Pod & Container Configuration
- •Fixed image tags or SHA — never
latest,head,canary, or floating tags. - •Separate
image.repositoryandimage.tagin values. - •Default
ImagePullPolicy: IfNotPresent. - •Always declare explicit pod selectors using stable labels.
Resource Management
- •Always set resource requests and limits.
- •Configure
livenessProbeandreadinessProbe. - •Use
nodeSelector,affinity,tolerationsfor scheduling.
Dependencies & Subcharts
- •Patch-level version matching:
version: ~1.2.3. - •Prefer
https://repository URLs. - •Conditional dependencies:
condition: somechart.enabled. - •Run
helm dependency updateafter Chart.yaml changes. - •Use
aliasfor multiple instances of the same dependency.
CRDs
- •Place in
crds/directory (not templated, installed as static YAML). - •Helm doesn't support CRD upgrades or deletions for safety.
- •Consider separate chart for CRDs vs resources.
Testing & Validation
- •Include
templates/tests/forhelm test. - •
helm lintfor static validation. - •
helm template --debugfor rendering issues. - •
helm-unittestfor unit testing templates.
Versioning
- •Semantic versioning. Increment chart version for any change.
- •Separate
appVersionfor the application version. - •Sign charts with
helm package --sign.
CI/CD
- •
helm lint charts/*andhelm template charts/* --validatein CI. - •Security scanning with
checkovorkube-score. - •Automated testing with
chart-testing(ct).