Встроенные объекты: Release, Chart, Values, Capabilities
Helm передаёт в каждый шаблон набор готовых объектов — разбираем, что в них и зачем.
Встроенные объекты — это данные, которые Helm кладёт в корневой контекст шаблона: информация о релизе, чарте, значениях и возможностях кластера. Доступ через ведущую точку:
.Release.Name,.Chart.Versionи т.д.
Откуда вообще берутся эти объекты и почему их не нужно объявлять? Перед тем как рендерить шаблоны, Helm формирует словарь с заранее известными ключами и передаёт его движку как корневой контекст. Часть данных он берёт из ваших файлов (.Values, .Chart), часть — из контекста самой операции (.Release), часть — спрашивает у кластера (.Capabilities). Для автора шаблона это выглядит так, будто данные «уже есть» — их остаётся только прочитать. Понимать происхождение полезно: оно объясняет, почему одни объекты доступны всегда, а другие (например, реальная версия кластера) — только при работе с живым кластером.
Объекты удобно делить на две группы по тому, кто их заполняет. .Values — единственный, чьё содержимое определяете вы: это ваши настройки. Остальные (.Release, .Chart, .Capabilities, .Files, .Template) заполняет сам Helm, и вы их только читаете. Это разделение объясняет и соглашение об именах: встроенные объекты всегда с заглавной буквы, чтобы их нельзя было спутать с вашими ключами внутри .Values, которые вы вольны называть как угодно.
.Release — данные текущей установки
| Поле | Значение |
.Release.Name | имя релиза (что вы дали в install) |
.Release.Namespace | namespace установки |
.Release.Revision | номер ревизии (1, 2, ...) |
.Release.IsInstall / .IsUpgrade | true на install / на upgrade |
.Release.Name — самый используемый объект: им префиксуют имена ресурсов, чтобы два релиза одного чарта не конфликтовали.
metadata:
name: {{ .Release.Name }}-config
namespace: {{ .Release.Namespace }}
.Chart — поля Chart.yaml
Зеркало Chart.yaml: .Chart.Name, .Chart.Version, .Chart.AppVersion. Удобно для лейблов, чтобы по объекту в кластере было видно, каким чартом и какой версией он создан.
Зачем тащить версию чарта в лейблы каждого ресурса? Чтобы кластер был самодокументируемым. Через полгода кто-то найдёт в namespace непонятный Deployment, посмотрит его лейблы — и сразу увидит helm.sh/chart: webapp-1.2.0, то есть «это поставил чарт webapp версии 1.2.0». Без таких меток связь между объектом в кластере и его источником теряется, и разбираться приходится археологией. Поэтому стандартный набор лейблов app.kubernetes.io/* в сгенерированных Helm чартах — не украшение, а инструмент эксплуатации: по ним фильтруют, группируют и отслеживают ресурсы.
Обратите внимание на разделение ролей версий и здесь: в лейбл version кладут .Chart.AppVersion (версию приложения — что важно для дежурного инженера), а в helm.sh/chart — .Chart.Version (версию упаковки — что важно для того, кто катит обновления). Это прямое продолжение различия из урока про Chart.yaml, доведённое до видимых меток в кластере.
labels:
app.kubernetes.io/name: {{ .Chart.Name }}
app.kubernetes.io/version: {{ .Chart.AppVersion }}
helm.sh/chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
.Values — ваши значения
Уже знакомый объект: слитый результат values.yaml + переопределений. Это единственный объект, содержимое которого определяете вы.
.Capabilities — что умеет кластер
Позволяет писать чарты, адаптирующиеся к версии Kubernetes и доступным API. Например, выбрать правильный apiVersion для Ingress в зависимости от версии кластера:
{{- if .Capabilities.APIVersions.Has "networking.k8s.io/v1" }}
apiVersion: networking.k8s.io/v1
{{- else }}
apiVersion: networking.k8s.io/v1beta1
{{- end }}
.Capabilities.KubeVersion.Minor даёт минорную версию кластера. Это делает чарт переносимым между кластерами разных версий.
Почему это вообще проблема, которую нужно решать? Kubernetes активно меняет свои API между версиями: ресурс, живший под networking.k8s.io/v1beta1, в новых версиях переехал на v1, а в самых старых его не было вовсе. Захардкодьте один apiVersion — и чарт, отлично работающий на свежем кластере, упадёт на старом (или наоборот). .Capabilities разрывает эту жёсткую привязку: чарт спрашивает у кластера «а есть ли у тебя такой API?» и сам выбирает подходящий вариант. Так один и тот же чарт переживает обновления Kubernetes и работает в разнородном парке кластеров без форков под каждую версию.
Важная оговорка про честность данных. .Capabilities правдив ровно настолько, насколько Helm видит кластер. При реальной установке он опрашивает живой API и отвечает точно. А вот при helm template без подключения к кластеру Helm подставляет стабы — заглушки с дефолтной версией, которая может не совпасть с боевой. Если логика чарта завязана на версию, при локальном рендере честнее задавать её явно через --kube-version, иначе можно отлаживать ветку if, которая на проде никогда не выполнится.
.Files — доступ к файлам чарта
Позволяет вшить в манифест содержимое файла из чарта (например, конфиг приложения) в ConfigMap:
data:
app.conf: |-
{{ .Files.Get "configs/app.conf" | indent 4 }}
Есть и .Files.Glob для набора файлов по маске. Важное ограничение: нельзя читать файлы из templates/ и из родительского чарта — только из своего.
.Template — о текущем шаблоне
.Template.Name и .Template.BasePath — путь текущего рендерящегося шаблона; используется редко, в основном в сложных хелперах.
Как объекты попадают в контекст под капотом
Перед рендером Helm собирает корневой объект-словарь и кладёт в него эти поля. .Release и .Capabilities формируются из текущей операции и опроса кластера (или из стабов при helm template без кластера). .Chart читается из Chart.yaml, .Values — из слияния. Все имена объектов начинаются с заглавной буквы — это соглашение Helm, отличающее встроенные объекты от ваших ключей в .Values (которые вы пишете как угодно). Внутри range/with корневой контекст подменяется, и чтобы достать встроенные объекты, используют $ — ссылку на исходный корень.
Частые ошибки
- Потерять доступ к
.Releaseвнутриrange. Точка там — элемент цикла; пишите$.Release.Name. - Полагаться на
.Capabilitiesприhelm templateбез кластера. Там подставляются стабы, реальная версия может отличаться; используйте--kube-version. - Читать
.Filesизtemplates/. Запрещено; кладите вспомогательные файлы внеtemplates/.
Итог
.Release— имя/namespace/ревизия установки;.Chart— поля Chart.yaml;.Values— ваши значения..Capabilitiesделает чарт переносимым между версиями кластера;.Filesвшивает файлы чарта.- Встроенные объекты пишутся с заглавной; внутри циклов корень доступен через
$.