Контракт настроек — обе схемы

Уровень: advanced ~55 мин Практика: Umami (MIT)

Что нужно знать перед уроком

  • M5.02 — package.yaml: разбор каждого поля — нужно понимать общий манифест пакета перед погружением в контракт настроек

Что нужно знать перед уроком

M4 урок 1values.yaml как источник значений для шаблонов. M5 уроки 1–2 — место openapi/ в структуре пакета. Здесь — зачем нужны две отдельные схемы, а не одна.

Теория

Две схемы, два разных назначения

openapi/
├── config-values.yaml   # (или settings.yaml) — контракт Application.spec.settings
└── values.yaml            # полный helm-values контракт

config-values.yaml (иногда называется settings.yaml в зависимости от версии/конвенции) — JSON Schema, описывающая пользовательские настройки: то самое подмножество полей, которое конечный пользователь пакета указывает в spec.settings объекта Application при установке. Именно эта схема валидируется, когда пользователь пишет:

1
2
3
4
5
6
7
8
9
apiVersion: deckhouse.io/v1alpha1
kind: Application
metadata:
  name: my-umami
spec:
  packageName: umami
  settings:
    replicas: 2
    hostname: "analytics.example.com"

openapi/values.yaml — полный контракт всех значений, которые видят Helm-шаблоны (.Values в терминах M4 урока 1), включая внутренние, недоступные напрямую пользователю поля (internal.*) — вычисляемые платформой или хуками значения (например, разрешённый IP управляемой БД после успешного подключения к Module-зависимости).

x-extend+internal.triggers

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# openapi/values.yaml
x-extend:
  schema: config-values.yaml
type: object
properties:
  internal:
    type: object
    default: {}
    properties:
      triggers:
        type: object
        default: {}

Директива x-extend.schema: config-values.yaml буквально расширяет пользовательскую схему настроек в полный values-контракт — все свойства из config-values.yaml автоматически становятся частью values.yaml-схемы, плюс сверху добавляется секция internal (и, в частности, internal.triggers — служебные значения, используемые для внутренней координации между хуками и шаблонами, например, флаг «настройки БД уже подтянуты и провалидированы хуком»). Это архитектурное решение устраняет дублирование: не нужно вручную повторять каждое пользовательское поле в обеих схемах — config-values.yaml является единственным источником истины для пользовательской части, а values.yaml просто добавляет к ней внутренний слой.

Разбор типичных рассинхронов имён файлов

При сверке реальных примеров Application-пакетов (Applications/*) встречаются вариации именования, о которых важно знать заранее:

  • Пакет minecraft использует settings.yaml вместо config-values.yaml для пользовательской схемы — оба имени признаются платформой, конкретное имя — вопрос конвенции конкретной версии инструментария, а не жёсткое ограничение.
  • Пакет quake3 демонстрирует расширенную вложенность настроек (settings.server.maxPlayers вместо плоской структуры) — иллюстрирует, что JSON Schema поддерживает произвольную вложенность, а не только плоский список примитивов.
  • Пакет pgadmin (тот же пример, что и полный разбор зависимости в M6 уроке 2) показывает типичный паттерн internal.*-полей, заполняемых хуком после проверки доступности зависимого Module, а не статически заданных пользователем.

Практическая схема для Umami

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
# openapi/config-values.yaml
type: object
properties:
  hostname:
    type: string
    description: "Публичный домен для доступа к Umami"
  replicas:
    type: integer
    default: 1
    minimum: 1
    maximum: 5
  database:
    type: object
    properties:
      storageSize:
        type: string
        default: "5Gi"
required:
  - hostname
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# openapi/values.yaml
x-extend:
  schema: config-values.yaml
type: object
properties:
  internal:
    type: object
    default: {}
    properties:
      postgresConnectionString:
        type: string
        default: ""

Частые ошибки и подводные камни

  • Дублировать пользовательские поля вручную и в config-values.yaml, и в values.yaml, не используя x-extend. Это создаёт риск рассинхрона схем при последующих изменениях — правильный подход всегда через x-extend.schema.
  • Помещать внутренние вычисляемые значения (internal.*) в config-values.yaml. Пользователь не должен (и не может по замыслу) задавать internal.postgresConnectionString напрямую — эти поля предназначены исключительно для заполнения хуками (M5 урок 8), а не пользователем.
  • Игнорировать разницу именования (config-values.yaml vs settings.yaml) как «просто синоним без последствий». Хотя оба варианта признаются платформой, смешение конвенций в одном пакете (например, документация ссылается на один файл, а реально используется другой) сбивает с толку и затрудняет поддержку.

Практика в кластере

Практики в кластере в этом уроке нет — фокус на JSON Schema контракте, первая установка Application с валидацией настроек — в конце модуля.

Практика разработки

🧩 Практика урока: Umami · лицензия MIT
  1. Добавьте обе схемы из теории урока в пакет Umami, созданный в M5 уроке 1.

  2. Проверьте, что схема config-values.yaml синтаксически валидна как JSON Schema:

1
python3 -c "import json,yaml; json.dumps(yaml.safe_load(open('openapi/config-values.yaml')))" && echo "OK"
  1. Смоделируйте установку с намеренно невалидными настройками (без обязательного hostname) и без реального применения в кластер посмотрите, как выглядела бы ошибка валидации (через nelm chart lint, зная итоговый values-контракт после x-extend):
1
nelm chart lint . --set replicas=2
  1. Убедитесь, что после добавления x-extend вам не нужно вручную дублировать hostname/replicas/database в values.yaml — они автоматически «наследуются» из config-values.yaml.

Шпаргалка команд урока

1
2
d8 package verify         # включает валидацию openapi-схем как часть pkglint
nelm chart lint <chart-dir>

Вопросы для самопроверки

В чём разница между openapi/config-values.yaml и openapi/values.yaml?

Первая схема — то, что видит и задаёт пользователь; вторая — полный контракт для шаблонов, включая служебные вычисляемые поля.

Источник: Deckhouse — Разработка Application-пакета

Что делает директива x-extend.schema: config-values.yaml в values.yaml?

x-extend делает config-values.yaml единственным источником истины для пользовательской части values-схемы.

Источник: Deckhouse — Structure

Может ли пользователь напрямую задать значение internal.postgresConnectionString через Application.spec.settings?

internal-секция — служебный слой, вычисляемый хуками (например, после подтверждения доступности зависимого Module), недоступный для прямого задания пользователем.

Источник: Deckhouse — Разработка Application-пакета

Является ли имя settings.yaml вместо config-values.yaml ошибкой?

Оба варианта именования встречаются в реальных Application-пакетах и распознаются платформой.

Источник: Deckhouse — Разработка Application-пакета

Поддерживает ли config-values.yaml вложенные объекты в настройках (не только плоские примитивы)?

config-values.yaml — обычная JSON Schema, полностью поддерживающая вложенные объекты и массивы.

Источник: Deckhouse — Разработка Application-пакета

Рекомендуемая литература

Официальная документация

Статьи и блоги

Книги

  • Marko Lukša. Kubernetes in Action. 2nd ed., 2022. ISBN 978-1617297618.

Связанные материалы