Chart.yaml и values.yaml подробно

Два файла-контракта чарта: метаданные пакета и его «настройки по умолчанию».

values.yaml — это публичный API чарта. Всё, что пользователь может настроить, должно иметь параметр здесь, с разумным дефолтом и понятным именем.

Эти два файла стоит держать в голове как пару с разными ролями. Chart.yaml отвечает на вопрос «что это за пакет и с чем он совместим» — его читают Helm и системы доставки, чтобы понять версию, зависимости и требования к окружению. values.yaml отвечает на вопрос «как это настроить» — его читает человек, который чарт устанавливает. Первый файл про идентичность пакета, второй — про его поведение. Перепутать их роли сложно, но важно понимать: правка Chart.yaml почти всегда означает выпуск новой версии чарта, тогда как values.yaml переопределяют на каждой установке, не трогая сам чарт.

Chart.yaml: полный набор полей

apiVersion: v2
name: webapp
description: Веб-приложение с API и фронтендом
type: application          # application | library
version: 1.2.0             # SemVer версии чарта
appVersion: "2.4.1"        # версия приложения (строка)
kubeVersion: ">=1.24.0"   # требование к версии кластера
keywords:
  - web
  - api
home: https://example.com
maintainers:
  - name: Platform Team
    email: [email protected]
dependencies:
  - name: postgresql
    version: "13.x.x"
    repository: https://charts.bitnami.com/bitnami
    condition: postgresql.enabled

Разберём неочевидное:

ПолеНазначение
typeapplication — обычный чарт; library — чарт-библиотека только с шаблонами, без своих ресурсов
kubeVersionограничение версии кластера; Helm откажет в установке на несовместимый
dependenciesсписок subchart-ов с версией, источником и условием подключения

SemVer и ограничения версий

В зависимостях используется синтаксис ограничений: "13.x.x" — любая минорная/патч в пределах мажора 13; "~13.2.0" — патчи 13.2.*; "^13.2.0" — совместимые в пределах мажора 13. Фиксированная "13.2.24" — самая предсказуемая для прода.

За удобством плавающих диапазонов прячется ловушка воспроизводимости. Запись "13.x.x" кажется заботливой — «бери любые свежие патчи безопасности», — но она же означает, что сборка чарта сегодня и через месяц может подтянуть разные версии subchart-а, и поведение прода тихо изменится без единой правки с вашей стороны. Поэтому ровно для этого Helm заводит файл Chart.lock: при helm dependency update он фиксирует точные версии, которые реально скачались, и в дальнейшем тянет именно их. Связка «диапазон в Chart.yaml + точные версии в Chart.lock» — это тот же приём, что package.json и package-lock.json в npm. Lock-файл коммитят в репозиторий, иначе теряется весь смысл фиксации.

Поле condition у зависимости заслуживает отдельного слова. Оно указывает на булев параметр в values (postgresql.enabled), и subchart разворачивается, только если этот флаг истинен. Так один чарт умеет работать в двух режимах: «всё в комплекте» (своя встроенная база данных для теста) и «база снаружи» (на проде подключаемся к управляемому PostgreSQL, а встроенный отключаем флагом). Без condition зависимость ставилась бы всегда, что для прод-сценария обычно нежелательно.

values.yaml как контракт

Хороший values.yaml структурирован, прокомментирован и сгруппирован по смыслу. Сравните плоский и структурированный подходы:

# ПЛОХО: плоско, неясно, что к чему относится
img: nginx
imgTag: "1.25"
port: 80
cpu: 250m

# ХОРОШО: сгруппировано, читается как документация
image:
  repository: nginx
  tag: "1.25.3"
  pullPolicy: IfNotPresent

service:
  type: ClusterIP
  port: 80

resources:
  requests:
    cpu: 250m
    memory: 256Mi
  limits:
    cpu: "1"
    memory: 512Mi

Дефолты должны быть безопасными

Дефолтные значения — это то, что получит пользователь, ничего не настроивший. Правило: дефолт безопасен для запуска, но скромен по ресурсам. Например, replicaCount: 1, скромные лимиты, выключенный по умолчанию ingress. Опасные вещи (внешний доступ, удаление данных) держите выключенными по умолчанию.

За этим правилом стоит простая логика рисков. Дефолт срабатывает именно тогда, когда человек не задумался о параметре — а значит, цена ошибки в дефолте ложится на самого неопытного пользователя. Если выставить ingress включённым по умолчанию, кто-то развернёт чарт «на попробовать» и нечаянно выставит сервис в интернет. Если выставить большие лимиты ресурсов — установка упадёт на маленьком кластере с непонятной ошибкой нехватки ресурсов. Поэтому безопасный дефолт — это не перестраховка, а уважение к тому, кто видит ваш чарт впервые. Включение «взрослых» возможностей оставляйте осознанным действием: пользователь сам пишет ingress.enabled: true, когда понимает, что делает.

Отдельно про принцип наименьшего удивления применительно к именам. Если в экосистеме сложились устоявшиеся ключи — image.repository, image.tag, resources.requests, nodeSelector, — повторяйте их один в один, даже если своё название кажется красивее. Люди, ставившие десятки чартов, ожидают именно эти имена, и совпадение делает ваш чарт предсказуемым без чтения документации. Оригинальность в именовании values — почти всегда вредная.

Как работает слияние values под капотом

Итоговые значения — это результат глубокого слияния (deep merge) нескольких слоёв: дефолты из values.yaml чарта → значения родителя для subchart → файлы -f в порядке указания → флаги --set. Слияние идёт по ключам: вложенные карты сливаются рекурсивно, а вот списки заменяются целиком, а не объединяются. Это частый сюрприз: переопределив один элемент массива через --set, вы замещаете весь массив. Поэтому массивы в values планируйте так, чтобы их заменяли целиком, а не «дополняли».

Документация значений: values.schema.json

У values.yaml есть слабое место: он задаёт дефолты, но никак не описывает правила. Пользователь может прислать строку вместо числа, забыть обязательное поле или сделать опечатку в имени ключа — и Helm молча соберёт кривой манифест, который упадёт уже в кластере с невнятной ошибкой. Чтобы ловить такое раньше и понятнее, к чарту прикладывают values.schema.json — формальное описание того, какими должны быть values.

Можно приложить JSON Schema, и Helm будет валидировать переданные values перед установкой — отвергнет опечатки и неверные типы:

{
  "$schema": "https://json-schema.org/draft-07/schema#",
  "type": "object",
  "required": ["image"],
  "properties": {
    "replicaCount": { "type": "integer", "minimum": 1 },
    "image": {
      "type": "object",
      "required": ["repository"],
      "properties": {
        "repository": { "type": "string" }
      }
    }
  }
}

Выгода схемы — в смещении ошибки «влево», ближе к моменту, когда её дёшево исправить. Без схемы неверный тип всплывёт где-то в недрах рендера или вовсе в кластере; со схемой Helm откажет в установке сразу и укажет конкретное поле. Особенно это ценно в командных и публичных чартах, где values задаёт человек, не читавший исходники: схема становится исполняемой документацией, которая не устаревает, потому что её проверяет сам Helm. Для маленького личного чарта схема избыточна, но как только чарт начинают использовать другие — это первое, что стоит добавить к контракту.

Частые ошибки

  • Плоский values.yaml без структуры — становится нечитаемым уже на 20 параметрах.
  • Опасные дефолты (включённый ingress, большие лимиты) — пользователь получает сюрприз «из коробки».
  • Надежда, что массив в values «дополнится». При слиянии списки заменяются целиком.

Итог

  • Chart.yaml описывает пакет: версии, тип, зависимости, требования к кластеру.
  • values.yaml — публичный API чарта; группируйте, комментируйте, делайте дефолты безопасными.
  • Слияние values — глубокое для карт, но списки замещаются целиком; values.schema.json валидирует ввод.
Проверьте себя
1. Что означает type: library в Chart.yaml?
AЧарт быстрее ставится
BЧарт содержит только переиспользуемые шаблоны и не создаёт собственных ресурсов
CЧарт нельзя обновить
DЭто устаревший формат
2. Как ведут себя списки при слиянии values?
AОбъединяются поэлементно
BЗаменяются целиком значением верхнего слоя
CСортируются
DДублируются
3. Зачем нужен values.schema.json?
AУскоряет рендеринг
BВалидирует переданные values по типам и обязательным полям перед установкой
CШифрует значения
DСоздаёт релиз