Стадия жизненного цикла модуля: General Availability
У модуля есть требования для установки

Как устроен Deckhouse Commander

Компоненты Deckhouse Commander

Схема

У Deckhouse Commander есть внешняя зависимость — база данных PostgreSQL.

Сервер API является центральным компонентом. Данные хранятся в PostgreSQL. Варианты установки Deckhouse Commander с СУБД указаны в разделе «Установка».

Сервер API предоставляет как внешние API — веб-приложения и для внешней интеграции — так и внутренние API для работы с кластерами.

Веб-приложение использует API для управления кластерами и другими сущностями Deckhouse Commander. Через него же доступен переход в веб-интерфейс администрирования прикладного кластера (DKP UI, модуль console): просмотр ресурсов Kubernetes и веб-терминал. Запросы к Kubernetes API прикладного кластера маршрутизируются через Deckhouse Commander от имени той же учётной записи, под которой пользователь вошёл в Deckhouse Commander.

Для управления кластерами используются асинхронные операции — задания. Менеджер кластеров — это сервис, который отслеживает задания и выполняет их. Заданиями могут быть установка кластера, удаление кластера или сверка состояния кластера с заданной конфигурацией.

При создании кластера создаётся задание установки. Затем свободный экземпляр менеджера кластеров берёт задание в работу. То же происходит при обновлении, удалении или сверке конфигурации кластера.

После получения задания менеджер кластеров определяет, с какой версией Deckhouse Kubernetes Platform (DKP) нужно работать, запускает или использует уже запущенный сервер dhctl нужной версии и запускает в нём требуемую операцию. Сервер dhctl однопоточный и выполняет только одну операцию одновременно. Менеджер кластеров автоматически запускает и останавливает серверы dhctl, а также масштабирует количество их реплик в зависимости от количества поступающих заданий. Благодаря этому система адаптируется к текущей нагрузке.

В каждом прикладном кластере работает модуль commander-agent. Deckhouse Commander включает его автоматически. После первичной установки кластера агент открывает обратный TLS-туннель к управляющему кластеру и удерживает его. Пока туннель открыт, Deckhouse Commander не нуждается во входящем сетевом доступе к Kubernetes API прикладного кластера. Через этот туннель идёт трафик к Kubernetes API прикладного кластера: он используется в фазах операций «Проверка» (check) и «Изменение» (converge) для сверки инфраструктурной конфигурации прикладного кластера с целевой и приведения её к этому состоянию (создание, удаление и обновление узлов, обновление компонентов DKP), а также при работе веб-интерфейса администрирования кластера для получения объектов из Kubernetes API прикладного кластера.

Телеметрия кластера передаётся отдельно через тот же HTTPS API Deckhouse Commander, через который агент открывает туннель. Телеметрия включает основные метрики (общее количество ядер, общий объем памяти, количество узлов и общий объем хранилищ), версии DKP и Kubernetes, доступность компонентов DKP.

Через этот же HTTPS API Deckhouse Commander работает механизм конверсии ресурсов: агент запрашивает desired-конфигурацию, применяет её в прикладном кластере и отправляет обратно статус и applied-конфигурацию.

Взаимодействие с API инфраструктурного провайдера выполняется отдельно — из управляющего или прикладного кластера, без использования обратного TLS-туннеля commander-agent.

Прямой SSH к master-узлу (22/TCP) используется при первичной установке, удалении, присоединении и отсоединении прикладного кластера, а также как резервный канал, если commander-agent не может установить или удержать обратный туннель. Сам агент по умолчанию запускается на master-узлах прикладного кластера.

Если включён флаг биллинга, Deckhouse Commander также собирает метрики потребления ресурсов со всех прикладных кластеров и рассчитывает по ним стоимость согласно настроенным тарифам. Эти метрики доставляются в выделенный долговременный Prometheus в управляющем кластере через Prometheus remote write. Remote write использует тот же HTTPS API Deckhouse Commander, через который агент открывает туннель, но это отдельный push-механизм из прикладного кластера, а не трафик внутри обратного TLS-туннеля. По полученным данным Deckhouse Commander отрисовывает дашборды биллинга и выгружает CSV-отчёты о расходах.

Со стороны прикладного кластера интеграцию с биллингом обеспечивает commander-agent:

  • он настраивает remote-write-поток метрик потребления ресурсов;
  • он передаёт в Deckhouse Commander описания групп узлов, классов инстансов облачного провайдера и StorageClass, которые используются в интерфейсе биллинга для привязки вычислительных классов и классов хранилища к реальным объектам кластера;
  • он проставляет на каждом узле служебный лейбл billing.commander.deckhouse.io/name, по которому узел сопоставляется с вычислительным классом и к его потреблению применяется цена из действующего тарифа.

Deckhouse Commander формирует контракт привязок (какие узлы какой лейбл должны иметь) и передаёт его агенту. Агент напрямую патчит объекты Node, добавляя лейбл на каждый узел, принадлежащий привязанной группе узлов.

Размещение компонентов и сетевое взаимодействие

Deckhouse Commander может быть включён в любом кластере DKP. Для прикладных кластеров, которыми он управляет, этот кластер становится управляющим. Рядом с Deckhouse Commander в этом же кластере могут работать другие системные модули Deckhouse. В совместной конфигурации в этом кластере могут работать и пользовательские приложения — на отдельных узлах.

По умолчанию Deckhouse Commander запускается на узлах с ролью commander (лейбл node-role.deckhouse.io/commander), а при их отсутствии — на системных узлах (лейбл node-role.deckhouse.io/system). Чтобы явно указать, на каких узлах запускать Deckhouse Commander, задайте параметр nodeSelector. Если выделенные узлы помечены taint-ом, укажите также tolerations. Компоненты биллинга наследуют эти же настройки.

commander-agent работает в каждом прикладном кластере и по умолчанию запускается на master-узлах. Он держит постоянный обратный TLS-туннель к управляющему кластеру, поэтому в штатном режиме Deckhouse Commander не обращается по входящему соединению к Kubernetes API прикладного кластера. SSH к master-узлу (22/TCP) используется при первичной установке, удалении, присоединении и отсоединении кластера, а также как резервный канал, если обратный туннель недоступен.

Требования к сетевой доступности компонентов

Между управляющим и прикладным кластером требуется сетевая доступность по следующим направлениям:

  • 22/TCP от серверов dhctl ко всем master-узлам прикладных кластеров — для первичной установки, удаления, присоединения и отсоединения кластера, а также как резервный канал, если обратный туннель недоступен.
  • Доступ от серверов dhctl к API облачных провайдеров — для управления инфраструктурными ресурсами прикладных кластеров.
  • 443/TCP от прикладного кластера к управляющему — через ingress на frontend-узлах управляющего кластера. Фактический порт зависит от настроек ингресс-контроллера. Обращения идут по двум доменам:
    • Домен Deckhouse Commander (commander.<publicDomainTemplate>) — commander-agent использует его для открытия обратного TLS-туннеля, телеметрии, механизма конверсии конфигурации прикладных кластеров, а также для billing remote write (Prometheus прикладного кластера отправляет метрики потребления на путь /prometheus/api/v1/write этого же домена). Через обратный туннель Deckhouse Commander получает доступ к Kubernetes API прикладного кластера для фаз операций «Проверка» и «Изменение» и веб-интерфейса администрирования кластера.
    • Домен Dex (dex.<publicDomainTemplate>) — Dex прикладного кластера обращается к нему для OIDC discovery и валидации токенов. Это необходимо для работы DexProvider/commander, через который прикладной кластер доверяет учётным записям управляющего кластера.
  • Доступ к хранилищу образов контейнеров, из которого загружается образ dhctl, — от узлов, где работает менеджер кластеров, потому что он обращается к хранилищу напрямую, и от узлов, где запускаются серверы dhctl, потому что с них загружается образ нужной версии dhctl.

Канал «агент → управляющий кластер» работает только по HTTPS. Работа Deckhouse Commander без HTTPS не поддерживается.

По умолчанию CA-сертификат, которому доверяют прикладные кластеры для этого канала, определяется автоматически по TLS-сертификату веб-интерфейса. Если HTTPS терминируется на внешнем балансировщике, чей сертификат недоступен Deckhouse Commander, укажите в параметре customCA PEM-сертификат CA, которому должны доверять прикладные кластеры.

Требования к качеству сети и таймауты

Deckhouse Commander спроектирован для работы через публичный интернет и устойчив к нестабильным каналам связи. Жёстких требований к латентности нет — все взаимодействия используют retry-логику и persistent-соединения с автоматическим переподключением.

Основные таймауты, влияющие на работу:

Компонент Параметр Значение
SSH (bootstrap, destroy, attach, detach) Connect timeout 10 сек
SSH KeepAlive interval 15 сек
Agent → Deckhouse Commander API (все запросы, включая конверсию ресурсов) HTTP timeout 30 сек
Agent → Deckhouse Commander API Retry при ошибке до 3 попыток
Agent: интервал синхронизации ресурсов Converge interval 30 сек
Обратный туннель (AMPG) TCP KeepAlive включён (OS default)
Обратный туннель (AMPG): ожидание backend-соединения Acquire timeout 60 сек
Dex: время жизни ID-токена idTokenTTL 10 мин (настраивается)
Dex: время жизни auth request authRequests 10 мин
Prometheus remote write Send timeout 30 сек (дефолт Prometheus)

При потере связи между прикладным и управляющим кластерами:

  • Обратный TLS-туннель (yamux) автоматически переподключается при разрыве.
  • Агент продолжает попытки связи с Deckhouse Commander API с интервалом 30 секунд.
  • Prometheus буферизует метрики remote write и дошлёт их после восстановления связи.

Синхронизация конфигурации и ресурсов прикладного кластера

В Deckhouse Commander каждый прикладной кластер синхронизируется по двум независимым каналам — у инфраструктурной конфигурации и у ресурсов Kubernetes свои исполнители и свои источники истины. Это два разных процесса, хотя оба отображаются на странице кластера.

Конфигурация инфраструктуры — операции «Изменение» и «Проверка»

К конфигурации инфраструктуры относятся вкладки в группе «Инфраструктура» на странице кластера: «Kubernetes», «Размещение», «Скрипт после установки» и «Параметры SSH». Эту конфигурацию применяет и сверяет управляющая часть Deckhouse Commander непосредственно из управляющего кластера:

  • «Изменение» приводит инфраструктуру кластера — узлы, control plane, начальную конфигурацию DKP, ресурсы провайдера — к целевому состоянию. Запускается при создании кластера и при сохранении правок на инфраструктурных вкладках в веб-интерфейсе. В режиме применения изменений «Авто» (описано ниже) запускается автоматически, в режиме «Вручную» — через запрос на изменения с подтверждением.
  • «Проверка» сравнивает желаемое и фактическое состояние инфраструктуры, не внося изменений. Запускается автоматически с заданной периодичностью («Интервал сверки» в параметрах рабочего пространства или кластера).

Если операция завершилась ошибкой, повторите её вручную — кнопкой «Повторить попытку» на странице кластера.

Режим применения изменений и интервал сверки задаются в параметрах рабочего пространства (вкладка «Параметры» → «Настройки») и могут быть переопределены индивидуально для каждого кластера.

Эти настройки не управляют синхронизацией групп ресурсов Kubernetes. При переключении режима применения изменений с «Авто» на «Вручную» commander-agent по-прежнему синхронизирует группы ресурсов в прикладном кластере согласно их режимам контроля.

Группы ресурсов Kubernetes — синхронизация агентом

В группе «Kubernetes» на странице кластера расположены нумерованные вкладки — группы ресурсов Kubernetes. Каждая группа — это набор YAML-манифестов, которые commander-agent применяет в прикладном кластере. К операциям «Изменение» и «Проверка» эти группы отношения не имеют: их синхронизирует отдельный цикл агента, независимо от того, идут ли в этот момент инфраструктурные операции.

У каждой группы есть один из режимов синхронизации, который задаётся в шаблоне кластера и переключается на странице кластера:

  • «Форсировать создание» — агент применяет манифесты группы в каждом цикле сверки и восстанавливает изменённые или удалённые ресурсы;
  • «Создать при установке» — ресурсы группы создаются только при установке кластера. Агент не контролирует их в течение жизненного цикла кластера; последующие правки в кластере не откатываются;
  • «Игнорируются» — контроль группы выключен в Deckhouse Commander: ранее применённые ресурсы остаются в прикладном кластере, но агент перестаёт их синхронизировать. После этого ресурсы становятся обычными объектами Kubernetes — их можно править и удалять вручную.

Проблемы с commander-agent (потеря связи, ошибки применения манифестов) отражаются на странице кластера: в общем статусе кластера, в бейдже синхронизации рядом с заголовком, на вкладке «Kubernetes» (детализация по группам и манифестам). Подробное описание статусов кластера — в разделе «Состояние кластера» руководства пользователя.

Защита контролируемых ресурсов

Чтобы изменения в обход Deckhouse Commander не расходились с целевой конфигурацией, ресурсы под активной синхронизацией защищены от внешних изменений. Под защиту попадают ресурсы из групп в режиме «Форсировать создание» и собственные служебные ресурсы Deckhouse Commander (DexProvider, биллинг, RBAC, проекты, секреты агента). Попытка отредактировать или удалить такой ресурс через d8 k отклоняется API-сервером прикладного кластера. Чтобы вывести группу из-под защиты, переключите её в режим «Игнорируются» — после этого её ресурсы становятся обычными объектами Kubernetes.

Часть служебных ресурсов Deckhouse Commander (RBAC, проекты, конфигурации Dex и биллинга) защищена от потери контроля строже: при выводе соответствующей группы из-под управления или временной недоступности её источника такие ресурсы удаляются, а не остаются в кластере без сопровождения Deckhouse Commander.

Включение и выключение возможностей Deckhouse Commander

Отдельные возможности интерфейса Deckhouse Commander включаются и выключаются через ModuleConfig модуля commander, поле spec.settings.featureFlags. Правки выполняются в управляющем кластере (где установлен Deckhouse Commander).

Биллинг и управление расходами — billingEnabled

Параметр Описание
По умолчанию Выключен (false), пока явно не задано billingEnabled: true
Включение Компоненты биллинга разворачиваются, в интерфейсе появляется раздел «Биллинг»
Выключение Задайте billingEnabled: false

Включение:

d8 k patch mc commander --type merge --patch '{"spec":{"settings":{"featureFlags":{"billingEnabled":true}}}}'

После включения раздел «Биллинг» становится доступен в верхней панели навигации на начальном экране со списком рабочих пространств или по URL {АДРЕС_COMMANDER}/billing/.

Помимо этого, компонент commander-agent в каждом прикладном кластере начинает:

  • настраивать передачу метрик потребления ресурсов (CPU, память, хранилище) в Prometheus управляющего кластера — для этого в прикладном кластере создаётся ресурс PrometheusRemoteWrite. Подробнее — в разделе Как Deckhouse Commander считает расходы;
  • передавать в Deckhouse Commander описания групп узлов, классов инстансов облачного провайдера и классов хранилища Kubernetes — эти данные используются в интерфейсе биллинга для привязки вычислительных классов и классов хранилища к реальным объектам кластера;
  • добавлять на каждый узел служебный лейбл billing.commander.deckhouse.io/name со значением имени вычислительного класса, к которому узел относится. По этому лейблу Deckhouse Commander сопоставляет узел с вычислительным классом и применяет к его потреблению цену, заданную в действующем тарифе. Лейбл восстанавливается автоматически при пересоздании узлов.

Deckhouse Commander формирует контракт привязок (группа узлов → значение лейбла) и передаёт его агенту. Агент напрямую патчит объекты Node, добавляя лейбл на каждый узел привязанной группы.

Метрики потребления хранятся в отдельном Prometheus биллинга (billing-prometheus) в управляющем кластере. В него попадают только данные, необходимые для расчёта стоимости: потребление CPU и памяти контейнерами, запрошенные ресурсы подов и PVC, использование томов, фазы подов, связи контроллеров с подами, лейблы неймспейсов, подов и узлов, а также информация о PVC.

Prometheus прикладного кластера отправляет эти данные в управляющий кластер по протоколу Prometheus remote write через HTTPS API Deckhouse Commander. Это отдельный HTTP(S)-запрос Prometheus, commander-agent не передаёт метрики сам. Агент настраивает ресурс PrometheusRemoteWrite и передаёт Prometheus параметры подключения.

Метаданные биллинга хранятся в базе данных Deckhouse Commander. К ним относятся тарифы, вычислительные классы, классы хранилища, привязки ресурсов, расписания отчётов, а также лицевые счета с историей операций по ним. Сформированные отчёты используют отдельное хранилище billing-reports.

При включённом биллинге каждое рабочее пространство должно быть привязано к лицевому счёту: пока на счёте есть средства, привязанные к нему рабочие пространства работают как обычно, а при неположительном балансе в них блокируется запуск установки новых кластеров (уже работающие кластеры продолжают работу). Для существующих рабочих пространств счета автоматически не создаются — после обновления администратор биллинга видит на вкладке «Лицевые счета» список непривязанных рабочих пространств и привязывает их вручную. Порядок работы описан в разделе Лицевые счета документации по биллингу.

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

Если раздел не отображается, проверьте наличие доступа. Подробнее — в разделе Управление доступом в документации по биллингу.

Отключение:

d8 k patch mc commander --type merge --patch '{"spec":{"settings":{"featureFlags":{"billingEnabled":false}}}}'

После отключения при необходимости удалите вручную оставшиеся ресурсы:

d8 k -n d8-commander delete pvc -l app=billing-reports
d8 k -n d8-commander delete pvc -l app=billing-prometheus

Пользовательская документация: Биллинг и управление расходами.

Проекты — projectsEnabled

Параметр Описание
По умолчанию Выключен (false), пока явно не задано projectsEnabled: true
Включение В интерфейсе доступен раздел «Проекты»
Выключение Задайте projectsEnabled: false

Включение:

d8 k patch mc commander --type merge --patch '{"spec":{"settings":{"featureFlags":{"projectsEnabled":true}}}}'

Отключение:

d8 k patch mc commander --type merge --patch '{"spec":{"settings":{"featureFlags":{"projectsEnabled":false}}}}'

Пользовательская документация: Руководство пользователя — Проекты.

Срок хранения записей аудита — auditsRetentionDays

Параметр Описание
По умолчанию Выключено — параметр не задан; записи аудита в базе данных Deckhouse Commander не удаляются автоматически
При установке значения Ежедневно CronJob удаляет записи аудита старше указанного числа дней
Допустимое значение Число дней, записанное только цифрами, например 30, 90 или 365

Включение автоматической очистки:

d8 k patch mc commander --type merge --patch '{"spec":{"settings":{"featureFlags":{"auditsRetentionDays":90}}}}'

Deckhouse Commander хранит историю изменений сущностей в PostgreSQL бессрочно. Если задан auditsRetentionDays, CronJob audits-cleaner в пространстве имён d8-commander запускается раз в сутки и удаляет записи старше указанного числа дней. Например, при auditsRetentionDays: 30 удаляются записи возрастом 31 день и больше; записи ровно 30-дневной давности сохраняются.

Чтобы отключить автоматическую очистку, удалите auditsRetentionDays из featureFlags в ModuleConfig модуля commander.

Пользовательская документация: Руководство пользователя — Аудит.

Срок хранения архива — archiveRetentionDays

Параметр Описание
По умолчанию Выключено — параметр не задан; архивные кластеры и шаблоны кластеров не удаляются автоматически
При установке значения Ежедневно CronJob безвозвратно удаляет архивные кластеры и шаблоны кластеров старше указанного числа дней
Допустимое значение Число дней, записанное только цифрами, например 30, 90 или 365

Включение автоматической очистки:

d8 k patch mc commander --type merge --patch '{"spec":{"settings":{"featureFlags":{"archiveRetentionDays":90}}}}'

Deckhouse Commander хранит архивные кластеры и шаблоны кластеров, пока администратор не восстановит или не удалит их безвозвратно. Если задан archiveRetentionDays, CronJob archives-cleaner в пространстве имён d8-commander запускается раз в сутки и безвозвратно удаляет архивные кластеры и шаблоны кластеров старше указанного числа дней. Например, при archiveRetentionDays: 30 удаляются архивы возрастом 31 день и больше; архивы ровно 30-дневной давности сохраняются.

Шаблон кластера, на который ещё ссылаются кластеры (в том числе архивные), пропускается, пока эти кластеры не будут удалены. Каталоги инвентаря этой задачей не очищаются. Безвозвратное удаление не удаляет записи аудита — срок хранения аудита задаётся отдельно параметром auditsRetentionDays.

Чтобы отключить автоматическую очистку, удалите archiveRetentionDays из featureFlags в ModuleConfig модуля commander.

Согласование изменений кластеров

Согласование изменений добавляет этап бизнес-согласования перед операциями с кластерами: вместо запуска операции Deckhouse Commander создаёт запрос на согласование и ждёт решения согласующего.

Согласование включается в каждом рабочем пространстве отдельно и действует на все его кластеры. Сейчас оно охватывает только установку кластера и применение изменений его конфигурации. Удаление и отсоединение выполняются сразу. В будущих релизах согласование планируется распространить на все операции с кластерами.

Подтверждение деструктивных изменений инфраструктуры — отдельный механизм, он продолжает работать независимо. Одобрить запросы на согласование через API интеграции нельзя: попытка возвращает 409 с кодом approval_flow_not_supported.

Включение согласования и назначение согласующих

Настройки согласования находятся в рабочем пространстве: откройте его, нажмите значок шестерёнки в верхней панели, выберите «Параметры» и перейдите к разделу «Согласование создания кластеров». Раздел виден при праве get на workspacerolebindings и доступен для изменения при праве update.

  1. Включите переключатель «Требовать согласование создания кластеров».
  2. В поле «Согласующие» добавьте пользователей или группы. Субъекты вводятся с префиксами user: и group:, например user:admin@example.com или group:web. Для включения согласования нужен как минимум один согласующий.
  3. Сохраните настройки.

Deckhouse Commander автоматически выдаёт выбранным субъектам роль рабочего пространства cluster-change-approver через назначение autogenerated-cluster-change-approvers. Любой участник назначенной группы может увидеть запрос, согласовать его или отклонить.

В поле показываются и субъекты, получившие право другой ролью рабочего пространства: отсюда их не удалить, право снимается в управлении доступом. Модель прав описана в разделе «Согласование изменений кластеров», пользовательский сценарий — в разделе «Согласование изменений».

Эксплуатация согласования

Замена согласующего. Если согласующий недоступен — заблокирован во внешнем IdP, находится в отпуске, — ожидающие запросы остаются в ожидании. Измените поле «Согласующие» рабочего пространства и добавьте другого пользователя или группу: изменение действует и на уже ожидающие запросы, повторно отправлять их не нужно.

Выключение согласования. Выключение прекращает создание новых запросов. Уже отправленные остаются в ожидании: обработайте их до выключения либо запустите операцию заново — устаревший запрос снимется автоматически.

Финансовая блокировка. Пока рабочее пространство заблокировано по финансам, запрос на установку кластера согласовать нельзя — установка недоступна, пока не пополнен баланс. На запросы о применении изменений конфигурации это не влияет.

Аудит. Отправка запроса, его одобрение, отклонение и отзыв фиксируются в истории изменений того кластера, к которому относится запрос, вместе со статусом запроса, инициатором и причиной отклонения. Доступ к этим записям даёт право clusters/audit.

Аутентификация в прикладных кластерах через DexProvider

Каждый кластер, подключённый к Deckhouse Commander, автоматически доверяет пользователям, аутентифицированным Dex управляющего кластера. После входа в Deckhouse Commander пользователь может перейти в веб-интерфейс администрирования прикладного кластера (DKP UI, модуль console) без повторного входа.

Заводить отдельную учётную запись в каждом прикладном кластере для этого не требуется.

Доверительная связка автоматически выстраивается через пару ресурсов, которыми управляет Deckhouse Commander:

  • В прикладном кластере создаётся DexProvider с именем commander и типом OIDC. В качестве эмитента (issuer) указан адрес Dex управляющего кластера. В поле сертификатов передан корневой сертификат управляющего кластера, чтобы TLS к Dex проходил без правки системного набора доверенных CA. Запрашиваются скоупы openid, profile, email и groups. Этого одного DexProvider достаточно, чтобы прикладной кластер опирался на учётные записи управляющего кластера; при необходимости рядом можно держать другие, «локальные», DexProvider-ы.
  • В управляющем кластере создаётся парный DexClient с именем commander-agent-<id> и Secret с его OIDC-клиентским секретом. В DexClient прописан redirect-URI на Dex прикладного кластера, поэтому Dex управляющего кластера корректно принимает колбэки после входа.

Оба ресурса создаются при первичной установке или подключении кластера и удаляются при его отключении — ручных шагов не требуется. Если ресурс был изменён или удалён вручную, следующая сверка восстановит его в исходном виде.

Как проходит вход

Когда пользователь открывает веб-интерфейс администрирования прикладного кластера из Deckhouse Commander, браузер попадает в Dex прикладного кластера. Dex прикладного кластера использует провайдер commander и перенаправляет браузер в Dex управляющего кластера.

Dex управляющего кластера аутентифицирует пользователя и возвращает браузер обратно в Dex прикладного кластера по redirect-URI, который относится к этому прикладному кластеру. После этого Dex прикладного кластера завершает вход для веб-интерфейса администрирования кластера. Если у пользователя уже есть активная сессия в Dex управляющего кластера после входа в Deckhouse Commander, повторно вводить логин и пароль обычно не требуется.

Параметр allowedUserGroups модуля commander определяет только то, кто может войти в веб-интерфейс Deckhouse Commander. На права внутри самого Deckhouse Commander этот параметр не влияет — роли назначаются отдельно. Подробности — в разделе «Управление доступом».

Не редактируйте, не отключайте и не удаляйте вручную автоматически создаваемый DexProvider/commander в прикладном кластере, а также парный DexClient и его Secret в управляющем кластере. Удаление этих ресурсов ломает все входы в прикладной кластер через Deckhouse Commander. Следующая сверка воссоздаст их в исходном виде, поэтому ручные правки в любом случае будут потеряны. Если нужно добавить свою настройку аутентификации для прикладного кластера, разместите рядом с управляемым ресурсом дополнительный DexProvider. Управляемый Deckhouse Commander провайдер задаёт минимум, необходимый для работы Deckhouse Commander, и не является эксклюзивным.

Миграция токенов доступа в сервисные аккаунты

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

Каждый токен становится отдельным аккаунтом с одним ключом:

Токен доступа Созданный для него аккаунт Начальная роль
Токен рабочего пространства, только чтение Сервисный аккаунт того же рабочего пространства Сохранённый доступ на чтение в этом РП
Токен рабочего пространства, чтение и изменение Сервисный аккаунт того же рабочего пространства Сохранённый доступ на чтение и изменение в этом РП
Глобальный токен, только чтение Глобальный сервисный аккаунт Сохранённый глобальный доступ на чтение
Глобальный токен, чтение и изменение Глобальный сервисный аккаунт Сохранённый глобальный доступ на чтение и изменение
Истёкший или архивный токен Аккаунт соответствующего вида Нет

Мигрированные аккаунты называются migrated-token-<ЧАСТЬ_ID_ТОКЕНА>, где <ЧАСТЬ_ID_ТОКЕНА> — начало идентификатора токена. Этот префикс зарезервирован: новым аккаунтам нельзя задать имя, начинающееся с migrated-token-. Ключ сохраняет идентификатор, дату истечения, время последнего использования и состояние прежнего токена: архивный токен становится отозванным ключом, а истёкший — ключом с истёкшим сроком действия. Ключ создаётся для каждого токена, а начальная роль назначается только тем токенам, которые оставались активными, поэтому истёкшие и архивные токены мигрируют без прав.

Начальные роли создаёт сама миграция, они называются migrated-auth-token-viewer и migrated-auth-token-editor. Роли помечены лейблами commander.deckhouse.io/owned-by: commander и commander.deckhouse.io/generated-by: service-account-migration и в точности воспроизводят прежние возможности токена:

  • глобальная роль охватывает ресурсы globalroles, globalrolebindings, workspaces, workspaceroles, workspacerolebindings и billingreports;
  • роль рабочего пространства охватывает ресурсы clusters, clustertemplates, catalogs, records, registries, projects и projectrolebindings;
  • вариант viewer даёт verb get, вариант editor — get, create, update и delete.

Правил Kubernetes в этих ролях нет, поэтому ClusterRole и ClusterRoleBinding для них в кластерах не создаются. История изменений прежних токенов переносится: совершённые действия и согласования изменений кластеров остаются связанными с мигрированным аккаунтом.

После обновления проверьте результат на вкладке «Сервисные аккаунты» раздела «Пользователи и права»:

  1. Посмотрите, какие аккаунты созданы и что разрешают их роли сохранённого доступа. Эти роли повторяют права прежних токенов, которые обычно шире, чем нужно конкретной интеграции.
  2. Замените их своими ролями, выдав каждому аккаунту только те ресурсы и verbs, которые использует его интеграция, и снимите назначение роли сохранённого доступа.
  3. Удалите аккаунты, чьи ключи истекли или отозваны и больше не нужны.

Имя аккаунта изменить нельзя, поэтому чтобы заменить техническое имя migrated-token- на осмысленное, создайте новый аккаунт, выпустите для него ключ, переключите интеграцию на этот ключ и удалите мигрированный аккаунт.

Ключ с широкими правами — не отдельный вид учётных данных: это обычный ключ глобального сервисного аккаунта, которому назначена широкая глобальная роль. У такого ключа нет особого статуса, он не ограничен единственным экземпляром и не обходит проверки прав — его ограничивают только роли его аккаунта. Обращайтесь с ним соответственно: назначайте роль не шире, чем нужно автоматизации, держите количество таких аккаунтов минимальным и отзывайте ключ сразу, как только он выходит из обращения.

Шифрование данных

Deckhouse Commander шифрует чувствительные данные в базе данных. Для шифрования используются ключи из секрета commander-envs, которые генерируются автоматически при включении модуля.

Крайне важно сохранить ключи в надёжное место, чтобы иметь возможность восстановить базу данных в случае каких-либо проблем. При отсутствии ключей восстановить данные будет невозможно!

$ d8 k -n d8-commander get secret commander-envs -oyaml
apiVersion: v1
data:
  ACTIVE_RECORD_ENCRYPTION_DETERMINISTIC_KEY: YVBBNVh5QUxoZjc1Tk5uTXphc3BXN2FrVGZacDBsUFk=
  ACTIVE_RECORD_ENCRYPTION_KEY_DERIVATION_SALT: eEVZMGR0NlRaY0FNZzUySzdPODR3WXpranZiQTYySHo=
  ACTIVE_RECORD_ENCRYPTION_PRIMARY_KEY: RUdZOFdodWxVT1hpeHlib2Q3Wld3TUlMNjhSOW81a0M=
kind: Secret
metadata:
...
  name: commander-envs
  namespace: d8-commander
type: Opaque

Сбор логов истории изменений

В Deckhouse Commander, начиная с версии 1.9, события из «Истории изменений» направляются в стандартный вывод и помечаются тегом ["audit"]. Сбор и отправку таких логов можно настроить при помощи модуля log-shipper

Пример логов:

{"level":"INFO","time":"2025-06-18 14:22:15 +0300","request_id":"ea09d409dc3c95dcf658fc2c2838084b","pid":19,"tags":["audit"],"auditable_type":"ClusterSettings","auditable_id":"8a0041ef-6c30-48bc-b3ca-e9db3e22be47","action":"create","user_type":"User","remote_address":"82.150.57.81","request_uuid":"ea09d409dc3c95dcf658fc2c2838084b","workspace_slug":"xcjtd","user_name":"admin@company.my","audited_changes":{"cluster_manager":{"sync":{"mode":"auto"},"check_interval":1}}}
{"level":"INFO","time":"2025-06-18 14:22:15 +0300","request_id":"ea09d409dc3c95dcf658fc2c2838084b","pid":19,"tags":["audit"],"auditable_type":"Cluster","auditable_id":"056f7fe5-7d22-4a76-b5e2-f225c0a99613","action":"create","user_type":"User","remote_address":"82.150.57.81","request_uuid":"ea09d409dc3c95dcf658fc2c2838084b","workspace_slug":"xcjtd","user_name":"admin@company.my","audited_changes":{"name":"mycluster","archived_at":null}}
{"level":"INFO","time":"2025-06-18 14:23:57 +0300","request_id":"a1eaf50bbc87a8cca4cd17d8be8fffdb","pid":12,"tags":["audit"],"auditable_type":"ClusterSettings","auditable_id":"707c46b1-b2c8-4fab-9392-8216a2058219","action":"create","user_type":"WorkspaceServiceAccount","remote_address":"238.106.231.86","request_uuid":"a1eaf50bbc87a8cca4cd17d8be8fffdb","workspace_slug":"bfqcc","user_name":"ci-bot","audited_changes":{"cluster_manager":{"sync":{"mode":"auto"},"check_interval":1}}}
{"level":"INFO","time":"2025-06-18 14:23:57 +0300","request_id":"a1eaf50bbc87a8cca4cd17d8be8fffdb","pid":12,"tags":["audit"],"auditable_type":"Cluster","auditable_id":"42d432aa-8250-4ef0-b260-51639e1445d0","action":"create","user_type":"WorkspaceServiceAccount","remote_address":"238.106.231.86","request_uuid":"a1eaf50bbc87a8cca4cd17d8be8fffdb","workspace_slug":"bfqcc","user_name":"ci-bot","audited_changes":{"name":"15731486914-1-con-1-30","archived_at":null}}
{"level":"INFO","time":"2025-06-18 14:28:56 +0300","request_id":"069566a46c004e53b686189587d484a9","pid":19,"tags":["audit"],"auditable_type":"ClusterSettings","auditable_id":"402a4d4d-5c14-4466-a1f3-3d990d7cf35a","action":"create","user_type":"User","remote_address":"30.231.184.26","request_uuid":"069566a46c004e53b686189587d484a9","workspace_slug":"xcjtd","user_name":"user@company.my","audited_changes":{"cluster_manager":{"sync":{"mode":"auto"},"check_interval":1}}}
{"level":"INFO","time":"2025-06-18 14:28:56 +0300","request_id":"069566a46c004e53b686189587d484a9","pid":19,"tags":["audit"],"auditable_type":"Cluster","auditable_id":"9ee687d4-18fe-423c-bbaa-e8e46ea47e67","action":"create","user_type":"User","remote_address":"30.231.184.26","request_uuid":"069566a46c004e53b686189587d484a9","workspace_slug":"xcjtd","user_name":"user@company.my","audited_changes":{"name":"mycluster2","archived_at":null}}
{"level":"INFO","time":"2025-06-18 14:29:06 +0300","request_id":"d29b248fbce414db8b71f821a3b1886e","pid":12,"tags":["audit"],"auditable_type":"Cluster","auditable_id":"e0f3c3de-2129-4b75-b927-72a8eb26902b","action":"update","user_type":"User","remote_address":"30.231.184.26","request_uuid":"d29b248fbce414db8b71f821a3b1886e","workspace_slug":"xcjtd","user_name":"user@company.my","audited_changes":{"archived_at":[null,"2025-06-18T14:29:05.943+03:00"]}}

Пример конфигурации:

apiVersion: deckhouse.io/v1alpha2
kind: ClusterLoggingConfig
metadata:
  name: commander-audit-logs
spec:
  destinationRefs:
  - loki-example
  kubernetesPods:
    labelSelector:
      matchLabels:
        app: backend
    namespaceSelector:
      labelSelector:
        matchLabels:
          kubernetes.io/metadata.name: d8-commander
  labelFilter:
  - field: message
    operator: Regex
    values:
    - .*\[\"audit\"\].*
  type: KubernetesPods
---
apiVersion: deckhouse.io/v1alpha1
kind: ClusterLogDestination
metadata:
  name: loki-example
spec:
  type: Loki
  loki:
    endpoint: http://loki-example.loki.svc:3100

Более подробную информацию по настройке смотрите в документации модуля log-shipper.

Изменение класса хранилища для БД (StorageClass)

Эта инструкция нужна только в том случае, если для СУБД используется модуль operator-postgres. На это указывает режим подключения к БД Internal в ModuleConfig/commander.

apiVersion: deckhouse.io/v1alpha1
kind: ModuleConfig
metadata:
  name: commander
spec:
  enabled: true
  version: 1
  settings:
    postgres:
      mode: Internal
    # Остальные настройки модуля.

Вариант 1 (предпочтительный)

  1. Выполняем резервное копирование экземпляра БД

    d8 k -n d8-commander exec -t commander-postgres-0 -- su - postgres -c "pg_dump -Fc -b -v -d commander" > commander.dump
  2. Изменяем storageClass в настройках модуля, заменив <NEW_STORAGECLASS_NAME> на название необходимого класса хранения

    Список доступных классов хранения можно узнать при помощи команды d8 k get storageclasses

    d8 k patch moduleconfig commander --type=merge -p '{"spec":{"settings":{"postgres":{"internal":{"storageClass":"<NEW_STORAGECLASS_NAME>"}}}}}'
    
    moduleconfig.deckhouse.io/commander patched

    Дожидаемся, пока очередь deckhouse окажется пустой

    d8 system queue main
    
    Queue 'main': length 0, status: 'waiting for task 5s'

    Проверяем логи оператора postgres на отсутствие ошибок

    d8 k -n d8-operator-postgres logs deployments/operator-postgres
    
    {"cluster-name":"d8-commander/commander-postgres","level":"info","msg":"cluster has been updated","pkg":"controller","time":"2024-05-19T20:36:22Z","worker":0}
  3. Увеличиваем количество реплик БД PostgreSQL (опционально)

    Этот шаг необходимо пропустить, если в кластере активен режим HighAvailability и PostgreSQL имеет 2 реплики

    d8 k -n d8-commander patch postgresqls.acid.zalan.do commander-postgres --type=merge -p '{"spec":{"numberOfInstances":2}}'
    
    postgresql.acid.zalan.do/commander-postgres patched

    Проверяем логи оператора и экземпляра postgres

    d8 k -n d8-operator-postgres logs deployments/operator-postgres
    
    {"cluster-name":"d8-commander/commander-postgres","level":"info","msg":"cluster has been updated","pkg":"controller","time":"2024-05-19T20:36:22Z","worker":0}
    d8 k -n d8-commander logs commander-postgres-1
    
    2024-05-19 20:38:15,648 INFO: no action. I am (commander-postgres-1), a secondary, and following a leader (commander-postgres-0)
  4. Выполняем переключение мастера

    d8 k -n d8-commander exec -it commander-postgres-0 -- patronictl failover
    
    Current cluster topology
    + Cluster: commander-postgres --------+---------+---------+----+-----------+
    | Member               | Host         | Role    | State   | TL | Lag in MB |
    +----------------------+--------------+---------+---------+----+-----------+
    | commander-postgres-0 | 10.111.3.167 | Leader  | running |  5 |           |
    | commander-postgres-1 | 10.111.2.239 | Replica | running |  5 |         0 |
    +----------------------+--------------+---------+---------+----+-----------+
    Candidate ['commander-postgres-1'] []: commander-postgres-1
    Are you sure you want to failover cluster commander-postgres, demoting current leader commander-postgres-0? [y/N]: y
    2024-05-19 20:40:52.63041 Successfully failed over to "commander-postgres-1"
    + Cluster: commander-postgres --------+---------+---------+----+-----------+
    | Member               | Host         | Role    | State   | TL | Lag in MB |
    +----------------------+--------------+---------+---------+----+-----------+
    | commander-postgres-0 | 10.111.3.167 | Replica | stopped |    |   unknown |
    | commander-postgres-1 | 10.111.2.239 | Leader  | running |  5 |           |
    +----------------------+--------------+---------+---------+----+-----------+

    Убеждаемся, что оба экземпляра БД находятся в состоянии running

    d8 k -n d8-commander exec -t commander-postgres-0 -- patronictl list
    + Cluster: commander-postgres --------+---------+---------+----+-----------+
    | Member               | Host         | Role    | State   | TL | Lag in MB |
    +----------------------+--------------+---------+---------+----+-----------+
    | commander-postgres-0 | 10.111.3.167 | Replica | running |  6 |         0 |
    | commander-postgres-1 | 10.111.2.239 | Leader  | running |  6 |           |
    +----------------------+--------------+---------+---------+----+-----------+

    Проверяем, что диск новой реплики БД создался с необходимым storageClass

    d8 k -n d8-commander get pvc --selector application=spilo
    NAME                          STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
    pgdata-commander-postgres-0   Bound    pvc-fd80fde4-d0e2-4b5f-9e3a-eac998191f11   2Gi        RWO            network-hdd    36h
    pgdata-commander-postgres-1   Bound    pvc-7af2f442-3097-4fe3-a795-5ad18bb11351   2Gi        RWO            network-ssd    2m54s
  5. Удаляем диск и под первого экземпляра

    d8 k -n d8-commander delete pvc pgdata-commander-postgres-0 --wait=false
    d8 k -n d8-commander delete po commander-postgres-0

    Проверяем логи

    d8 k -n d8-commander logs commander-postgres-0
    
    2024-05-19 20:43:33,293 INFO: Lock owner: commander-postgres-1; I am commander-postgres-0
    2024-05-19 20:43:33,293 INFO: establishing a new patroni connection to the postgres cluster
    2024-05-19 20:43:33,357 INFO: no action. I am (commander-postgres-0), a secondary, and following a leader (commander-postgres-1)

    Проверяем, что диск создался с правильным storageClass

    d8 k -n d8-commander get pvc
    NAME                          STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
    pgdata-commander-postgres-0   Bound    pvc-fd80fde4-d0e2-4b5f-9e3a-eac998191f11   2Gi        RWO            network-ssd    2m6s
    pgdata-commander-postgres-1   Bound    pvc-7af2f442-3097-4fe3-a795-5ad18bb11351   2Gi        RWO            network-ssd    7m11s
  6. Выполняем обратное переключение мастера

    d8 k -n d8-commander exec -it commander-postgres-0  -- patronictl failover
    
    Current cluster topology
    + Cluster: commander-postgres --------+---------+---------+----+-----------+
    | Member               | Host         | Role    | State   | TL | Lag in MB |
    +----------------------+--------------+---------+---------+----+-----------+
    | commander-postgres-0 | 10.111.3.189 | Replica | running |  6 |         0 |
    | commander-postgres-1 | 10.111.2.239 | Leader  | running |  6 |           |
    +----------------------+--------------+---------+---------+----+-----------+
    Candidate ['commander-postgres-0'] []: commander-postgres-0
    Are you sure you want to failover cluster commander-postgres, demoting current leader commander-postgres-1? [y/N]: y
    2024-05-19 20:46:11.69855 Successfully failed over to "commander-postgres-0"
    + Cluster: commander-postgres --------+---------+---------+----+-----------+
    | Member               | Host         | Role    | State   | TL | Lag in MB |
    +----------------------+--------------+---------+---------+----+-----------+
    | commander-postgres-0 | 10.111.3.189 | Leader  | running |  6 |           |
    | commander-postgres-1 | 10.111.2.239 | Replica | stopped |    |   unknown |
    +----------------------+--------------+---------+---------+----+-----------+

    Убеждаемся, что оба экземпляра БД находятся в состоянии running

    d8 k -n d8-commander exec -t commander-postgres-0 -- patronictl list
    + Cluster: commander-postgres --------+---------+---------+----+-----------+
    | Member               | Host         | Role    | State   | TL | Lag in MB |
    +----------------------+--------------+---------+---------+----+-----------+
    | commander-postgres-0 | 10.111.3.189 | Leader  | running |  6 |         0 |
    | commander-postgres-1 | 10.111.2.239 | Replica | running |  6 |           |
    +----------------------+--------------+---------+---------+----+-----------+
  7. Уменьшаем количество реплик БД PostgreSQL (опционально)

    Этот шаг необходимо пропустить, если в кластере активен режим HighAvailability и PostgreSQL имеет 2 реплики

    d8 k -n d8-commander patch postgresqls.acid.zalan.do commander-postgres --type=merge -p '{"spec":{"numberOfInstances":1}}'
    
    postgresql.acid.zalan.do/commander-postgres patched

    Проверяем логи оператора

    d8 k -n d8-operator-postgres logs deployments/operator-postgres
    
    {"cluster-name":"d8-commander/commander-postgres","level":"info","msg":"cluster has been updated","pkg":"controller","time":"2024-05-19T20:50:22Z","worker":0}
  8. Удаляем диск и под первого экземпляра (если в кластере активен режим HighAvailability и PostgreSQL имеет 2 реплики)

    Этот шаг необходимо пропустить, если в кластере не используется режим HighAvailability

    d8 k -n d8-commander delete pvc pgdata-commander-postgres-1 --wait=false
    d8 k -n d8-commander delete po commander-postgres-1

    Проверяем логи

    d8 k -n d8-commander logs commander-postgres-1
    
    2024-05-19 20:53:33,293 INFO: Lock owner: commander-postgres-0; I am commander-postgres-1
    2024-05-19 20:53:33,293 INFO: establishing a new patroni connection to the postgres cluster
    2024-05-19 20:53:33,357 INFO: no action. I am (commander-postgres-1), a secondary, and following a leader (commander-postgres-0)

    Проверяем, что диск создался с правильным storageClass

    d8 k -n d8-commander get pvc
    NAME                          STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
    pgdata-commander-postgres-0   Bound    pvc-fd80fde4-d0e2-4b5f-9e3a-eac998191f11   2Gi        RWO            network-ssd    7m6s
    pgdata-commander-postgres-1   Bound    pvc-7af2f442-3097-4fe3-a795-5ad18bb11351   2Gi        RWO            network-ssd    1m11s

    Убеждаемся, что оба экземпляра БД находятся в состоянии running

    d8 k -n d8-commander exec -t commander-postgres-0 -- patronictl list
    + Cluster: commander-postgres --------+---------+---------+----+-----------+
    | Member               | Host         | Role    | State   | TL | Lag in MB |
    +----------------------+--------------+---------+---------+----+-----------+
    | commander-postgres-0 | 10.111.3.189 | Leader  | running |  6 |         0 |
    | commander-postgres-1 | 10.111.2.239 | Replica | running |  6 |           |
    +----------------------+--------------+---------+---------+----+-----------+
  • Удаляем неиспользуемый диск, оставшийся от временной реплики БД (если режим HighAvailability не используется)

    Этот шаг необходимо пропустить, если в кластере активен режим HighAvailability и PostgreSQL имеет 2 реплики

    d8 k -n d8-commander delete pvc pgdata-commander-postgres-1
    
    persistentvolumeclaim "pgdata-commander-postgres-1" deleted

Вариант 2

  1. Выполняем резервное копирование экземпляра БД

    d8 k -n d8-commander exec -t commander-postgres-0 -- su - postgres -c "pg_dump -Fc -b -v -d commander" > commander.dump
  2. Выключаем модуль commander

    d8 k patch moduleconfig commander --type=merge -p '{"spec":{"enabled":false}}'
    
    moduleconfig.deckhouse.io/commander patched

    Дожидаемся, пока очередь deckhouse окажется пустой

    d8 system queue main
    
    Queue 'main': length 0, status: 'waiting for task 5s'

    Проверяем, что неймспейс d8-commander удален

    d8 k get namespace d8-commander
    Error from server (NotFound): namespaces "d8-commander" not found
  3. Указываем необходимый класс хранилища и включаем модуль commander

     d8 k patch moduleconfig commander --type=merge -p '{"spec":{"enabled":true,"settings":{"postgres":{"internal":{"storageClass":"<NEW_STORAGECLASS_NAME>"}}}}}'
    
     moduleconfig.deckhouse.io/commander patched

    Дожидаемся, пока очередь deckhouse окажется пустой

    d8 system queue main
    
    Queue 'main': length 0, status: 'waiting for task 5s'

    Проверяем, что экземпляр БД в статусе Running

    d8 k -n d8-commander get po commander-postgres-0
    
    NAME                   READY   STATUS    RESTARTS   AGE
    commander-postgres-0   1/1     Running   0          2m4s
  4. Восстанавливаем ранее сохраненную резервную копию БД

    d8 k -n d8-commander exec -it commander-postgres-0 -- su - postgres -c "pg_restore -v -c --if-exists -Fc -d commander" < commander.dump