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

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

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

Схема

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Компонент Параметр Значение
SSH (bootstrap, destroy, attach, detach) Connect timeout 10 сек
SSH KeepAlive interval 15 сек
Agent → Commander API (все запросы, включая конверсию ресурсов) HTTP timeout 30 сек
Agent → 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) автоматически переподключается при разрыве.
  • Агент продолжает попытки связи с 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 применяет в прикладном кластере. К операциям «Изменение» и «Проверка» эти группы отношения не имеют: их синхронизирует отдельный цикл агента, независимо от того, идут ли в этот момент инфраструктурные операции.

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

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

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

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

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

Часть служебных ресурсов Commander (RBAC, проекты, конфигурации Dex и биллинга) защищена от потери контроля строже: при выводе соответствующей группы из-под управления или временной недоступности её источника такие ресурсы удаляются, а не остаются в кластере без сопровождения 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. Подробнее — в разделе Как Commander считает расходы;
  • передавать в Commander описания групп узлов, классов инстансов облачного провайдера и классов хранилища Kubernetes — эти данные используются в интерфейсе биллинга для привязки вычислительных классов и классов хранилища к реальным объектам кластера;
  • добавлять на каждый узел служебный лейбл billing.commander.deckhouse.io/name со значением имени вычислительного класса, к которому узел относится. По этому лейблу Commander сопоставляет узел с вычислительным классом и применяет к его потреблению цену, заданную в действующем тарифе. Лейбл восстанавливается автоматически при пересоздании узлов.

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

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

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

Метаданные биллинга хранятся в базе данных 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}}}}'

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

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

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

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

Доверительная связка автоматически выстраивается через пару ресурсов, которыми управляет 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 управляющего кластера корректно принимает колбэки после входа.

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

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

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

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

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

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

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

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":"AuthToken","remote_address":"238.106.231.86","request_uuid":"a1eaf50bbc87a8cca4cd17d8be8fffdb","workspace_slug":"bfqcc","user_name":"api-user","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":"AuthToken","remote_address":"238.106.231.86","request_uuid":"a1eaf50bbc87a8cca4cd17d8be8fffdb","workspace_slug":"bfqcc","user_name":"api-user","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