В Deckhouse Platform (DP) Stronghold поставляется как модуль stronghold. Модуль сам разворачивает кластер Stronghold, инициализирует и распечатывает хранилище, публикует веб-интерфейс и API через выбранный инлет (по умолчанию Ingress) и в режиме Automatic настраивает вход через Dex. Порядок включения и настройки описан в разделе «Настройка Stronghold».

Схема размещения

На схеме показано размещение модуля в кластере DP:

Размещение модуля stronghold в кластере Deckhouse Platform

Схема иллюстративная: активный узел выбирается Raft и не обязательно является stronghold-0. Элементы Ingress, секрет ingress-tls, Dex и stronghold-keys соответствуют конфигурации по умолчанию (инлет Ingress с CertManager и режим Automatic).

Компоненты модуля

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

  • Неймспейс d8-stronghold — в нём работают все контейнеры Stronghold и хранятся служебные секреты модуля.
  • Поды Stronghold — каждый узел Stronghold запускается в отдельном поде. Поды управляются StatefulSet и размещаются по одному на узел (pod anti-affinity). Если storageClass пуст, поды запускаются на control-plane (master) узлах и на узлах с лейблом node.deckhouse.io/etcd-arbiter. Если storageClass задан, размещение определяется параметром модуля nodeSelector (по умолчанию node-role.kubernetes.io/control-plane=""). Число реплик равно числу master-узлов плюс числу арбитров (etcd-arbiter); если сумма чётная, добавляется ещё одна реплика. Позже его можно изменить вручную.
  • Хранилище — интегрированное хранилище Raft в режиме HA включено по умолчанию. Если storageClass пуст, данные каждого узла хранятся на локальном диске узла в директории /var/lib/deckhouse/stronghold (может использоваться поддиректория с именем из localPathUUID модуля). Если storageClass задан, данные хранятся в PersistentVolumeClaim data-stronghold-N StatefulSet.
  • Внутренний сервис — узлы обращаются друг к другу по именам вида stronghold-0.stronghold-internal. Внутренний API слушает порт 8300 (адреса Raft-пиров — 8301); retry_join между узлами и распечатывание inner-cluster идут на порт 8300. Внешний API слушает 8200. Его кластерный порт 8201 принимает трафик репликации от secondary-кластеров, только если задан publishCluster.enabled. Подробнее — в разделе «Сетевые порты».
  • Инлет — параметр inlet задаёт способ публикации сервиса: Ingress (по умолчанию), GatewayAPI, LoadBalancer, NodePort или None. Для LoadBalancer, NodePort и None обязательно указать https.mode: CustomCertificate. При инлете Ingress веб-интерфейс и API публикуются по адресу, который получается из шаблона publicDomainTemplate заменой %s на stronghold, например stronghold.mycompany.tld.
  • TLS-сертификат — секрет ingress-tls в неймспейсе d8-stronghold. При инлете Ingress и https.mode: CertManager его выпускает cert-manager по ClusterIssuer, заданному в настройках DP; для остальных инлетов, а также при https.mode: CustomCertificate, используется сертификат из customCertificate. Без этого секрета поды остаются в состоянии ContainerCreating.

Режим работы и распечатывание

Режим задаётся параметром management.mode. По умолчанию используется Automatic; также поддерживается Manual. В режиме Manual автоматическая инициализация отключена, интеграции с Dex и Kubernetes не настраиваются, секрета stronghold-keys нет, а параметр management.administrators недоступен. В режиме Automatic:

  1. При первом запуске модуль автоматически инициализирует хранилище.
  2. Ключ распечатывания и root-токен сохраняются в секрет stronghold-keys неймспейса d8-stronghold.
  3. Узлы Stronghold автоматически распечатываются после инициализации и при каждом перезапуске подов. В режиме Automatic модуль запускает компонент stronghold-automatic (одна реплика, период проверки 60 секунд), который распечатывает узлы ключами из секрета stronghold-keys. В Stronghold EE узлы дополнительно настроены с seal "inner-cluster": каждые 5 секунд (параметр autoUnsealPeriod) каждый распечатанный узел распечатывает запечатанные узлы кластера ключом, который читает из собственного барьера, через внутренний API на порту 8300.

Секрет stronghold-keys содержит root-токен и ключ распечатывания. Любой, кто может прочитать секреты в неймспейсе d8-stronghold, получает полный доступ к Stronghold. Ограничьте доступ к этому неймспейсу средствами RBAC DP и сохраните копию секрета в защищённом месте: при выключении модуля секрет удаляется, а без него восстановить доступ к данным нельзя.

HSM (seal "pkcs11") и Yandex Cloud KMS (seal "yandexcloudkms") в DP не поддерживаются — они доступны только в standalone-развёртывании.

Доступ пользователей

Модуль настраивает доступ пользователей следующим образом:

  • После инициализации модуль создаёт в Stronghold политику deckhouse_administrators (полный доступ ко всем путям), назначает её администраторам и включает вход в веб-интерфейс через OIDC-аутентификацию Dex (модуль user-authn).
  • Администраторы Stronghold задаются в ModuleConfig stronghold в параметре management.administrators (только при management.mode: Automatic) — группами (Group) или отдельными пользователями (User). Пользователь должен входить хотя бы в одну группу, иначе вход через OIDC не сработает.
  • Остальных пользователей и их права настраивайте встроенными средствами Stronghold: методами аутентификации и политиками.

Интеграция с кластером

Модуль автоматически подключает текущий кластер DP к Stronghold для работы модуля secrets-store-integration, который доставляет секреты в поды приложений.

Для этого модуль включает метод аутентификации Kubernetes по пути kubernetes_local (kubernetes_host — https://kubernetes.default.svc:443) и создаёт политику deckhouse_administrators и роль для ServiceAccount stronghold-automatic.

Кворум и отказоустойчивость

Кворум Raft рассчитывается по формуле floor(n/2)+1, где n — число узлов Stronghold (PodDisruptionBudget модуля использует minAvailable = replicas/2 + 1). По умолчанию n равно числу master-узлов плюс числу арбитров, округлённому до нечётного. В кластере из трёх master-узлов для чтения и записи нужны как минимум два работающих пода. Кластер из одного master-узла не отказоустойчив. Порядок действий при потере кворума — на странице «Восстановление после потери кворума».

Выключение модуля и данные

При выключении модуля удаляются все контейнеры Stronghold из неймспейса d8-stronghold и секрет stronghold-keys. Если storageClass пуст, данные на узлах в директории /var/lib/deckhouse/stronghold сохраняются. Если storageClass задан, PVC удаляются вместе с StatefulSet (persistentVolumeClaimRetentionPolicy.whenDeleted: Delete), поэтому данные не сохраняются. Чтобы вернуть доступ, включите модуль и поместите в неймспейс сохранённую копию секрета stronghold-keys.

Требования

К модулю предъявляются следующие требования:

  • Начиная с Stronghold 1.19.2, для развёртывания нужна DP версии 1.76 или новее.
  • Stronghold EE включается лицензионным ключом в ModuleConfig и доступен только в коммерческих редакциях DP. Подробнее — в разделе «Редакции».