Post 6/10 — Helm Fundamentals Done Right: Chart Architecture, Values Schema, and Reuse

Source: Dev.to | Jan 18, 2026 (UTC)

If you’re reading this blog I’d guess you’re familiar with Helm and want to utilize if effectively. In case you aren’t, I got you. Helm is a powerful packaging tool that help scale the Kubernetes manifest in a structured manner. I have highlighted the importance of Helm in some of my previous blogs and I’m covering some extra bits in this one. Just want my DevOps Engineer to not miss out on this simple yet effective tool. Do check my previous releases on Helm on my profile.

1) Executive Summary

Helm charts can be a blessing or a mess — depending on how disciplined your structure is. In this post, I’ll show how to design charts that scale: clean folder layout, validated values, reusable helpers, and consistent environment overlays.
Think of this as the point where “copy-pasted YAML” evolves into a templatized, validated, and reusable release artifact.

2) Prereqs

You should already be comfortable with:

  • kubectl basics and manifests (Deployment, Service, Ingress).
  • helm install, upgrade, and uninstall.
  • YAML indentation and Go template syntax ({{ .Values.image.repository }}).

If not, go back to Post 5 where we replaced Ingress with Gateway API — that’s the level of confidence you need.

3) Concepts

a) Chart layout & sane defaults

A Helm chart is just structured YAML + templates + metadata.

Default layout:

mychart/ ├── Chart.yaml ├── values.yaml ├── values.schema.json ├── templates/ │ ├── deployment.yaml │ ├── service.yaml │ └── _helpers.tpl └── charts/

Enter fullscreen mode

Exit fullscreen mode

Why it matters:

Decision cue:
If you can’t read your chart structure at a glance — it’s probably too magical. Keep it explicit.

b) values.schema.json validation

This file enforces structure and type-checking for your values.yaml.
Without it, Helm silently ignores typos — your app may deploy with wrong configs.

Before → After

Before:

# values.yaml image: repo: nginx tag: latest # typo: should be 'repository'

Enter fullscreen mode

Exit fullscreen mode

After:

// values.schema.json { "$schema": "https://json-schema.org/draft-07/schema#", "properties": { "image": { "type": "object", "properties": { "repository": { "type": "string" }, "tag": { "type": "string" } }, "required": ["repository"] } } }

Enter fullscreen mode

Exit fullscreen mode

Now, helm lint will fail fast if someone mis-keys a field.

Decision cue:
If multiple people edit values.yaml, a schema is mandatory.

c) Helpers/partials & library charts

Avoid repetition. Use helpers (_helpers.tpl) for common names, labels, and annotations.

# _helpers.tpl {{- define "app.fullname" -}} {{ printf "%s-%s" .Release.Name .Chart.Name }} {{- end -}}

Enter fullscreen mode

Exit fullscreen mode

Then reuse it:

metadata: name: {{ include "app.fullname" . }}

Enter fullscreen mode

Exit fullscreen mode

When multiple services share common patterns (e.g., serviceaccount.yaml, probes, labels), extract them into a library chart.
Library charts have no manifests — just helpers and templates that other charts can import.

Decision cue:
When you copy the same YAML block in more than two charts — extract it into a helper or library.

d) Environment overlays strategy

Instead of maintaining values-dev.yaml, values-stg.yaml, and values-prod.yaml in chaos, organize by overlays:

values/ base.yaml dev.yaml stg.yaml prod.yaml

Enter fullscreen mode

Exit fullscreen mode

Each extends the base:

helm install myapp . -f values/base.yaml -f values/prod.yaml

Enter fullscreen mode

Exit fullscreen mode

Best practice:

4) Mini-Lab — From Raw Manifests to Chart

  1. Start with raw YAML:

kubectl create deploy web --image=nginx --dry-run=client -o yaml > deployment.yaml kubectl expose deploy web --port=80 --dry-run=client -o yaml > service.yaml

Enter fullscreen mode

Exit fullscreen mode

  1. Create a chart:

helm create webapp

Enter fullscreen mode

Exit fullscreen mode

  1. Move manifests: replace defaults with your generated files under templates/.
  2. Add schema validation: Create values.schema.json to validate image & replica fields.
  3. Extract helpers: Move naming logic to _helpers.tpl.
  4. Test locally:

helm template webapp . helm lint webapp helm install webapp . --dry-run

Enter fullscreen mode

Exit fullscreen mode

Result: a reusable, validated chart with clear structure.

5) Cheatsheet

Command

Purpose

helm show values <chart>

Display default values

helm lint .

Validate chart + schema

helm template .

Render YAML locally

helm upgrade --install <release> . -f values/prod.yaml

Idempotent deploy

Schema tip:

Run jq . values.schema.json to quickly validate structure

6) Pitfalls

Pitfall

Why It Hurts

Fix

Values drift

Each team edits values.yaml differently.

Enforce schema + overlays.

Over-templating

Logic explodes inside YAML.

Keep logic minimal; pre-compute in CI/CD.

No library reuse

Duplication everywhere.

Move shared blocks to _helpers.tpl or library charts.

Missing schema

Silent deployment errors.

Add values.schema.json early.

7) Wrap-up — Next: Shipping Charts with Confidence: Lint, Tests, Diff, OCI & Provenance (Post 7)

We now have clean, validated, reusable Helm charts that can be tested in isolation.
Next, in Post 7, we’ll cover how to ship charts with confidence: Lint, Tests, Diff, OCI & Provenance.

Helm is powerful when it’s predictable.
Do it right once, and every future deployment becomes safer, faster, and auditable. Thanks for sticking around till the end, drop your comments and feedback below.

For further actions, you may consider blocking this person and/or reporting abuse

Залишити відповідь

Ваша e-mail адреса не оприлюднюватиметься. Обов’язкові поля позначені *

Читайте також