← Документация Hope·HopeDChopedc.ru
HopeDC · Документация

Кластер HA: создание и обслуживание

Мульти‑мастер репликация каталога и DNS, разрешение конфликтов и наблюдаемость
Документ 7 · Версия 3.2 · 10.11.2026 · соответствует HopeDC v199
Аудитория: администраторы инфраструктуры HopeDC
Соответствует коду ядра: hopedc-core (cluster.rs, api.rs) и hopedc-db (engine.rs)

Содержание

  1. Что даёт кластер HopeDC
  2. Архитектура репликации
  3. Что реплицируется, а что нет
  4. Требования и подготовка
  5. Создание кластера пошагово
  6. Разрешение конфликтов (LWW)
  7. Наблюдаемость: конфликты, возвраты, согласованность
  8. Обслуживание: вывод, возврат и замена узла
  9. Диагностика проблем
  10. Региональные серверы дочерних доменов (разделы)
  11. Масштаб: 100 тыс. пользователей и 100 тыс. компьютеров
  12. Автотопология репликации по сайтам

1. Что даёт кластер HopeDC

Кластер HopeDC — это несколько равноправных контроллеров домена (узлов), которые синхронизируют между собой каталог, DNS, доверительные отношения, доменную политику безопасности и конфигурацию DHCP‑пулов. Схема мульти‑мастер: писать можно на любом узле, изменения расходятся на остальные. Это повышает доступность (при отказе одного узла клиенты обслуживаются другими) и позволяет распределять нагрузку.

Согласованность — итоговая (eventual): после сетевых задержек и простоев узлы сходятся к одинаковому состоянию. Конфликты (одновременная правка одного объекта на разных узлах) разрешаются автоматически по правилу «последняя запись побеждает» (Last‑Writer‑Wins, см. раздел 6).

Где настраивается. Раздел Настройки → Кластер (HA) веб‑панели. Право доступа: cluster.view (просмотр) и cluster.edit (изменение).

2. Архитектура репликации

Модель обмена — pull: каждый узел раз в ~15 секунд сам забирает изменения у настроенных пиров, а не рассылает их. Ключевые элементы:

Весь обмен идёт по HTTPS на порту API 9444. Узел аутентифицируется одним из двух способов: общим секретом кластера (заголовок X-Cluster-Secret) — полное взаимное доверие и обмен всеми доменами; либо личным токеном сопряжения пары (заголовок X-Replica-Token) — для региональных узлов с ограниченным разделом (отдаются только их домены, см. раздел 10). Без действующего секрета или токена узел отвечает HTTP 401. Межузловые эндпоинты: /api/replication/pull, /api/replication/snapshot, /api/replication/digest.

Проверка сертификата узла

Узел, подключаясь к пиру, проверяет его сертификат — иначе подставной узел мог бы получить секрет кластера и данные каталога:

  1. Сертификат выпущен ЦС домена. Если в домене настроен центр сертификации (корневой ЦС домена есть после выпуска первого сертификата в разделе PKI), каждый узел предъявляет сертификат от этого ЦС с адресами узла (IP из DC_SELF_IP, адрес основного интерфейса, DC_WEB_EXTRA_SAN). Пиры проверяют цепочку до ЦС своего домена и совпадение адреса из URL пира. Это основной режим — ничего настраивать не нужно.
  2. Закреплённый отпечаток. Если ЦС нет, узел использует постоянный самоподписанный сертификат (создаётся один раз и хранится зашифрованным в каталоге данных). Пир сверяет его SHA‑256 с отпечатком, закреплённым в настройках пира. Отпечаток можно вписать заранее: он показан на самом узле в карточке «Этот узел» (Кластер → Узлы и репликация, кнопка копирования).
  3. Первое подключение. Если отпечаток не задан, сертификат принимается при первом подключении и после успешного обмена запоминается; в журнале появляется строка 🔐 Кластер: запомнен сертификат узла … — сверьте отпечаток с карточкой «Этот узел» на соседнем узле.

Если сертификат пира не проходит проверку ЦС и не совпадает с закреплённым отпечатком, связь с ним прекращается, а в статусе пира и журнале выводится «сертификат узла изменился: … вместо закреплённого …». Если узел действительно переустановлен или сменил сертификат, сверьте новый отпечаток на нём и нажмите «Сбросить» у этого пира (или впишите новый отпечаток) и сохраните настройки.

При сохранении настроек кластера закреплённые отпечатки сохраняются; сбрасываются они только кнопкой «Сбросить». Сертификат от ЦС проверяется в первую очередь: после настройки PKI смена сертификата узла (он перевыпускается при каждом запуске) связь не прерывает.
О портах. 9444 — порт Admin API (HTTPS, DC_API_PORT), по которому узлы кластера реплицируются; 9443 — порт веб‑панели (HTTPS, DC_UI_PORT), к которому ходит браузер администратора (панель вкомпилирована в бинарник и на том же origin отдаёт /api/). Между узлами кластера нужен именно 9444, а не порт веб‑панели. Внешний nginx/Vite в продакшене не требуется.

3. Что реплицируется, а что нет

Важно понимать границы репликации — это влияет на планирование кластера.

РеплицируетсяНЕ реплицируется (настраивается на каждом узле отдельно)
  • Объекты каталога: домены, OU, пользователи, группы, компьютеры, служебные объекты (в т.ч. ключи Kerberos на объектах)
  • DNS‑записи всех зон (A, PTR, SRV, CNAME, MX, TXT, NS, SOA…)
  • Доверительные отношения (Trusts) — чтобы кросс‑реалм работал на любом узле
  • Доменная политика безопасности (длина/сложность пароля, блокировка, срок пароля) — чтобы была единой на всех контроллерах
  • Блокировка учётки (lockoutTime) и её снятие администратором — учётка, заблокированная на одном узле, заблокирована на всех (v138)
  • Конфигурация DHCP‑пулов (scopes): сеть, диапазон, шлюз, DNS, опции — чтобы задавать пул один раз на весь кластер
  • Аренды DHCP (leases) — только конфигурация пулов реплицируется, сами аренды локальны (иначе возможна выдача одного IP двумя узлами; корректная HA‑раздача — через failover)
  • Сертификаты и шаблоны ЦС (PKI)
  • Учётные записи и роли панели администрирования
  • Лицензия, сетевой доступ, расписание бэкапов, конфигурация кластера
  • Файловые журналы сервера (hopedc.log.*)
  • Счётчик неверных попыток входа (badPwdCount) — у каждого узла свой, как у каждого DC в AD
Практический вывод. Реплицируется «доменная» часть: каталог, DNS, доверия, политика безопасности и конфигурация DHCP‑пулов — именно она нужна для аутентификации и единообразного поведения на любом узле. Аренды DHCP и ЦС остаются локальными, настройки панели задавайте согласованно вручную. Проверка согласованности (раздел 7) сравнивает каталог, DNS, доверия, политику и DHCP‑пулы.
Выбор области репликации. В разделе Кластер (HA) → «Узлы и репликация» → «Что реплицировать» можно по отдельности включать/выключать категории (каталог, DNS, доверия, политика, DHCP‑пулы). Выключенная категория остаётся локальной на этом узле: локальные изменения по ней не рассылаются, входящие — не применяются (но релеятся дальше для транзитивности), и она не влияет на вердикт «Сошлись». Настройка — пер‑узловая; для предсказуемости держите её одинаковой на всех узлах. Если позже включить ранее выключенную категорию, для «добора» пропущенного может понадобиться повторный бутстрап узла.
DHCP‑failover (split‑scope). Тумблер там же («Узлы и репликация»). Реплицируется только конфигурация пулов, а аренды локальны — поэтому, чтобы два узла не выдали один IP, при включённом failover узлы делят диапазон каждого пула между собой (по устойчивому порядку node_id): каждый выдаёт новые адреса только из своей части. Если пир недоступен, выживший узел берёт весь диапазон (takeover). Клиенты, у которых уже есть аренда или резервация, сохраняют свой адрес независимо от раскладки. Это упрощённый split‑scope без протокола MCLT: в момент возврата пира возможно кратковременное окно перекрытия — для лабораторного/типового применения приемлемо.

4. Требования и подготовка

Сеть

Синхронизация времени (обязательно)

NTP на всех узлах — критично. Конфликты разрешаются по стенным часам (см. раздел 6). Узел со «спешащими» часами будет систематически выигрывать конфликты, а рассинхронизация времени делает исход правок непредсказуемым. Настройте NTP (например, chrony) и убедитесь, что расхождение часов между узлами — доли секунды.

Прочее

5. Создание кластера пошагово

Ниже — сценарий из двух узлов. Дополнительные узлы добавляются аналогично.

Быстрый путь — раздел «Контроллеры» (v188). Второй и следующие узлы можно не настраивать вручную. На первом узле откройте Контроллеры (главное меню, под «Доменами») → «Добавить контроллер», укажите адрес сервера и доступ по SSH (пароль или ключ, sudo), роль — «Полная реплика всех доменов» (узел полного доверия) или «Региональный контроллер» с его доменами (раздел 10), — затем «Проверить» и «Установить». HopeDC передаст пакет и установщик, установит службу в режиме присоединения (JOIN_CLUSTER=1, для регионального — HOSTED_DOMAINS), передаст новому узлу адрес первого узла и общий секрет (полная реплика) или личный токен пары (региональный), а на первом узле добавит пир нового узла. Шаги 2–3 ниже при этом выполняются автоматически; общий секрет, если он ещё не задан, создаётся. Пароль панели admin нового узла задаётся случайно и показывается один раз в журнале установки (v195). Подробно — Документ 2, раздел 7 «Контроллеры».

Шаг 1. Первый узел — источник данных

Поднимите первый узел и наполните каталог (создайте домен, учётки, DNS) как обычно. Затем откройте Настройки → Кластер (HA), вкладка «Узлы и репликация»:

  1. Задайте Имя узла (для удобства, напр. dc-01). ID узла уже сгенерирован автоматически.
  2. Задайте Общий секрет кластера — придумайте длинную строку.
  3. Включите переключатель репликации (вверху карточки настройки узла).
  4. Нажмите Сохранить настройки кластера.

Шаг 2. Второй узел — присоединение

Второй узел запускайте в режиме присоединения, чтобы он не создавал собственный демо‑домен hope.local: задайте службе переменную окружения DC_JOIN_CLUSTER=1 до первого запуска (например, строкой Environment=DC_JOIN_CLUSTER=1 в unit‑файле или файле /etc/systemd/system/hopedc.service.d/). Узел с пустым каталогом в этом режиме создаёт только учётную запись панели admin и ждёт данных от пира; в журнале — «Режим присоединения к кластеру: демо‑домен не создаётся». Тот же режим включается автоматически, если на пустом узле ещё до первого запуска лежит настроенный cluster_config.json с пирами. После присоединения переменную можно убрать — на непустом каталоге она ни на что не влияет.

Затем на втором узле в разделе Кластер (HA):

  1. Задайте Имя узла (напр. dc-02) и тот же секрет кластера, что на первом.
  2. Нажмите Добавить узел и впишите URL первого узла: https://10.0.0.1:9444.
  3. Включите репликацию и Сохранить.

При первом контакте второй узел выполнит бутстрап: заберёт снимок каталога, DNS, доверий, политики безопасности и DHCP‑пулов у первого. Дальше пойдёт инкрементальная синхронизация.

Шаг 3. Встречное направление

Чтобы изменения расходились в обе стороны, на первом узле добавьте пира — URL второго (https://10.0.0.2:9444) и сохраните. В мульти‑мастере каждый узел тянет у каждого.

Domain Controllers (v192). Каждый узел сам добавляет свою учётную запись компьютера в подразделение Domain Controllers каждого домена, который он держит (имя — имя узла). Так в «Структуре домена» видно, какие контроллеры обслуживают домен. Записи защищены от удаления; запись выведенного узла удаляет полный администратор панели (Документ 2, п.4.1).

Шаг 4. Проверка

Не засевайте демо‑данные независимо на обоих узлах. Второй узел должен присоединяться бутстрапом к первому (запуск с DC_JOIN_CLUSTER=1, см. шаг 2), а не создавать свой домен с нуля. Если узел уже успел создать свой hope.local, остановите его, очистите каталог данных и запустите заново в режиме присоединения. Иначе у объектов будут разные внутренние идентификаторы (UUID), и такие объекты никогда не сойдутся — вкладка «Согласованность» будет постоянно показывать расхождение.

6. Разрешение конфликтов (LWW)

Если один и тот же объект изменён на двух узлах до того, как они синхронизировались, возникает конфликт. HopeDC разрешает его автоматически правилом Last‑Writer‑Wins:

победитель = у кого больше ts (время изменения);
при равном ts — у кого больше node_id (детерминированный добор)

Три свойства, которые важно понимать:

Подводные камни

7. Наблюдаемость: конфликты, возвраты, согласованность

Раздел Кластер (HA) содержит четыре вкладки. Кроме «Узлы и репликация» — три инструмента наблюдаемости.

Журнал конфликтов

Фиксирует случаи, когда изменение с этого узла столкнулось с изменением того же объекта на другом узле. Каждая запись показывает объект, что сохранилось (победитель: узел + время) и что затёрлось (проигравшая версия перечёркнута), а также принято ли входящее изменение или отклонено (наша версия оказалась новее). Записи ведутся на обоих узлах — у проигравшего «затёрлось», у победителя «отклонено чужое», — что даёт полную картину.

Хранится в repl_conflicts.json (кольцо на 2000 записей). Кнопка «Очистить журнал» сбрасывает его.

Возвраты узлов

Когда пир возвращается после недоступности, HopeDC догоняет пропущенные изменения. Вкладка показывает сводку каждого догона: простой пира, сколько событий догнано (из полученных), сколько было конфликтов, из них — затёрто локальных (ваши изменения заменены версией пира) и отклонено чужих, и число проходов. Если были перезаписи локальных — карточка подсвечивается и отсылает к «Журналу конфликтов». Долгий догон (более 500 событий за проход) агрегируется в один отчёт.

Хранится в repl_reconnects.json (кольцо на 500 записей).

Согласованность

Сверяет отпечаток (дайджест) реплицируемого состояния с каждым узлом. Дайджест считается детерминированно и порядко‑независимо отдельно по каталогу, DNS, доверительным отношениям и DHCP‑пулам, плюс отдельный хеш доменной политики безопасности (эндпоинт /api/replication/digest). По каждому пиру выводится статус: Сошлись, Расхождение или «Нет связи», с разбивкой по каталогу, DNS, доверию, политике и DHCP‑пулам (сколько объектов «здесь» и «там» и совпадает ли содержимое). Кнопка «Проверить сейчас» запускает сверку.

Кратковременное расхождение — норма. Согласованность итоговая: сразу после массовых правок узлы могут ненадолго различаться, пока идёт догон. Повторите проверку через несколько секунд или нажмите «Реплицировать сейчас». Устойчивое расхождение — повод для диагностики (раздел 9).

8. Обслуживание: вывод, возврат и замена узла

Плановый вывод узла

Просто остановите узел. Остальные продолжат работать; клиентов переключит DNS/локатор на живые узлы. Изменения, сделанные на живых узлах во время простоя, накапливаются в их журналах.

Возврат узла

Запустите узел снова. Он автоматически догонит пропущенное по watermark. Проверьте вкладку «Возвраты узлов» — там появится отчёт о догоне, и вкладку «Согласованность» — статус должен стать Сошлись. Если во время простоя те же объекты правились и на вернувшемся узле, часть его локальных правок могла быть затёрта по LWW — детали в «Журнале конфликтов».

Долгий простой: автоматическая пересинхронизация

Каждый узел хранит в журнале последние 8000 изменений. Если узел отсутствовал дольше (или на пире за это время прошёл массовый импорт), часть событий из журнала пира уже вытеснена. С v126 узел обнаруживает такой разрыв сам: пир сообщает нижнюю границу своего журнала, и если наш водяной знак ниже неё, в журнале появляется предупреждение 🔁 Репликация: пропущены события узла … и узел выполняет пересинхронизацию по снимку:

Пересинхронизацию можно запустить и вручную — кнопка «Пересинхронизировать» на вкладке «Узлы и репликация» (право cluster.edit). На 200 тыс. объектов она занимает 5–10 секунд. Пока узел сам принимает снимок, отдавать снимок другим он отказывается (HTTP 503) — так не распространяются неполные данные.

Замена узла / повреждённые данные

Если данные узла повреждены — пересоберите его с нуля: остановите службу, очистите каталог данных узла (сохранив cluster_config.json) и запустите — узел присоединится заново бутстрапом снимком. На 200 тыс. объектов бутстрап занимает около 12 секунд после запуска службы.

Шифрование данных и узлы кластера

У каждого узла свой мастер‑ключ шифрования данных на диске (по умолчанию /etc/hopedc/master.key). Ключи узлов не обязаны совпадать и не передаются по сети: узел отдаёт изменения пиру по HTTPS (порт 9444), а принимающий узел записывает их на диск, зашифровав своим ключом. Поэтому:

Подробнее — Документ 2, раздел «Шифрование данных на диске и мастер‑ключ».

Смена ключа krbtgt в кластере

Ключ krbtgt хранится в объекте каталога и реплицируется, как любое изменение. Ручную смену выполняйте на одном узле (Домены → домен → «Ключи Kerberos»; у каждого домена свой ключ): новый ключ доходит до остальных узлов со следующим проходом репликации (обычно до 15 секунд). Предыдущий ключ принимается всеми узлами до следующей смены, поэтому выданные ранее билеты работают на любом узле. В короткое окно до репликации билет, выданный узлом с новым ключом, другой узел может не принять — клиент повторит запрос.

Проверка сертификата LDAPS контроллеров AD

Закреплённый отпечаток сертификата DC, сохранённые ЦС AD и имя DC (см. Документ 2, «Проверка подлинности контроллера AD») реплицируются вместе с корнем интегрированного домена. Любой узел кластера проверяет DC одинаково. Сброс или закрепление отпечатка на одном узле действует на всех. Сведения о последнем отказе проверки («DC предъявил другой сертификат») показываются на том узле, где он произошёл.

Вывод Windows‑DC в кластере

Приём роли KDC и отключение домена от AD (Документ 2, п.4.9) выполняйте на одном центральном узле. Ключи krbtgt и отметки домена (роль KDC принята, домен мигрирован) реплицируются: остальные узлы начинают выдавать билеты тем же ключом и прекращают синхронизацию с AD со следующей репликацией.

Контроллер только для чтения (RODC) (v171–v177)

RODC — узел, который держит копию каталога только для чтения и кэширует пароли лишь для заранее разрешённых учёток. Его ставят там, где нельзя полностью доверять физической защите: филиалы, удалённые площадки, DMZ. Если такой узел украдут или вскроют, под угрозой окажутся только кэшированные на нём пароли, а не весь домен.

Как включить. При установке узла задайте переменную окружения DC_RODC=1 (режим хранится в конфигурации кластера; в разделе «Кластер» у такого узла — метка «RODC · только чтение»). RODC настраивается как обычный региональный узел: он тянет каталог с записываемого контроллера (пир с указанным URL), а сам наружу ничего не отдаёт — репликация односторонняя.

Сопряжение RODC с мастером — только токеном пары (v177)

Важно (исправление v177). В v171–v176 RODC подключался к мастеру по общему секрету кластера, и мастер отдавал ему все данные — секреты вычищались лишь на самом RODC. Укравший филиальный узел мог достать секрет с его диска и получить у мастера все хэши паролей. Начиная с v177 секреты для RODC вырезает сам мастер, а RODC не должен знать общий секрет. Если RODC уже развёрнут — выполните порядок ниже.
  1. На RODC в разделе «Кластер» скопируйте его node_id (кнопка копирования в карточке «Этот узел»).
  2. На мастере добавьте пира: имя (например, «Филиал»), URL — пусто (RODC тянет у мастера, мастер у него — нет), домены обмена — домен филиала или «*», токен пары — «Сгенерировать», и отметьте «Этот узел — RODC» с node_id из п.1. Сохраните; токен скопируйте.
  3. На RODC у пира-мастера задайте тот же токен пары и домены, сохраните. Проверьте, что репликация идёт (счётчик принятых событий, нет ошибки).
  4. На RODC нажмите «Удалить общий секрет» в красном предупреждении. Без токена у пира-мастера кнопка откажет — чтобы не остановить репликацию.
  5. На узлах полного доверия смените общий секрет кластера (секрет мог быть скопирован с RODC).
Что мастер вырезает для RODCПодробность
Секреты учётокВсех, кроме разрешённых (hopeRodcAllowed): NT-хэш, ключи Kerberos и прежние ключи после смены, история паролей, кэш входа, gMSA.
krbtgtМастер-krbtgt (текущий и прежний ключ) и персональные krbtgt других RODC. Отдаётся только krbtgt_rodc_* этого RODC (по node_id из пометки).
Ключи и пароли сервисовЗакрытый ключ ЦС, ключ KDC для PKINIT, секрет и пароль синхронизации с AD, ключ TSIG DNS, пароли и ключи доверий.
Где действуетНачальный снимок и все последующие изменения (дельты репликации). Узлы полного доверия (общий секрет) получают данные как прежде.

Защиты от ошибок: на RODC нельзя задать общий секрет (сохранение отклоняется); пометку «RODC» нельзя сохранить без токена пары и node_id; старый клиент API, не знающий о пометке, её не снимает. Пока RODC знает секрет, в журнале и в разделе «Кластер» висит предупреждение.

Проверено на стенде (мастер + RODC): по общему секрету снимок содержит секреты всех учёток, мастер-krbtgt (текущий и прежний), krbtgt другого RODC, ключи и пароль доверия; по токену RODC — только свой krbtgt_rodc и разрешённая учётка, остальное вырезано, в том числе в дельтах (смена пароля неразрешённой учётки приходит без секретов, 0 утечек на 500 событий). RODC реплицирует по токену; разрешённый пользователь входит на RODC, неразрешённый — нет (на мастере входит); отказы: секрет на RODC, удаление секрета без токена, пометка RODC без токена/node_id.
Режим RODC задаётся при развёртывании узла (DC_RODC=1) и хранится в конфигурации кластера. Обычное сохранение настроек кластера из панели его не меняет — понизить RODC до записываемого можно только осознанно.
Проверено на стенде (2 узла): односторонняя репликация, вычистка секретов у неразрешённых учёток (вход по ним на RODC не проходит), сохранение секретов у разрешённой учётки (вход и получение сервисного билета проходят), отказ записи по LDAP и из панели, персональный krbtgt RODC (мастер принимает его билеты; поворот ключа отзывает старые), снятие ключей ЦС/PKINIT/синхронизации (RODC переходит на самоподписанный TLS и продолжает обслуживать LDAP/вход), отказ kpasswd на RODC, сохранение режима RODC при сохранении настроек кластера.

Интеграция с MS AD в кластере (v157)

Пароль учётки синхронизации реплицируется на все узлы (как пароль доверия: на диске зашифрован мастер-ключом узла, по LDAP и API не отдаётся). Синхронизацию каталога, импорт DNS и доверий из AD ведёт один узел — держатель аренды, которую он продлевает каждой успешной синхронизацией (атрибут корня домена). Остальные узлы пишут в журнал «синхронизацию с AD ведёт узел …» и не опрашивают AD. Если ведущий не синхронизирует дольше трёх интервалов + минуты (плюс сдвиг узла до 2 минут), аренду забирает другой узел — в журнале «синхронизацию с AD берёт этот узел». Вернувшийся прежний ведущий роль обратно не забирает. «Синхронизировать сейчас» на любом узле делает ведущим этот узел. Запись по LDAP и правки из панели для интегрированного домена выполняются в AD с любого узла (Документ 2, п.4.9). Сквозная проверка паролей идёт с каждого узла напрямую к DC AD (636).

Доверительные отношения в кластере

Доверие хранится и как запись доверия, и как реплицируемый объект trustedDomain (CN=System домена). В объекте — направление, тип, атрибуты, SID партнёра, суффиксы леса (TLN), время смены пароля и сам пароль доверия (внутренний атрибут: по LDAP не отдаётся, на диске зашифрован мастер‑ключом узла). Поэтому на любом узле кластера доверие видно Windows‑клиентам, ключи Kerberos доверия при необходимости восстанавливаются, а смену пароля может выполнить любой узел. Автоматическую смену пароля доверия (DC_TRUST_ROTATE=1) выполняет тот же единственный выбранный узел, что и плановую смену krbtgt.

Смена пароля и блокировка учёток в кластере

Сменить пароль (kpasswd, Ctrl+Alt+Del) можно на любом узле — новый пароль расходится по кластеру как любое изменение каталога. Политика блокировки задаётся в Default Domain Policy и одинакова на всех узлах. Неверные попытки считает тот узел, к которому обратился клиент; когда счётчик на узле достигает порога, учётке записывается lockoutTime, и блокировка действует на всех узлах. Поэтому подбор пароля, распределённый по N узлам, получит не больше N×порог попыток до блокировки — учитывайте это при выборе порога. Счётчики всех узлов видны в свойствах учётки (вкладка Account → «Состояние входа», таблица по контроллерам, v142) — по ним видно, на какой контроллер шёл подбор. Снять блокировку можно на любом узле кнопкой «Разблокировать» (она обнуляет счётчики и на остальных узлах) или записью lockoutTime=0.

Обновление версии узлов (v147)

Узлы обновляются по очереди из раздела Настройки → Обновления панели каждого узла (Документ 2, п.7). Там же видны версии всех узлов кластера. Пока узел перезапускается (секунды), клиентов обслуживают остальные; после старта он догоняет изменения обычной репликацией. Разные версии на узлах допустимы на время поэтапного обновления; региональные серверы обновляйте после центрального.

Из раздела «Контроллеры» (v188). Узлы, добавленные в «Контроллеры», обновляются по SSH: по одному или все контроллеры домена кнопкой «Обновить контроллеры домена», до пакета из «Обновлений» (если он новее) или до версии узла, с которого запущено обновление. Так обновляются и региональные узлы и RODC, которые обновление «всего кластера» пропускает. Первая ошибка останавливает обход; установщик сам возвращает прежнюю версию, если новая не запустилась. Корневой сервер так не обновляется — только из его «Обновлений» полным администратором.

Обновление всего кластера одной кнопкой (v176)

В разделе Обновления узла с подготовленным пакетом (загружен или скачан) есть блок «Весь кластер одной кнопкой». Узел, на котором нажали кнопку, становится координатором и обновляет остальные по одному:

  1. Предпроверка. Каждый узел, который нужно обновить, доступен, на нём установлен механизм применения обновлений (hopedc-update) и не идёт другая установка. Если хоть одно условие не выполнено — обновление не начинается, ничего не меняется; панель называет, что устранить.
  2. По узлу за раз: передача пакета → установка (с теми же проверками, что при загрузке вручную, плюс сверка версии и SHA-256) → ожидание, пока узел ответит новой версией → проверка через 15 секунд, что он на ней и остался.
  3. При сбое — стоп. Если узел откатился, не вернулся за 15 минут или установщик сообщил об успехе, а узел работает на прежней версии, обновление останавливается: следующие узлы и сам координатор не трогаются. Причина видна в таблице.
  4. Координатор — последним. Итог («все узлы на vNNN» или ошибка) сохраняется и виден после его перезапуска.

Кнопка «Остановить после текущего узла» прерывает обход (текущий узел доводится до конца). Узлы, уже работающие на целевой версии, пропускаются.

Безопасность. Передать узлу бинарник — значит исполнить на нём код, поэтому узел принимает пакет только по общему секрету кластера (узлы полного доверия); запросы без него, с неверным секретом или по токену пары отклоняются. Региональные узлы и RODC (сопряжённые токеном пары) в обход не входят — они помечаются «обновите на самом узле». Координатором не может быть RODC.
Проверено на стенде (2 узла, эмуляция установщика): отказ без общего секрета / с неверным секретом / по токену пары; предпроверка при недоступном узле — обновление не начато; откат на узле — обновление остановлено, координатор не тронут, вход пользователей на обоих узлах работает; успешное обновление обоих узлов (сначала пир, затем координатор), после него вход пользователей и репликация работают; перезапуск координатора посреди обхода фиксируется как ошибка с подсказкой.

Лицензия

Кластер (HA) доступен в версии Enterprise. Если лицензия ниже или истекла, раздел открывается только для просмотра: настройки, пиры и включение/выключение недоступны, но уже настроенный кластер продолжает работать и реплицировать изменения.

Файлы состояния (каталог данных)

ФайлНазначение
repl_journal.binЖурнал событий репликации + watermarks (кольцо 8000)
repl_conflicts.jsonЖурнал конфликтов LWW (кольцо 2000)
repl_reconnects.jsonОтчёты о догоне после возврата (кольцо 500)
cluster_config.jsonКонфигурация узла: node_id, секрет, список пиров
cluster_nodes.jsonИзвестные узлы для автотопологии (сайт, адрес, время последнего контакта)

Все файлы состояния хранятся зашифрованными мастер‑ключом узла; просматривать их следует через вкладки раздела «Кластер (HA)», а не напрямую.

Совет. Журнал hopedc.log.* содержит строки репликации (🔁 Репликация…, 📥 Догон…). Их удобно фильтровать в разделе Логирование (подстрока «Репликация» или «Догон»).

9. Диагностика проблем

«сертификат узла изменился» в статусе пира — пир предъявил сертификат, который не проходит проверку ЦС домена и не совпадает с закреплённым отпечатком. Сверьте отпечаток в карточке «Этот узел» на пире; если узел переустанавливали — нажмите «Сбросить» у этого пира. Если пир не менялся — возможна подмена узла, проверьте сеть.
СимптомВероятная причина и действие
Пир «офлайн», ошибка связиПроверьте доступность TCP 9444 между узлами, правильность URL пира, работу узла. Ошибка видна на вкладке «Узлы и репликация» и в «Согласованности».
HTTP 401 при репликацииНет действующего секрета кластера или токена сопряжения. Задайте одинаковый секрет на центральных узлах; для регионального узла — одинаковый токен пары на обоих концах (раздел 10). Пустой секрет больше не открывает репликацию: без секрета или токена узел отвечает 401.
Устойчивое расхождение, счётчики каталога отличаются на постоянную величинуСкорее всего узлы независимо засеяли данные (разные UUID). Пересоберите присоединяемый узел бутстрапом от эталонного (раздел 8).
«Неправильная» сторона выигрывает конфликтыРассинхронизация часов. Проверьте NTP на всех узлах.
Изменение сделано, но не доехалоПроверьте, что репликация включена и пир настроен в обе стороны; нажмите «Реплицировать сейчас»; посмотрите лог репликации.
DHCP/сертификаты/доверия не синхронизируютсяТак и задумано — они не реплицируются (раздел 3). Настраивайте на каждом узле отдельно.

10. Региональные серверы дочерних доменов (разделы)

HopeDC ставится не только в корневом домене, но и в регионах, где работают дочерние домены. Региональный сервер держит только свой домен: данные других доменов леса — в том числе учётные записи и ключи Kerberos родительского домена — он не получает, не принимает и не хранит. Общими для всего леса остаются только конфигурация и схема. Это снимает с регионов обязанность хранить секреты всего леса и ограничивает ущерб при компрометации площадки.

Где настраивается. Кластер (HA) → «Узлы и репликация» → «Разделы (домены) этого сервера». Центральный сервер держит Все домены; региональный — Только выбранные (его поддомен). То же можно задать переменной окружения DC_HOSTED_DOMAINS=child.hope.local.
Автоматически — из «Контроллеров» (v188). Региональный сервер можно поставить из панели центрального сервера или из рабочей области домена (это может сделать и администратор домена — Domain Admins; делегату раздел доступен только для просмотра, v195): роль «Региональный контроллер», домены — его поддомен. Сопряжение токеном пары, домены обмена и раздел регионального сервера настраиваются сами; общий секрет кластера региональному серверу не передаётся. Ручная настройка ниже нужна, если сервер ставится без SSH‑доступа из панели.

Настройка пары «центр ↔ регион»

  1. Домены обмена обязательны (v141). На центральном сервере (все домены) поле «Домены обмена с этим узлом» у узла с токеном сопряжения нельзя оставить пустым: раньше пустое поле означало «все домены», и забытое поле отдавало региональному серверу весь лес, включая ключи родительского домена. Теперь такая настройка не сохраняется, а уже сохранённая — отклоняет репликацию по токену (в журнале: «Репликация по токену пары … отклонена: для узла не указаны домены обмена»). Для узла с полной репликой по токену впишите *. На региональном сервере (раздел ограничен) поле можно оставить пустым — он отдаёт не больше своего раздела.
  2. На центральном сервере (раздел = все домены): «Добавить узел», укажите адрес регионального сервера, в поле «Домены обмена с этим узлом» впишите его домен (напр. child.hope.local), нажмите кнопку генерации и скопируйте токен сопряжения.
  3. На региональном сервере: в «Разделы этого сервера» выберите «Только выбранные» и отметьте его домен; добавьте центральный сервер как узел и вставьте тот же токен.
  4. Общий секрет кластера региональному серверу не выдаётся — по секрету отдаются все домены (полная реплика). Региональный узел связывается с центром только личным токеном пары и списком доменов.
  5. При сохранении сужения раздела панель запросит подтверждение: всё, что вне выбранных доменов, удаляется с этого сервера (на других узлах данные остаются). Аварийная локальная учётная запись узла сохраняется.
Фильтрация в обе стороны. Центр отдаёт региональному узлу только его домен, а изменения чужих доменов, пришедшие от регионального узла, отбрасывает. Даже скомпрометированный региональный сервер не запишет ничего в родительский домен. Для узла с ограниченным разделом центр дополнительно отклоняет из реплики объекты с чужим SID, группы Schema/Enterprise Admins (RID 518/519), запись sIDHistory, материал krbtgt и любые правки корня домена.

Enterprise Admins в дочерних доменах — как в Windows

В Windows группа Enterprise Admins автоматически входит в BUILTIN\Administrators каждого домена леса и управляет поддоменами. HopeDC теперь ведёт себя так же — и на центральном сервере, и на региональном сервере поддомена (туда пользователь родителя приходит через проверенный PAC по доверию). Доступ распространяется на панель, LDAP и SMB/SYSVOL. Обычный Domain Admins родителя поддоменом по‑прежнему не управляет.

Защита от эскалации «снизу вверх» (строже Windows). Enterprise Admins определяются строго как <SID корня леса>-519, а не по любому SID с окончанием -519 или по имени группы — поэтому группу «Enterprise Admins», созданную в поддомене, подделать нельзя. Фильтрация SID привязана к издателю (дереву доменов): предок проносит привилегии вниз (корень → поддомен), но поддомен не может пронести привилегированный или чужой SID вверх к родителю или вбок к соседу. Это закрывает атаки типа golden ticket и SID‑history с контроллера поддомена. Встроенные алиасы S-1-5-32-* через границу realm не принимаются вообще. В лесу Windows этот путь не фильтруется; HopeDC закрывает его намеренно, так как региональные серверы часто стоят в менее защищённом периметре.
Где смотреть в коде. Модель леса и правило вручения SID — hopedc-core/src/kerberos/forest.rs (enterprise_admins_sid, pac_sid_allowed); права администратора — ldap/authz.rs (is_admin_for); фильтр входящей реплики — hopedc-db/src/engine.rs (restricted_inbound_allows).

11. Масштаб: 100 тыс. пользователей и 100 тыс. компьютеров

Нагрузочное тестирование v126 проведено на кластере из трёх узлов с доменом hope.local: 100 000 пользователей, 100 000 компьютеров, 1 000 пользователей с ключами AES и служебные объекты — всего около 211 тыс. объектов каталога. Все три узла и генераторы нагрузки работали на одной виртуальной машине (2 vCPU, 8 ГБ ОЗУ), поэтому показатели пропускной способности ограничены процессором клиентов и являются нижней оценкой; на отдельных серверах они выше.

Задержки одиночных операций

ОперацияДо оптимизации (v125)v126
LDAP simple bind5,2 с1–2 мс
LDAP-поиск по sAMAccountName (всё поддерево)≈ 0,13 с1 мс
LDAP-поиск 11 111 записей в одном контейнере (ldapsearch)—0,46 с
LDAP-выгрузка всего каталога, 201 тыс. записей—5,5 с
Kerberos AS-REQ (kinit)3,5 с12–20 мс
Kerberos TGS-REQ (билет службы)≈ 0,25 с4–5 мс
Создание пользователя через API≈ 0,13 с9–16 мс
Страница «Структуры домена» (100 из 111 тыс.)0,7 с≈ 0,33 с
Поиск в «Структуре домена»—≈ 0,1 с
Полный каталог в API (/api/directory)108 МБ, 1,3–3 сне используется панелью (обзор, DNS, DHCP — счётчики доменов)

Пропускная способность под нагрузкой (ошибок — 0)

НагрузкаРезультат
LDAP: подключение + bind + поиск + отключение, 40 потоков на один узел≈ 770 оп/с, p50 ≈ 45 мс
LDAP: 40 потоков по трём узлам≈ 620 оп/с суммарно, p95 ≈ 150 мс
Kerberos AS (kinit), 8 потоков≈ 190 оп/с, p95 ≈ 66 мс
DNS (SRV/A/SOA), 20 потоков≈ 1 900 запросов/с, p99 ≈ 35 мс
Смешанная: Kerberos + LDAP + DNS на разных узлах и 100 созданий пользователейKerberos 79 оп/с, LDAP 192 оп/с, DNS 1 300 запросов/с; создание p50 16 мс
LDAP (10 потоков) во время серии записей через API340 оп/с, p99 94 мс (в v125 — p99 12 с)

Для оценки: утренний вход 100 тыс. пользователей за 30 минут — это около 55 входов в секунду, то есть доля нагрузки одного узла.

Кластер

СценарийРезультат
Запуск службы с 211 тыс. объектов27–28 с (v125: 31–38 с)
Бутстрап нового узла (213 тыс. записей)12 с после запуска
Задержка репликации изменения на другие узлы4–7 с в среднем, не более 15 с (цикл pull)
Узел пропустил 10 000 изменений (больше журнала): пересинхронизация5–6 с; узел сошёлся через 46 с после запуска (включая 28 с старта)
Сверка содержимого трёх узлов (выгрузка LDAP, 211 594 записи)совпадает побайтно

Память и ресурсы узла

Что изменилось в v126 для больших каталогов

Ограничения

12. Автотопология репликации по сайтам (v178)

Раньше каждый узел получал список пиров вручную, а при отказе узла связи приходилось перенастраивать. С автотопологией узлы сами узнают друг о друге и строят связи по сайтам — так же, как KCC в Active Directory. Ручные пиры при этом сохраняются и всегда имеют приоритет.

Как включить

  1. Опишите сайты и подсети в разделе «Сайты и службы» (если сайтов нет — все узлы попадают в «Default-First-Site-Name», и автотопология строит одну полносвязную группу). Для интегрированного с MS AD домена используются сайты, подсети и связи сайтов из AD (siteObject, siteList, cost).
  2. На каждом узле полного доверия (общий секрет кластера, все разделы) откройте Кластер (HA), включите переключатель «Автотопология репликации по сайтам» и нажмите «Сохранить».
  3. Новому узлу достаточно одного ручного пира на любой узел кластера: через него он узнает остальных, после чего ручной пир можно удалить.

Поля «Сайт этого узла» и «Адрес этого узла для других» обычно пустые: сайт определяется по самой узкой подсети, в которую попадает IP узла, адрес — https://<IP узла>:9444. Заполняйте их, если узел за NAT/с другим именем или подсети не описаны. Адрес должен быть https://.

Как строится план

ГдеСвязи
Внутри сайта, до 5 узловПолносвязно: каждый тянет у каждого.
Внутри сайта, больше 5 узловКольцо в обе стороны + хорды: не больше ~4 связей на узел, путь изменения — не более 3 шагов.
Между сайтамиТолько через мосты (по одному живому узлу на сайт — с наименьшим node_id), по минимальному остовному дереву связей сайтов (самые дешёвые cost). Нет связей сайтов вообще — все сайты связываются с одинаковой стоимостью 100.
Сайт без связи с остальнымиДобавляется аварийная связь и предупреждение в панели «сайт X не связан…» — репликация не теряется, но связь сайтов стоит добавить.

Каждый узел считает план сам по одинаковым данным, поэтому все узлы приходят к одному и тому же плану без «главного». Список узлов распространяется обменом сведениями (каждые 2 минуты) — со своими пирами и напрямую со всеми известными узлами полного доверия, так что филиал не теряет связь с центром при отказе моста.

Отказ узла

Узел, от которого нет сведений больше часа, выпадает из плана. Если это был мост, мостом сайта становится следующий живой узел, и другие сайты переключаются на него автоматически. Вернувшийся узел снова включается в план после первого обмена сведениями.

Кто не участвует

Сведения об узлах передаются только по общему секрету кластера; запросы по токену пары отклоняются.

Наблюдение

Карточка автотопологии показывает таблицу узлов (сайт, адрес, «мост», RODC, давность последнего контакта, «не отвечает»), связи плана (узел ← источник, связи этого узла подсвечены) и предупреждения. В списке состояния пиров автоматические пиры подписаны «(авто)». API: GET /api/cluster/auto-topology.

Проверено на стенде (3 узла, 2 сайта: Center — dc02, dc03; Branch — dc04): узлы нашли друг друга через один ручной пир; сайт определён по подсетям; все узлы построили одинаковый план (мост Center — dc03); после удаления ручного пира изменения с dc02 доходят до dc04 и обратно через мост; при остановке моста dc03 мостом стал dc02 и репликация филиала продолжилась; dc03 после возврата снова стал мостом; выключение переключателя на узле убирает его из плана; вход пользователей (Kerberos) на всех узлах работает.