Четыре известных подводных камня Nelm

Уровень: expert ~40 мин Практика: Umami (финал M5-M7) (MIT)

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

  • M7.08 — Семь готовых use-case'ов — нужен полный набор аннотаций/функций как контекст перед разбором того, что может пойти не так

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

M7 уроки 1–8 — полный справочник аннотаций и функций. Этот заключительный урок модуля разбирает четыре официально задокументированных подводных камня Nelm — не гипотетические, а реально зафиксированные в официальной документации Nelm-аннотаций проблемы, с которыми сталкиваются разработчики Application-пакетов.

Теория

Подводный камень 1 — Server-Side Apply и null-значения

Server-Side Apply может провалиться на полях со значением null. Если значение из .Values равно nil (например, необязательный параметр не задан в config-values.yaml), итоговый манифест будет содержать foo: null — и в зависимости от типа поля Kubernetes API может либо корректно интерпретировать это как «убрать поле», либо выдать ошибку валидации, в зависимости от специфики конкретного API-ресурса и его OpenAPI-схемы.

Решение: оборачивать потенциально пустые значения в {{ if .Values.foo }} (полностью исключая поле из манифеста, если значение отсутствует) или использовать функцию default:

1
replicas: { { .Values.replicaCount | default 1 } }

Подводный камень 2 — lookup и рассинхронизация Plan/Apply

Функция lookup (стандартная Helm-функция для чтения текущего состояния объектов кластера прямо во время рендера) может привести к устаревшему («stale») отрендеренному плану, если ресурсы кластера изменяются в промежутке между стадиями Plan и Apply (M4 урок 4) — Plan увидел одно состояние, а к моменту Apply состояние кластера уже другое, и итоговое поведение становится непредсказуемым.

Решение: не использовать lookup для критичной логики (условного изменения манифеста на основе текущего состояния кластера); вместо этого передавать нужные данные явно через .Values, полученные заранее (например, через --set в CI-пайплайне) или через собственный механизм получения состояния вне цикла Render/Plan/Apply одного релиза.

Подводный камень 3 — недетерминированные функции и «мерцающий» diff

Функции вроде now (текущее время) и randAlphaNum (случайная строка), а также итерация по map с переменным порядком ключей (в Go map не гарантирует порядок итерации без явной сортировки) могут производить разный рендер при каждом вызове. Это приводит к ложным diff’ам при включённом «замораживании» плана (сравнении Plan с предыдущим состоянием) — Nelm видит «изменение», хотя пользователь не менял ничего осмысленного, просто рендер каждый раз генерирует новое случайное значение или другой порядок ключей.

Решение: избегать now/randAlphaNum в местах, где важна стабильность рендера между запусками (например, для меток или полей, которые не должны меняться при каждом деплое); для генерации одноразовых секретов при первой установке — see также use case 6 из M7 урока 8 (deploy-on: install + ownership: anyone), фиксирующий значение один раз и не пересоздающий его при обновлениях; для итерации по map — использовать явную сортировку ключей (keys | sortAlpha) перед range.

Подводный камень 4 — deploy-dependency не работает между разными lifecycle-фазами

deploy-dependency, разобранный в M7 уроке 2, строит DAG в рамках одной операции (install/upgrade/rollback) — если ресурс А имеет deploy-on: pre-install, а ресурс Б (с deploy-dependency на ресурс А) имеет deploy-on: install, зависимость не сработает предсказуемо в том смысле, в котором ожидается: pre-install и install — это, по сути, разные проходы рендера/применения, и DAG для каждой фазы строится независимо, а не как единое целое между фазами.

Решение: держать взаимозависимые ресурсы в одной lifecycle-фазе (deploy-on), используя deploy-dependency/weight только для управления порядком внутри этой фазы; если необходима строгая последовательность между разными фазами (pre-installinstall), полагаться на естественную гарантию порядка самих фаз (Kubernetes/Nelm выполняет pre-install целиком до перехода к install), а не пытаться связать конкретные ресурсы разных фаз через deploy-dependency.

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

(Этот раздел урока целиком посвящён подводным камням — см. теорию выше, где каждый камень уже сопровождён решением.)

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

🧩 Практика урока: Umami (финал M5-M7) · лицензия MIT

Проверьте пакет Umami на все четыре подводных камня:

1
2
grep -n "lookup\|now \|randAlphaNum" templates/*.yaml
nelm chart render . -r umami | grep -B2 ": null"

Если найдены потенциально проблемные конструкции — примените решения из теории (обёртки if/default, замена lookup на явные .Values, стабилизация случайных значений через deploy-on: install + ownership: anyone).

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

Проведите финальный аудит всего пакета Umami (накопленного за M5–M7) на соответствие всем разобранным в курсе паттернам и подводным камням — это готовит пакет к следующему этапу курса, посвящённому CI/CD-публикации в M8.

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

Полный список известных pitfalls — 📋 nelm .

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

Что происходит, если значение .Values.foo равно nil и подставляется напрямую в манифест?

Решение — обёртка {{ if }} или функция default.

Источник: Deckhouse — Nelm-аннотации

Почему использование lookup в шаблонах рискованно?

Между Plan и Apply может пройти время, за которое состояние кластера изменится.

Источник: Deckhouse — Nelm-аннотации

Почему now и randAlphaNum могут вызывать ложные diff при замороженном плане?

Недетерминированность рендера — источник ложных срабатываний diff.

Источник: Deckhouse — Nelm-аннотации

Работает ли deploy-dependency предсказуемо между РАЗНЫМИ lifecycle-фазами (например, pre-install и install)?

Между фазами гарантируется только последовательность самих фаз, а не связь конкретных ресурсов через deploy-dependency.

Источник: Deckhouse — Nelm-аннотации

Сколько официально задокументированных pitfalls разобрано в этом уроке?

Это полный список известных подводных камней из [официальной документации Nelm-аннотаций](https://deckhouse.ru/products/kubernetes-platform/documentation/latest/architecture/marketplace/nelm-annotations.html).

Источник: Deckhouse — Nelm-аннотации

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

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

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

Книги

  • Matt Butcher, Matt Farina, Josh Dolitsky. Learning Helm. 2019. ISBN 978-1492036781.

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