Go-хуки Application
Что нужно знать перед уроком
- M5.07 — Множественные инстансы одного пакета — нужно понимать модель namespace-изоляции Application перед разбором того, как хуки эту изоляцию соблюдают
- M2.02 — Как устроен Deckhouse изнутри — общее представление о типах хуков модулей для контраста с хуками Application
Что нужно знать перед уроком
M2 урок 2 — типы хуков Module (OnStartup/BeforeHelm/… — только обзорно, не для написания). M5 урок 5 — хуки Application жёстко ограничены собственным namespace. Здесь — как реально пишется код хука Application.
Теория
ApplicationHookInput — базовый хук
| |
input.Instance() даёт доступ к метаданным конкретного установленного инстанса — то же смысловое значение, что и .Application.Instance.Name в шаблонах (M5 урок 4), но со стороны программируемой Go-логики, а не шаблонизации. input.ObjectPatcher() — специальный клиент для создания/изменения ресурсов, архитектурно ограниченный namespace конкретного инстанса (M5 урок 5) — попытка адресовать ресурс в другом namespace будет отклонена во время выполнения, а не просто «не сработает по недосмотру».
Чем отличается от HookInput модулей
Хуки Module (упомянутые обзорно в M2 уроке 2) используют более широкий HookInput, не ограниченный namespace — логично, т.к. Module по определению работает на уровне всего кластера. ApplicationHookInput — специализированный, более узкий интерфейс именно потому, что Application по определению должен оставаться в рамках namespace (M5 урок 5) — сама сигнатура типа в SDK физически не даёт возможности выйти за эту границу, а не просто документирует правило, которое разработчик обязан не нарушать по доброй воле.
settingscheck.Input/Result — валидация настроек сверх JSON Schema
| |
Этот тип хука решает задачу, которую не может решить обычная JSON Schema-валидация (M5 урок 3): JSON Schema прекрасно проверяет тип/диапазон/обязательность отдельного поля (minimum/maximum для числа), но не может выразить бизнес-логику, зависящую от комбинации нескольких полей или требующую нетривиального вычисления. Пример из документации показывает именно такой случай: replicas == 0 отклоняется (Reject), replicas == 2 разрешается, но с предупреждением (Allow с warning про потенциальный split-brain — специфика распределённых систем, которую JSON Schema принципиально не может выразить), replicas > 3 снова отклоняется.
Хук вызывается до того, как DKP применит изменения (M2 урок 3, статусная модель ConfigurationApplied) — если хук возвращает Reject, condition ConfigurationApplied перейдёт в False с reason: ConfigurationFailed (M5 урок 10), не давая невалидной конфигурации дойти до реального Nelm-рендера.
Когда settingscheck нужен, а когда достаточно JSON Schema
| Ситуация | Достаточно JSON Schema? | Нужен settingscheck |
|---|---|---|
| Поле должно быть числом от 1 до 10 | да (minimum/maximum) | нет |
| Поле обязательно, если задано другое поле | частично (if/then в JSON Schema сложны для читаемости) | часто удобнее и понятнее через хук |
| Комбинация нескольких полей должна соответствовать бизнес-правилу (нечётное число реплик для кворума, суммарный лимит ресурсов не должен превышать квоту) | нет | да |
| Предупреждение (не блокирующая ошибка) о потенциально проблемной, но допустимой конфигурации | нет (JSON Schema либо валидна, либо нет — нет концепции «предупреждения») | да, через Allow(warnings...) |
Частые ошибки и подводные камни
- Пытаться выполнить cluster-wide операцию через
ObjectPatcherхука Application. Это архитектурно заблокировано в самом SDK — попытка адресовать ресурс вне namespace инстанса вернёт ошибку выполнения, а не тихо проигнорируется. - Дублировать в
settingscheckпроверки, которые JSON Schema уже покрывает. Если проверку можно выразить декларативно черезopenapi/config-values.yaml(M5 урок 3) — используйте её, оставляя Go-хуки для действительно нетривиальной логики, требующей вычислений или комбинации полей. - Забыть, что
Rejectблокирует именноConfigurationApplied, а не всю установку целиком. Пользователь увидит понятную причину отказа в статусной модели (M5 урок 10), но сам ресурсApplicationостанется существовать в кластере, просто не сможет перейти в готовое состояние, пока настройки не будут исправлены.
Практика в кластере
Практики в кластере в этом уроке нет — компиляция и логика хука проверяются локально, поведение хука в связке со статусной моделью — в конце модуля (M5 урок 10) и в M6 при полном сценарии зависимостей.
Практика разработки
- Добавьте хук валидации настроек для Umami в
hooks/batch/settings-check/main.go, ограничивающийreplicasразумным диапазоном и предупреждающий о потенциальных проблемах:
| |
- Соберите хук локально, чтобы убедиться в отсутствии ошибок компиляции:
| |
- Добавьте базовый хук синхронизации (пока без реальной логики, просто для проверки доступа к метаданным инстанса):
| |
Шпаргалка команд урока
| |
Вопросы для самопроверки
Application по определению namespace-scoped, поэтому и его SDK-интерфейс физически ограничивает область действия.
Источник: Deckhouse — Хуки Application
JSON Schema хорошо покрывает проверку отдельных полей, но не сложную межполевую логику и не концепцию предупреждений.
Источник: Deckhouse — Хуки Application
Allow с warnings позволяет продолжить, но сигнализирует пользователю о потенциально проблемной, но допустимой конфигурации.
Источник: Deckhouse — Хуки Application
Reject блокирует именно применение конфигурации, отражаясь в статусной модели, а не удаляет ресурс целиком.
Источник: Deckhouse — Troubleshooting
Это ключевая гарантия изоляции мультитенантности, реализованная непосредственно в самом ObjectPatcher.
Источник: Deckhouse — Хуки Application
Рекомендуемая литература
Официальная документация
Статьи и блоги
- Разворачиваем приложение в кластере Kubernetes под управлением Deckhouse c помощью werf — Flant на Habr.
- Готовим Gitea со вкусом werf CI/CD в кластере Deckhouse. Часть 3 — Flant на Habr.
- Вышла werf 2.0: новый движок развёртывания Nelm — Flant на Habr.
Книги
- Marko Lukša. Kubernetes in Action. 2nd ed., 2022. ISBN 978-1617297618.
Связанные материалы
- Предыдущий урок: M5.07 — Множественные инстансы одного пакета.
- Следующий урок: M5.09 — Жизненный цикл через d8 package.
- Заполнение internal.* значений хуками: M5 урок 3.
✓ Урок пройден — все вопросы самопроверки отвечены верно