Application vs Module — официальная граница

Уровень: beginner ~45 мин

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

  • M0.01 — Карта экосистемы — первое знакомство с разграничением Application/Module
  • M1.11 — RBAC — методическая параллель: cluster-wide vs namespaced права

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

M0 урок 1 уже вводил разграничение Application/Module на уровне интуиции. Здесь мы формализуем его дословно по официальной документации и закрепляем как критерий, который будет применяться к каждой следующей теме курса.

Теория

Package — общая абстракция

Платформа Deckhouse оперирует единой абстракцией Package. У Package есть ровно два конкретных вида — Module и Application. Официальное определение (Deckhouse — Концепции Application и Module):

Дословная цитата — граница курса
Package — абстракция платформы, бывает Application или Module. Module: cluster-wide, один на кластер, может создавать CRD и cluster-wide объекты, предназначен для расширения инфраструктуры. Application: namespaced, неограниченное число инстансов, запрещено создавать CRD и cluster-wide объекты, предназначен для пользовательских workload’ов.

Таблица сравнения

КритерийModuleApplication
Область действияcluster-widenamespaced
Число инстансов в кластереровно одиннеограниченное число
Может создавать CRDданет
Может создавать cluster-wide объектыданет
Назначениерасширение инфраструктуры платформыпользовательские workload’ы
Линтерdmtlint (9 линтеров)pkglint (6 линтеров)
Примерmanaged-postgres, ingress-nginx, cert-manager, albваш веб-сервис, бот, внутренний инструмент

Сравнение реальных деревьев файлов

Разница видна буквально на уровне структуры проекта. Дерево Module (по официальной документации Deckhouse — Структура Module, приводится только для контраста, не как учебный материал — курс не учит разработке Module):

my-module/
  module.yaml
  crds/                    # ← только у Module: собственные CRD
    my-crd.yaml
  charts/
    helm_lib/               # ← общая библиотека helm-хелперов платформы
  hooks/
    batch/                  # ← cluster-wide хуки (OnKubernetesEvent и др.)
  templates/
  openapi/
    config-values.yaml
    conversions/            # ← версионирование схемы настроек модуля
      v1.yaml
  .werf/
    workflows/

Дерево Application (по официальной документации Deckhouse — Разработка Application-пакета, разбирается подробно во всём M5):

my-app/
  package.yaml              # apiVersion, type: Application, name, requirements...
  changelog.yaml
  .gitlab-ci.yml
  .pkglint.yaml
  docs/
  hooks/batch/               # ← хуки Application, ограничены namespace инстанса
  images/
  openapi/
    config-values.yaml       # схема пользовательских settings
    values.yaml               # helm-values контракт
  templates/
  oss.yaml

Отсутствие crds/ и полноценных .werf/workflows/ — не случайность, а прямое следствие архитектурного запрета: Application физически не может объявлять CRD, поэтому у него просто нет соответствующей директории в структуре проекта.

Почему это архитектурное решение, а не произвольное ограничение

Три причины, почему платформа проводит эту границу именно так:

  1. Изоляция. CRD и cluster-wide объекты влияют на весь кластер сразу. Если бы любой Application мог объявлять собственные CRD, два независимо установленных Application от разных разработчиков могли бы случайно (или злонамеренно) конфликтовать за одно и то же CRD-имя, ломая друг друга. Ограничение Application до namespaced-ресурсов делает установку одного Application физически не способной повлиять на любой другой namespace.
  2. Безопасность. Cluster-wide права требуют cluster-wide доверия. Позволяя Module создавать CRD/RBAC cluster-wide, платформа требует от Module более строгой проверки (отсюда — 9 линтеров dmtlint против 6 у pkglint, подробно в M9), а Application, ограниченный namespace, может безопасно устанавливаться пользователями с меньшим уровнем доверия/прав.
  3. Множественные инстансы. Пользовательские workload’ы — по природе штука, которую разумно ставить много раз с разными настройками (два независимых сайта, два инстанса Redis под разные задачи). Cluster-wide CRD физически не масштабируется на «поставить 10 раз с разными настройками» — CRD либо есть в кластере, либо нет, в единственном экземпляре схемы. Namespaced-модель Application снимает это противоречие.
flowchart TB Package["Package (абстракция платформы)"] Package --> Module["Module\ncluster-wide, 1 на кластер\nсоздаёт CRD/cluster-wide объекты\nдля инфраструктуры"] Package --> App["Application\nnamespaced, N инстансов\nЗАПРЕЩЕНО CRD/cluster-wide\nдля пользовательских workload'ов"] Module -->|"пример"| MEx["managed-postgres, ingress-nginx, alb"] App -->|"пример"| AEx["ваш сайт / бот / внутренний сервис"]

Правило для любой новой темы курса

Всякий раз, когда в курсе встречается что-то, относящееся к платформе Deckhouse (а не к чистому Kubernetes из M1), задавайте себе вопрос: это про Application или про Module? Если про Module — курс раскрывает его ровно в объёме, нужном для понимания зависимости и диагностики (как в M6), но не для самостоятельной разработки.

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

  • Пытаться «на всякий случай» добавить CRD в свой Application-пакет. pkglint (см. M9 урок 2) явно проверяет это ограничение и отклонит такой пакет на этапе d8 package verify.
  • Считать, что «Module — это просто более сложный/старый способ упаковки», а Application — «новый, упрощённый». Разница не в возрасте или сложности API, а в архитектурной ответственности: инфраструктура vs пользовательский workload.
  • Путать «неограниченное число инстансов Application» с «Application можно установить только один раз на namespace». Можно поставить сколько угодно инстансов и в одном namespace тоже (при условии, что имена ресурсов не конфликтуют — подробно в M5 уроке 7).

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

🧩 Практика урока: Без нового приложения — инспектируем платформу
  1. Посмотрите список установленных в вашем кластере Module (cluster-wide, один экземпляр каждого):
1
2
d8 k get modules
d8 k get module ingress-nginx -o yaml | head -30   # cluster-scoped, без namespace в metadata
  1. Если в вашем CE-кластере уже есть установленные Application (после прохождения M5+) — сравните:
1
d8 k get application -A    # namespaced — обязательно указывается namespace
  1. Явно убедитесь, что Module — cluster-scoped тип API, а гипотетический Application — namespaced (когда установите первый в M5):
1
kubectl api-resources | grep -iE "module|application"

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

В этом уроке нет собственной сборки — мы только классифицируем существующие концепции платформы.

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

1
2
3
d8 k get modules
d8 k get module <name> -o yaml
kubectl api-resources --namespaced=false | grep -i module

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

Сколько инстансов Module может быть установлено в одном кластере одновременно?

Module — cluster-wide Package, устанавливается ровно в одном экземпляре на кластер, в отличие от Application.

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

Может ли Application создавать собственные CRD?

Application по определению не может создавать CRD или cluster-wide объекты — это одно из фундаментальных ограничений, проверяемых линтером pkglint.

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

Почему запрет на CRD у Application — архитектурное решение, а не случайное ограничение?

Три причины: изоляция инстансов друг от друга, требования безопасности к cluster-wide доверию, и физическая несовместимость CRD (единственная cluster-wide схема) с идеей множественных независимых инстансов.

Источник: Deckhouse — Концепции Application и Module

Какой линтер применяется к Module, а какой — к Application?

dmtlint (Deckhouse Module Tool) с 9 линтерами проверяет Module; pkglint с 6 линтерами — Application-пакеты.

Источник: GitHub — deckhouse/dmt

Этот курс учит самостоятельной разработке Module?

Явно зафиксированное ограничение курса: фокус на Application, Module — только как зависимость и часть архитектуры платформы.

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

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

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

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

Книги

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

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