Функции и конвейеры: default, quote, toYaml
Голой подстановки мало: значения нужно приводить к нужному виду. Знакомимся с функциями и конвейером.
Конвейер (pipe, символ
|) передаёт результат слева как последний аргумент функции справа — как пайп в shell.{{ .Values.name | upper | quote }}читается слева направо.
Go templates вместе со Sprig (библиотека функций, встроенная в Helm) дают сотни функций. Разберём самые востребованные.
Почему вообще нельзя обойтись голой подстановкой {{ .Values.x }}? Потому что значение из values.yaml почти никогда не ложится в манифест «как есть». Его нужно то обрезать до допустимой длины, то обернуть в кавычки, то снабдить запасным вариантом, то развернуть из вложенной карты в плоский YAML-блок. Каждая из этих задач — отдельная функция, а конвейер позволяет выстроить их в читаемую цепочку. По сути шаблонизатор Helm — это маленький язык преобразования данных, где values на входе, готовый текст манифеста на выходе, а функции и pipeline — инструменты трансформации между ними.
Важно понимать происхождение функций. Часть из них (if, range, index, printf) — родные для Go templates. Подавляющее же большинство, включая default, quote, toYaml, trunc, upper, приходит из библиотеки Sprig, которую Helm подключает. Знать это полезно: когда ищете документацию по конкретной функции, гуглить надо «Sprig функция X», а не «Helm функция X» — так быстрее находится точное описание сигнатуры и поведения на краевых случаях.
default — значение на случай пустоты
Если параметр не задан, подставит запасной:
replicas: {{ .Values.replicaCount | default 1 }}
tag: {{ .Values.image.tag | default .Chart.AppVersion }}
Второй пример — частый паттерн: если тег образа не указан, взять версию приложения из Chart.yaml. Это избавляет от обязательности параметра.
У default есть тонкость, о которую спотыкаются: «пустотой» она считает не только отсутствие ключа, но и любое «ложное» значение — 0, false, пустую строку. Если пользователь осознанно задал replicaCount: 0 (например, чтобы временно остановить деплоймент), то default 1 молча вернёт единицу и перезапустит поды — а это уже не то, что человек хотел. Поэтому для числовых и булевых параметров, где ноль и false — легитимные значения, default опасна, и лучше проверять наличие ключа явно через hasKey или конструкцию if. Для строк и тегов образа, где пустота и «не задано» эквивалентны, default работает идеально.
quote — обернуть в кавычки
YAML коварен: значения true, 123, 1.0, yes трактуются как булев/число, а не строка. Если нужна именно строка — оборачивайте:
image:
tag: {{ .Values.image.tag | quote }} # "1.25" а не 1.25
env:
- name: DEBUG
value: {{ .Values.debug | quote }} # "true" а не булев
Переменные окружения в Kubernetes обязаны быть строками — quote здесь спасает от ошибки валидации.
toYaml — вставить целый блок значений
Самая мощная функция для сложных структур. Превращает кусок values (карту/список) обратно в YAML-текст, чтобы вставить его в манифест целиком:
resources:
{{ toYaml .Values.resources | indent 2 }}
При .Values.resources с requests/limits весь блок подставится с правильной структурой. Это избавляет от перечисления каждого поля вручную и делает чарт гибким: пользователь задаёт любую структуру resources, а чарт её прозрачно вставляет.
Сила toYaml в том, что она делает чарт «прозрачным» для целых поддеревьев конфигурации. Вместо того чтобы автор чарта заранее перечислял все возможные поля (а в случае resources, nodeSelector, tolerations, affinity их десятки, и они эволюционируют от версии к версии Kubernetes), он просто пробрасывает кусок values как есть. Пользователь получает полную мощь Kubernetes API, не дожидаясь, пока автор чарта добавит поддержку нужного поля. Это ключевой приём библиотечных чартов вроде bitnami: почти любой сложный объект там вставляется через toYaml, а в values.yaml оставлен пустой плейсхолдер с комментарием-примером.
Есть и обратная функция — fromYaml, которая разбирает YAML-строку обратно в структуру. На практике она нужна реже, но незаменима, когда значение пришло строкой (например, из .Files.Get при чтении вшитого в чарт файла), а вам нужно обращаться к его полям. Пара toYaml/fromYaml — это, по сути, сериализация и десериализация внутри шаблона.
Строковые и числовые функции
{{ .Values.name | upper }} # В ВЕРХНИЙ
{{ .Values.name | lower | trunc 63 }} # нижний, обрезать до 63
{{ .Values.name | trimSuffix "-" }} # убрать хвостовой дефис
{{ add .Values.a .Values.b }} # сложение
{{ .Values.list | join "," }} # элементы через запятую
trunc 63 + trimSuffix "-" — классическая пара: имена в Kubernetes ограничены 63 символами, а обрезка не должна оставить дефис на конце.
Скобки для группировки
Чтобы вызвать функцию от результата другой, используют круглые скобки:
value: {{ quote (printf "%s-%s" .Release.Name .Chart.Name) }}
Скобки и конвейер решают одну задачу — вложить вызовы функций — но с разных сторон. Конвейер хорош, когда данные текут одной линейной цепочкой: «взять значение, обрезать, обернуть». Скобки нужны, когда аргумент функции — сам результат другого вызова, причём не последний, а, скажем, первый или средний. В примере выше printf собирает строку из двух частей, и только её целиком мы передаём в quote. Эти два механизма свободно комбинируются: {{ printf "%s-%s" .Release.Name (.Values.suffix | default "app") | quote }} — здесь внутри есть и скобки с конвейером, и внешний конвейер. Читать такие выражения проще, разбирая их изнутри наружу, как в математике.
Как работает конвейер под капотом
Конвейер — синтаксический сахар. {{ .Values.x | default "a" | quote }} движок превращает в quote (default "a" .Values.x): результат каждого этапа становится последним позиционным аргументом следующей функции. Понимание этого снимает путаницу с порядком аргументов: default объявлена как default ЗАПАСНОЕ ЗНАЧЕНИЕ, и при записи через pipe «значение» приходит из конвейера последним, поэтому запасное пишется первым. Sprig-функции спроектированы так, чтобы «обрабатываемые данные» шли последним аргументом — именно ради удобства конвейеров.
Частые ошибки
- Перепутать порядок аргументов
default. Запасное значение — первый аргумент:default 1 .Values.x, а в pipe —.Values.x | default 1. toYamlбезindent/nindent. Вставленный блок поедет по отступам — будет невалидный YAML.- Не обернуть строковое значение в
quote.tag: 1.10станет числом1.1— образ не найдётся.
Итог
- Конвейер
|передаёт значение последним аргументом следующей функции — отсюда порядок аргументов Sprig. defaultзадаёт запасное значение,quoteзащищает строки,toYamlвставляет целые блоки values.trunc 63 | trimSuffix "-"— стандарт для безопасных имён Kubernetes.