Errors
Kubernetes

Kubernetes: What is the usage of include in helm

Ты сидишь перед `templates/deployment.yaml`, пишешь `{{ .Values.name }}` и думаешь — зачем эти сложности с `include`, если есть прямые подстановки. Потом открыв

Ты сидишь перед templates/deployment.yaml, пишешь {{ .Values.name }} и думаешь — зачем эти сложности с include, если есть прямые подстановки. Потом открываешь чарт коллеги и видишь {{ include "mychart.fullname" . }}. Начинаешь гуглить, читаешь документацию, а понимание всё не приходит. Что это — магия, лишняя сложность или всё-таки есть причина?

Разберёмся. Прямая подстановка {{ .Values.nameOverride }} — это просто вставка значения. Работает, если нужно вставить одно значение в одно место. Но что если это “имя” должно быть одинаковым в десяти разных местах: в метках, селекторах, именах ресурсов? А потом приходит требование добавить префикс окружения. Придётся бегать по всем файлам и менять логику в каждом.

Вот здесь и выходит на сцену include. Это не просто подстановка, а вызов другого шаблона. В templates/_helpers.tpl живут эти самые шаблоны-помощники.

# _helpers.tpl
{{- define "cluster-dev.fullname" -}}
{{- if .Values.nameOverride -}}
{{- .Values.nameOverride | trunc 63 | trimSuffix "-" -}}
{{- else -}}
{{- printf "%s-%s" .Release.Name .Chart.Name | trunc 63 | trimSuffix "-" -}}
{{- end -}}
{{- end -}}

И потом в деплойменте:

metadata:
  name: {{ include "cluster-dev.fullname" . }}

Ключевое отличие — точка . в конце. Это текущий контекст (scope), который передаётся в вызываемый шаблон. Без неи include не увидит Values, Release или Chart. Простые {{ }} контекст не передают — они его используют на своём уровне.

Зачем это нужно? Для консистентности и сложной логики. Хелпер fullname может содержать не только nameOverride, но и проверки, усечение длины, добавление суффиксов. Если эта логика поменяется, правка в одном месте _helpers.tpl обновит все имена во всём чарте.

Можно ли использовать {{ .Values.nameOverride }} напрямую? Да, если это значение нужно только один раз и никакой дополнительной обработки не требуется. Но как только логика усложняется или повторяется — выносите в define и используйте include.

Порядок мыслей при встрече с include:

  1. Ищи объявление {{- define "имя" -}} в _helpers.tpl или других файлах с расширением .tpl.
  2. Смотри, какая логика там зашита — часто там есть ветвления, преобразования строк, работа с контекстом.
  3. Передаётся ли контекст (точка) правильно? {{ include "name" . }} — с точкой, если нужен доступ к .Values.
  4. Используется ли этот хелпер в нескольких местах? Если да — значит, это точка централизации логики.

Итог: {{ }} — это прямое обращение к данным. include — это вызов функции шаблонизации, которая может содержать сложную логику и переиспользоваться. Выбор зависит не от “что короче”, а от “где эта логика будет меняться и сколько раз используется”. Один раз — можно и прямо. Два и больше — скорее всего, в _helpers.tpl.