2. Шаблоны Helm (Templates)
Шаблоны — ядро Helm: это Go templates (плюс библиотека Sprig), которые превращают values.yaml в готовые манифесты Kubernetes. Без уверенного владения {{ .Values }}, if / range, default / required, toYaml + nindent сложно дойти до уровня Middle+. Ниже — синтаксис, функции, пайплайны и минимальный кастомный chart (Deployment, Service, опционально Ingress).
Контекст и .Values
В шаблоне доступны встроенные объекты:
| Объект | Содержимое |
|---|---|
.Values |
Содержимое values.yaml + переопределения -f / --set |
.Release |
Name, Namespace, Service и др. |
.Chart |
Поля из Chart.yaml (Name, Version, AppVersion, …) |
.Capabilities |
Версия API Kubernetes и т.д. |
replicas: {{ .Values.replicaCount }}
Условия и циклы
{{- if .Values.ingress.enabled }}
# манифест Ingress
{{- end }}
{{- range .Values.extraEnv }}
- name: {{ .name }}
value: {{ .value | quote }}
{{- end }}
Комментарий: {{- и -}} убирают лишние переносы строк в выводе — иначе YAML часто «разъезжается» или появляются пустые строки.
Функции: default, required
default — запасное значение, если вход пустой или «zero value»:
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
required — если значение не задано, helm template / install упадёт с понятной ошибкой (лучше, чем «пустой образ» в prod):
repository: {{ required "Задайте .Values.image.repository" .Values.image.repository | quote }}
toYaml, indent, nindent
Встраивание фрагментов YAML из values (ресурсы, nodeSelector, tolerations):
resources:
{{- toYaml .Values.resources | nindent 12 }}
nindent N— вставить перенос + N пробелов у каждой строки (типично дляcontainers:под 12 spaces).indent— без начального переноса; чаще удобнееnindent.
Пайплайны (|)
Значение передаётся в функцию справа налево по цепочке:
{{ .Values.name | upper | quote }}
{{ .Values.podAnnotations | toYaml | nindent 8 }}
Практика: фрагменты чарта
Ниже — учебный минимум. Имена могут совпадать с тем, что даёт helm create; при желании замените my-release на {{ .Release.Name }} и вынесите общие лейблы в _helpers.tpl.
values.yaml
replicaCount: 2
image:
repository: ghcr.io/myorg/my-app
tag: ""
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 500m
memory: 512Mi
service:
type: ClusterIP
port: 8080
ingress:
enabled: false
className: nginx
host: my-app.example.com
В корне чарта нужен Chart.yaml с полем appVersion, иначе подстановка default .Chart.AppVersion для тега образа не сработает осмысленно.
templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ .Release.Name }}
labels:
app.kubernetes.io/name: {{ .Chart.Name }}
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
app.kubernetes.io/name: {{ .Chart.Name }}
template:
metadata:
labels:
app.kubernetes.io/name: {{ .Chart.Name }}
spec:
containers:
- name: app
image: "{{ required "image.repository обязателен" .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
ports:
- containerPort: {{ .Values.service.port }}
resources:
{{- toYaml .Values.resources | nindent 12 }}
templates/service.yaml
apiVersion: v1
kind: Service
metadata:
name: {{ .Release.Name }}
spec:
type: {{ .Values.service.type }}
selector:
app.kubernetes.io/name: {{ .Chart.Name }}
ports:
- port: {{ .Values.service.port }}
targetPort: {{ .Values.service.port }}
protocol: TCP
name: http
templates/ingress.yaml (опционально)
{{- if .Values.ingress.enabled -}}
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: {{ .Release.Name }}
spec:
ingressClassName: {{ .Values.ingress.className }}
rules:
- host: {{ .Values.ingress.host | quote }}
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: {{ .Release.Name }}
port:
number: {{ .Values.service.port }}
{{- end }}
Проверка рендера:
helm template test-release . -f values.yaml --debug
Production best practices
| Практика | Зачем |
|---|---|
required для обязательных полей |
Ранний отказ в CI, а не «молча» сломанный деплой |
Единые лейблы app.kubernetes.io/* |
Селекторы, логи, HPA, стандарты команды |
| Ресурсы requests/limits из values | Разные профили по средам |
| Не генерировать пустые блоки | Всегда if вокруг optional Ingress/PVC |
| Ревью шаблонов как кода | Сложные range легко ломают отступы YAML |