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:
- Ищи объявление
{{- define "имя" -}}в_helpers.tplили других файлах с расширением.tpl. - Смотри, какая логика там зашита — часто там есть ветвления, преобразования строк, работа с контекстом.
- Передаётся ли контекст (точка) правильно?
{{ include "name" . }}— с точкой, если нужен доступ к.Values. - Используется ли этот хелпер в нескольких местах? Если да — значит, это точка централизации логики.
Итог: {{ }} — это прямое обращение к данным. include — это вызов функции шаблонизации, которая может содержать сложную логику и переиспользоваться. Выбор зависит не от “что короче”, а от “где эта логика будет меняться и сколько раз используется”. Один раз — можно и прямо. Два и больше — скорее всего, в _helpers.tpl.