dmtlint — назначение и архитектура платформенного линтера

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

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

  • M9.02 — pkglint глубоко — нужен полный разбор pkglint для содержательного сравнения с dmtlint
  • M2.04 — Компоненты платформы и линтеры — нужно первое, обзорное знакомство с различием dmtlint/pkglint

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

M9 урок 2 — полный разбор pkglint. M2 урок 4 — первое, обзорное упоминание dmtlint. Этот урок — чистая теория, без практики разработки Module (что противоречило бы фокусу курса на Application) — разбирает dmtlint как инструмент, важный для понимания качества платформы, от которой зависят Application-пакеты.

Теория

Что такое DMT (Deckhouse Module Tool)

DMT — Deckhouse Module Tool, репозиторий deckhouse/dmt на GitHub, содержащий инструменты для разработки Module: линтер (dmtlint, реализованный как подкоманда dmt lint), скаффолдинг новых Module (dmt bootstrap), рендеринг чартов для отладки (dmt render) и тестирование конверсий/шаблонов (dmt test).

Зачем Module нужен более строгий линтер, чем Application

Ключевая архитектурная причина, напрямую связанная с ограничениями Application из M5 урока 5: Module может создавать cluster-wide ресурсы, CRD, определять RBAC для доступа к произвольным API-группам, запускать хуки с доступом ко всему кластеру. Цена ошибки для Module принципиально выше — некорректный RBAC модуля может случайно предоставить избыточные права всему кластеру, ошибка в CRD-схеме может сломать данные во всех объектах этого CRD в кластере, а не в одном namespace, как максимум для Application. Именно поэтому линтер для Module должен покрывать значительно больше поверхности потенциальных ошибок.

Полный разбор девяти линтеров dmtlint

ЛинтерЧто проверяет
containerДубли имён контейнеров, корректность env, securityContext, наличие probes, разумность resources
docsREADME, билингвальность документации (ru/en), отсутствие кириллицы в англоязычной версии
hooksСинтаксис Go-хуков модуля, корректность ingress-конфигураций, регистрируемых хуками
imagesПрактики Dockerfile/werf-сборки образов модуля
modulemodule.yaml, конверсии OpenAPI-схем между версиями настроек, oss.yaml, лицензии зависимостей
no-cyrillicОтсутствие кириллических символов там, где ожидается только английский текст (отдельный от docs линтер, применяемый шире)
openapiКорректность OpenAPI-схем, соответствие конвенциям именования CRD
rbacКорректность Role/RoleBinding, ServiceAccount, обнаружение избыточных wildcard-прав (resources: ["*"], verbs: ["*"])
templatesНаличие VerticalPodAutoscaler/PodDisruptionBudget, корректность интеграции с Prometheus/Grafana, портов сервисов

.dmtlint.yaml — формат конфигурации

1
2
3
4
5
6
7
8
9
linters-settings:
  rbac:
    impact: error
    exclude-rules:
      wildcards:
        - kind: ClusterRole
          name: my-module-controller
  openapi:
    impact: warn

linters-settings.<linter>.impact — управляет строгостью конкретного линтера целиком (error — блокирует, warn — только предупреждение, не блокирует). exclude-rules вложен внутрь настроек конкретного линтера и сгруппирован по имени конкретного правила этого линтера (в примере — wildcards, правило детектора избыточных прав внутри линтера rbac) — точечное исключение конкретных находок по kind/name (для некоторых правил — по имени контейнера или строке-имени). Это принципиально более гранулярный механизм, чем у pkglint из M9 урока 2: у pkglint нет исключений по kind/name конкретного ресурса вообще — там правило можно только целиком выключить, поставив ему impact: ignored в .pkglint.yaml. Такая разница оправдана архитектурно: в одном Application-пакете обычно один экземпляр каждого вида ресурса, тогда как в Module шаблонах одного kind (например, ClusterRole) часто несколько — и нужно исключить находку только для одного конкретного ресурса, не отключая проверку для остальных.

Команды dmt

1
2
3
4
dmt lint [dirs...] [--linter <name>] [--values-file] [--hide-warnings] [--abs-path] [--show-ignored] [--log-level]
dmt bootstrap <name> [--pipeline github|gitlab] [--directory] [--repository-url]
dmt render [module-path] [--output]
dmt test conversions|templates [module-path] [--update]

dmt render и dmt test conversions|templates заслуживают отдельного пояснения, поскольку они существенно отличаются от helm template/обычного CI-тестирования: dmt render учитывает Module-специфичный контекст (значения из values.yaml, полученные от Deckhouse-платформы, а не просто «сырые» Helm values, как в обычном helm template), а dmt test conversions проверяет корректность миграции настроек между версиями схемы config-values.yaml модуля (сценарий, которого у Application вообще нет — у Application нет версионируемых конверсий настроек между релизами, только прямая замена значений).

Прямое количественное сравнение с pkglint

pkglint (Application)dmtlint (Module)
Число линтеров69
RBAC-проверкиНет (Application не создаёт RBAC уровня кластера)Есть (rbac)
CRD/OpenAPI-конверсииНетЕсть (openapi, часть module)
Проверка хуковНет отдельного линтераЕсть (hooks)
Проверка контейнеров (env/securityContext/probes)Частично, через templatesОтдельный линтер container

Полтора раза больше линтеров и на порядок больше конкретных правил внутри каждого — прямое следствие того, что у Module в полтора-два раза больше типов сущностей и связанных с ними классов возможных ошибок, недоступных Application по архитектуре.

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

  • Путать dmtlint и pkglint при чтении логов CI сторонних Module-репозиториев. Как разработчик Application, вы можете столкнуться с выводом dmtlint, читая CI Module, от которого зависит ваше приложение — важно узнавать его формат и не путать с pkglint вашего собственного пакета.
  • Считать dmtlint избыточно строгим «просто так». Строгость dmtlint прямо пропорциональна цене ошибки в Module (cluster-wide последствия) — это не бюрократия, а осознанный компромисс безопасности платформы.
  • Пытаться применить конфигурацию .dmtlint.yaml к Application-пакету или наоборот. Это два разных инструмента с разными наборами линтеров и разным форматом конфигурации — они не взаимозаменяемы.

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

Практики в кластере в этом уроке нет — это чистая теория, практика анализа — в следующем уроке.

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

Практики разработки Module в этом уроке намеренно нет — курс сфокусирован на Application, и dmtlint рассматривается только для понимания платформы, а не для авторства модулей. Изучите таблицу девяти линтеров из теории и подготовьте письменное сравнение с шестью линтерами pkglint — эта подготовка нужна для практического анализа в следующем уроке.

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

1
2
dmt lint <module-dir> --linter rbac
dmt render <module-path> --output ./rendered

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

Сколько линтеров содержит dmtlint, в отличие от 6 у pkglint?

Разница отражает больший объём типов сущностей и классов ошибок, доступных Module.

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

Почему у Module нужен отдельный линтер rbac, которого нет у pkglint?

Прямое следствие ограничений Application из M5 урока 5.

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

Чем dmt test conversions отличается от обычного helm template тестирования?

У Application нет версионируемых конверсий настроек между релизами.

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

Что делает поле impact: warn в linters-settings.<linter> конфигурации .dmtlint.yaml?

impact управляет тем, блокирует ли находка линтера пайплайн или только предупреждает.

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

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

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

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

Книги

  • Gene Kim, Jez Humble, Patrick Debois, John Willis. The DevOps Handbook. 2nd ed., 2021. ISBN 978-1942788003.

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