Best Practices
Lint, template-render, and version your charts; keep values documented and templates predictable.
A few habits keep charts reliable and easy for others to use.
Validate before shipping
helm lint ./chart— catch structural and convention issues.helm template ./chart— render locally and eyeball the YAML.helm install --dry-run --debug— validate against a real cluster's API without applying.
Design guidelines
- Give every value a sensible default and a comment.
- Use the standard
app.kubernetes.iolabels via a shared helper. - Prefix helper templates with the chart name to avoid collisions.
- Bump
versionon every chart change; useappVersionfor the app. - Prefer
includeovertemplateso you can pipe throughnindent. - Quote strings that could be misread as numbers or booleans.
Example
# A typical pre-release validation pipeline
helm lint ./mychart
helm template ./mychart --debug > /dev/null
helm install my-web ./mychart --dry-run --debug
# Then package and publish
helm package ./mychart
helm push mychart-0.1.0.tgz oci://registry.example.com/chartsWhen to use it
- A chart maintainer runs helm lint --strict in the CI pipeline on every pull request to catch missing required fields and non-standard conventions before code review.
- A developer increments the chart's version field in Chart.yaml on every change so users of the chart repository can track changes and pin to a known-good version.
- A platform team adds comments above every key in values.yaml documenting the purpose and accepted values, treating the file as the chart's user-facing API documentation.
More examples
Lint before packaging
Runs lint for standard checks, strict lint for warnings-as-errors, and template to catch rendering errors before packaging.
helm lint ./myapp
helm lint ./myapp --strict
helm template my-release ./myapp -f values.yaml > /dev/nullDocument values clearly
Shows values.yaml documented with comments explaining each field's purpose and accepted values, making it self-documenting.
# values.yaml
# replicaCount: number of Pod replicas (min 1, scale >=3 for HA)
replicaCount: 1
# image.pullPolicy: Always | IfNotPresent | Never
image:
repository: myregistry/myapp
tag: "" # Defaults to Chart.appVersion when empty
pullPolicy: IfNotPresentVersion bump workflow
Shows a complete release workflow: bump version, lint, dry-run apply for Kubernetes validation, then package and push.
# After each chart change:
# 1. Bump version in Chart.yaml (follows semver)
# 2. Lint and template-test
helm lint ./myapp --strict
helm template test-release ./myapp | kubectl apply --dry-run=client -f -
# 3. Package and publish
helm package ./myapp && helm push myapp-*.tgz oci://ghcr.io/myorg/charts
Discussion