Паттерн «общий ресурс между релизами»

Уровень: advanced ~45 мин Практика: Umami (продолжение M5) (MIT)

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

  • M6.04 — Паттерн «Job-миграция перед Deployment» — нужен опыт с аннотациями Nelm перед изучением следующего паттерна

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

M6 урок 4 — первый паттерн управления порядком через аннотации Nelm. Здесь — паттерн для другой задачи: что делать, когда один и тот же ресурс должен быть общим между несколькими независимыми релизами (Helm-релизами/Application-инстансами), и как защитить его от случайного удаления.

Теория

Дефолтное поведение Nelm: ownership: release

По умолчанию Nelm считает, что каждый ресурс в кластере принадлежит ровно одному релизу — тому, который его создал. Если этот релиз будет удалён (nelm release uninstall, M4 урок 5) — все его ресурсы, включая данный, будут удалены вместе с ним. Это разумное поведение по умолчанию для подавляющего большинства ресурсов (никто не хочет «осиротевших» ConfigMap/Service после удаления релиза), но создаёт проблему, если конкретный ресурс намеренно должен переживать удаление отдельного релиза, т.к. используется несколькими.

werf.io/ownership: anyone — явное объявление совместного владения

1
2
3
4
5
6
7
8
apiVersion: v1
kind: Secret
metadata:
  name: {{ .Application.Instance.Name }}-shared-tls
  annotations:
    werf.io/ownership: anyone
type: kubernetes.io/tls
data: ...

Пример из официальной документации — общий TLS-сертификат (Secret), используемый несколькими чартами/релизами (например, wildcard-сертификат для целого поддомена, которым пользуются сразу несколько Application-инстансов одной команды). Аннотация werf.io/ownership: anyone сообщает Nelm: «этот ресурс не принадлежит единолично данному релизу — не удаляй его при uninstall этого конкретного релиза, т.к. другие релизы тоже могут на него ссылаться».

Почему без этой аннотации Nelm удалит секрет

Без ownership: anyone при выполнении nelm release uninstall для любого из релизов, которые рендерят этот Secret в своих шаблонах, Nelm посчитает себя единоличным владельцем ресурса (дефолт ownership: release) и удалит его — даже если другие релизы всё ещё от него зависят. Результат — неожиданный обрыв работы других, казалось бы, не затронутых операцией удаления релизов, чьи ресурсы внезапно ссылаются на несуществующий Secret.

Другой контекст ownership: anyone — дефолт для hooks и CRD

Важная деталь для полноты картины (хотя CRD неприменимо для Application из-за ограничений M5 урока 5): ownership: anyone — это дефолтное поведение для служебных категорий ресурсов вроде hooks и CRD в crds/-директории Module-чартов, но не дефолт для обычных ресурсов (Deployment/Service/Secret/ConfigMap) — для них дефолт всегда release, и ownership: anyone нужно указывать явно, только когда есть осознанная необходимость совместного владения. Полный разбор всех lifecycle-аннотаций — M7 урок 3.

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

  • Ставить ownership: anyone «на всякий случай» на все ресурсы. Это лишает Nelm возможности корректно очищать ресурсы при реальном удалении релиза — приводит к накоплению «осиротевших» объектов в кластере, которые никто не удаляет автоматически ни при каких обстоятельствах.
  • Забывать про ownership: anyone для действительно общих ресурсов и получать неожиданное удаление при, казалось бы, несвязанной операции uninstall другого релиза. Это довольно коварная ошибка — проблема проявляется не в том релизе, который вы удаляли, а в совершенно другом, использующем тот же ресурс.
  • Не документировать, какие ресурсы являются общими между релизами. Если в команде несколько разработчиков управляют разными Application-инстансами, использующими общий ресурс, отсутствие явной документации о совместном использовании создаёт риск случайного удаления кем-то, кто не знает о зависимости других релизов.

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

🧩 Практика урока: Umami (продолжение M5) · лицензия MIT

Смоделируйте сценарий двух инстансов Umami (как в M5 уроке 7), совместно использующих один TLS-секрет:

  1. Добавьте общий Secret с аннотацией ownership: anyone в шаблоны, устанавливаемые обоими инстансами:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
apiVersion: v1
kind: Secret
metadata:
  name: umami-shared-tls
  annotations:
    werf.io/ownership: anyone
type: kubernetes.io/tls
data:
  tls.crt: ""
  tls.key: ""
  1. Установите оба инстанса, оба рендерят один и тот же Secret:
1
2
3
nelm release install -n course-m6-umami -r umami-a . --auto-rollback
nelm release install -n course-m6-umami -r umami-b . --auto-rollback
d8 k get secret umami-shared-tls -n course-m6-umami
  1. Удалите один из релизов и убедитесь, что общий Secret не был удалён:
1
2
nelm release uninstall -n course-m6-umami -r umami-a
d8 k get secret umami-shared-tls -n course-m6-umami
  1. Для сравнения, повторите эксперимент без аннотации ownership: anyone (в отдельном тестовом namespace) и убедитесь, что Secret действительно удаляется при первом же uninstall.

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

Практики разработки в этом уроке нет — весь материал относится к аннотациям шаблонов, применённым в практике выше.

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

1
2
werf.io/ownership: release   # дефолт для обычных ресурсов — удаляется вместе со своим релизом
werf.io/ownership: anyone    # ресурс переживает uninstall — используется несколькими релизами

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

Что произойдёт с ресурсом при uninstall релиза, если не указана аннотация werf.io/ownership?

Дефолтное поведение — единоличное владение релизом, создавшим ресурс.

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

Для чего нужна аннотация werf.io/ownership: anyone?

anyone сообщает Nelm, что ресурс не принадлежит единолично текущему релизу.

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

Является ли ownership: anyone дефолтным поведением для ВСЕХ ресурсов?

Для Deployment/Service/Secret/ConfigMap и подобных ресурсов дефолт — release, anyone нужно указывать явно.

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

Что произойдёт при удалении релиза A, если ресурс без ownership: anyone используется также релизом B?

Дефолт release означает единоличное владение — удаление A затронет ресурсы, на которые ссылается B, если не указан anyone.

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

Хорошая ли практика ставить ownership: anyone на все ресурсы 'на всякий случай'?

ownership: anyone нужно использовать точечно, только для действительно намеренно общих ресурсов.

Источник: Рекомендуемая литература

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

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

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

Книги

  • Michael Hausenblas, Stefan Schimanski. Programming Kubernetes. 2019. ISBN 978-1492047107.

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