Command Palette

Search for a command to run...

Hectal
PHASE 7Intermediate ~14 min· topic 2 of 4

Topic 7.2

Writing Your Own Chart

In one line

helm create scaffolds a working starter chart — turning your own Deployment, Service, and ConfigMap from earlier phases into genuinely reusable, parameterized templates is most of the real skill.

0/4 · 0%

Key ideas

  1. 01

    helm create <name> scaffolds a complete, working starter chart with sensible example templates already in place — genuinely the standard way to begin a new chart, since starting from a proven structure is faster and less error-prone than building the directory layout from scratch.

  2. 02

    Converting an existing plain manifest (like Phase 1.1's Deployment) into a chart template means identifying which specific VALUES should actually be configurable — the image tag, the replica count, resource requests/limits — and replacing those specific fields with {{ .Values.xxx }} references, while leaving everything that's genuinely fixed and identical across every environment as plain, literal YAML.

  3. 03

    {{ .Release.Name }} is a BUILT-IN template variable (not from your own values.yaml) referring to the release name given at install time — genuinely useful for naming resources uniquely per release ({{ .Release.Name }}-deployment), letting the SAME chart be installed multiple times in the same cluster under different release names without any naming collision.

  4. 04

    Helm templates support genuine LOGIC, not just simple substitution — {{ if .Values.ingress.enabled }} conditionally includes an entire block (or an entire separate template file) only if a value is set a certain way, and {{ range .Values.items }} loops over a list, generating repeated YAML for each entry — genuinely powerful once a chart needs to support meaningfully different configurations, not just different values for the same fixed structure.

  5. 05

    helm lint <chart> checks a chart for common mistakes and best-practice violations BEFORE you ever try installing it — genuinely worth running routinely while developing a chart, catching issues like missing required fields or malformed templates early, the same 'catch it before it costs you' philosophy CI (Git's own course, Phase 7.3) is built around.

  6. 06

    A well-written chart should have SENSIBLE DEFAULTS in values.yaml — a chart that requires every single value to be explicitly overridden just to install successfully at all defeats much of the point; the goal is a chart that installs and runs correctly with ZERO overrides for a reasonable default case, while still allowing genuine customization when actually needed.

Code & diagrams

templated-deployment.yamlmarkdown

The same Deployment from Phase 1.1, now genuinely parameterized with logic and built-in variables.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ .Release.Name }}-my-app
spec:
  replicas: {{ .Values.replicaCount }}
  selector:
    matchLabels:
      app: {{ .Release.Name }}-my-app
  template:
    metadata:
      labels:
        app: {{ .Release.Name }}-my-app
    spec:
      containers:
        - name: my-app
          image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
          resources:
            requests:
              cpu: {{ .Values.resources.requests.cpu }}
              memory: {{ .Values.resources.requests.memory }}
          {{- if .Values.healthCheck.enabled }}
          readinessProbe:
            httpGet:
              path: {{ .Values.healthCheck.path }}
              port: {{ .Values.service.port }}
          {{- end }}
values.yamlmarkdown

Sensible defaults — this chart installs correctly with ZERO overrides.

replicaCount: 2

image:
  repository: my-registry/my-app
  tag: "1.5.0"

resources:
  requests:
    cpu: "250m"
    memory: "256Mi"

service:
  port: 8080

healthCheck:
  enabled: true
  path: /health
writing-a-chart.shmarkdown

Scaffold, lint, and install your own chart — starting from a proven baseline structure.

# Scaffold a new starter chart
helm create my-app-chart

# Check it for common mistakes before ever installing it
helm lint ./my-app-chart

# Preview it, confirming logic (like the conditional readinessProbe) renders correctly
helm template test-release ./my-app-chart

# Try it with healthCheck disabled — confirm the readinessProbe block disappears entirely
helm template test-release ./my-app-chart --set healthCheck.enabled=false

# Install two SEPARATE releases of the SAME chart, in the same cluster —
# {{ .Release.Name }} prevents any naming collision between them
helm install release-a ./my-app-chart
helm install release-b ./my-app-chart
kubectl get deployments
# release-a-my-app and release-b-my-app — both exist independently

Explain it without notes

01

Why does {{ .Release.Name }} matter for letting the same chart be installed multiple times in one cluster without conflict?

02

Why is having sensible defaults in values.yaml considered a genuinely important part of writing a good chart, not just a nice-to-have?

Practice

01

Scaffold a new chart with helm create, then modify its default Deployment template to use at least one conditional block ({{ if }}) controlling whether a specific field appears at all.

02

Run helm lint against your own chart and fix any warnings it surfaces before considering the chart genuinely done.

Trade-offs

  • ↔

    Writing a genuinely well-parameterized, reusable chart takes real, deliberate upfront thought about WHICH values should be configurable (and with what sensible defaults) — over-parameterizing everything imaginable produces a chart that's genuinely harder to understand and use than one that's parameterized specifically for the handful of things that actually vary in practice; a chart trying to be infinitely flexible often ends up being flexible in ways nobody actually needs, at a real cost to clarity.

Done when you can

  • I can convert a plain Kubernetes manifest into a genuinely parameterized Helm template.

  • I understand built-in variables like {{ .Release.Name }} and can use conditional/loop logic in a template.

  • I know to run helm lint routinely while developing a chart, and to provide sensible defaults in values.yaml.