Lesson 5 · This repo's library-chart architecture
Named templates & helpers
Reusable template blocks — define + include — and the fullname/labels pattern that glues objects together.
Your win: explain what a named template is, how define/include
work, and the fullname/labels helper pattern — the foundation of the util.*
library you'll dissect next lesson.
Named templates = functions for YAML
A named template (a "partial") is a reusable block created with
{{ define "name" }}…{{ end }} and invoked with
include.1 Think of it as a function:
define once, call from many manifests. By convention they live in leading-underscore files
(so they don't render as manifests) and are prefixed with a namespace to
avoid clashes — here, everything is util.*.
# define once (in a _*.tpl file) {{- define "util.labels" -}} app.kubernetes.io/name: {{ include "util.name" . }} app.kubernetes.io/managed-by: {{ .Release.Service }} {{- end }} # call from any manifest, indented into place metadata: labels: {{- include "util.labels" . | nindent 4 }}
Recall Lesson 3: use include (not template) so the output can be
piped to nindent. The . passed as the second argument is the
context the template renders against — get that wrong and
.Values is empty inside the partial.
The fullname / labels pattern
Two helpers appear in nearly every real chart, because they solve a concrete problem — keeping an object's name and labels consistent so a Deployment, its Pods, and its Service selector all agree (Course 2 L4–5):2
- fullname — the canonical object name (chart/release-derived, truncated to 63 chars for the K8s label limit).
- labels / selectorLabels — the standard
app.kubernetes.io/*labels; selectorLabels is the stable subset a Service/ReplicaSet matches on.
_helpers.tpl)
Instead of one _helpers.tpl, this repo splits partials by concern, all
util.*:
util.namelibs/util/templates/_name.tpl:5,util.fullname_name.tpl:14,util.chart_name.tpl:25.util.labelslibs/util/templates/_label.tpl:5,util.selectorLabels_label.tpl:15, plus parameterizedutil.labels.v2/util.selectorLabels.v2(_label.tpl:28,59) that add anapp.kubernetes.io/componentfor the consumer/on-demand variants.util.environment/util.vendor_env.tpl:6,37 (Lesson 4).
trunc 63 | trimSuffix "-" so a long release/chart name
can't produce an invalid object. It's a small detail interviewers love, and forgetting it is
a real production bug.
Helm docs — Named Templates + Best Practices (labels)
define/include/template, the naming convention, and
the standard labels/fullname pattern.
→ helm.sh — Named Templates
→ helm.sh — Best Practices: Labels
Check yourself (from memory)
Q1. A named template is created and used with…
{{ define "name" }}…{{ end }} creates it;
include "name" . renders it (pipeable, unlike template).
Q2. The second argument in include "util.labels" . is…
. so .Values/.Release
resolve inside the partial; wrong context = empty values.
Q3. The fullname helper truncates to 63 chars because…
trunc 63 | trimSuffix "-" to stay valid.
{{ define "name"
}}…{{ end }}, invoked with include "name" . (pipeable; prefer over
template). Convention: leading-underscore file (no manifest) + namespace prefix
to avoid clashes. Pass . = the CONTEXT (so .Values/.Release
resolve). FULLNAME/LABELS PATTERN: fullname = canonical object name
(trunc 63 | trimSuffix "-" for K8s's 63-char cap); labels = standard
app.kubernetes.io/*; selectorLabels = the stable subset a
Service/ReplicaSet matches → keeps Deployment/Pods/Service in sync. REPO: no
_helpers.tpl; split into util.name/fullname (_name.tpl),
util.labels/selectorLabels (_label.tpl), util.environment/vendor
(_env.tpl).util.fullname body, or see how
util.labels.v2 adds a component for the -consumers workload?
Ask me.