Репликация — это процесс, в ходе которого содержимое каталога синхронизируется между серверами, за счет чего достигается целостность данных или так называемая конвергентность.
Согласно теореме CAP, в любой реализации распределенных вычислений возможно обеспечить не более двух параметров из трех:
- Согласованность данных (англ. consistency) — во всех вычислительных узлах в один момент времени данные не противоречат друг другу.
- Доступность (англ. availability) — любой запрос к распределённой системе завершается корректным откликом, однако без гарантии, что ответы всех узлов системы совпадают.
- Устойчивость к разделению (англ. partition tolerance) — расщепление распределённой системы на несколько изолированных секций не приводит к некорректности отклика от каждой из секций.
В случае со службой каталога, из трех параметров теоремы CAP целостность данных имеет наименьший приоритет. Служба каталога должна обеспечивать в первую очередь доступность данных и быть устойчива к разделению, когда любой из контроллеров домена при обращении к нему клиента способен обработать его запрос или выдать ответ о невозможность обработки за определенное конечное время. В то же время, система стремится к состоянию согласованности данных на разных контроллерах домена, однако данные могут не быть идентичны в один и тот же момент времени. Это не является проблемой для службы каталога, если механизм репликации работает штатно.
Каждый контроллер имеет свой идентификатор и свой журнал изменений, в котором он логирует все изменения произошедшие как на нем самом, так и на других контроллерах домена.
За работу репликации в 389 Directory Server отвечает плагин Multimaster Replication Plugin. Алгоритм его работы основан на использовании журнала событий, который хранится в отдельной базе данных (каталог /var/lib/dirsrv/slapd-ALD-LOCAL/db/changelog в моем случае, имя домена у каждого свое). Для работы механизма репликации требуются заранее установленные соглашения о репликации, за управление которыми отвечает плагин IPA Topology Configuration.
Данные в журнале событий храниться в течении 30 дней. Это позволяет при невозможности выполнять репликацию (машина с контроллером выключена, нет сетевого соединения и т.д.) на контроллере домена не более этого периода, или корректно выполнить репликацию, если с момента её сбоя до восстановления прошло не более 30 дней. В противном случае потребуется инициализация контроллера домена.
Период в 30 дней считается оптимальным с точки зрения соотношения размера журнала и «безопасного» периода невозможности выполнить репликацию. Однако, при необходимости, этот период может быть изменен, а размер журнала ограничен. Для этого, в записи с DN «cn=changelog5,cn=config» можно задать два атрибута:
- nsslapd-changelogmaxage - максимальный возраст записей в журнале изменений (по умолчанию 30 дней)
- nsslapd-changelogmaxentries - максимальное количество записей в журнале (по умолчанию значение не задано)
Если репликация между контроллерами не происходила больше 30 дней, то потребуется полная инициализация контроллера, потому что он не сможет корректно запустить процесс репликации, т.к. данные будут неконсистентны.
В домене FreeIPA каждая реплика является Мастером, то есть доступна на запись и с ее помощью можно вносить изменения в каталог. Такую репликацию, когда один и тот же сервер в разные моменты времени выступает то в роли Поставщика, то в роли Потребителя, называют репликацией с несколькими Ведущими серверами.
Репликация всегда инициируется Поставщиком, а не Потребителем (т.е. работает по модели Push). В сеансе репликации Поставщик связывается с Потребителем, запрашивает у того сводную информацию о состоянии его репликации (так называемую таблицу RUV, Replica Update Vector), чтобы определить, есть ли у него для Потребителя более свежие данные, которые можно было бы передать, и запускает передачу данных.
Пример репликации между контроллерами dc1 и dc2. dc1 связывается с dc2, чтобы передать ему изменения (например, были созданы новые пользователи):
- Контроллер dc1 запрашивает у контроллера dc2 таблицу векторов RUV. У каждой реплики запрашивается - какой известный идентификатор изменений самый минимальный и какой известный идентификатор изменений максимальный. В итоге получается таблица, у которой в строчках будут идентификаторы реплики, а в двух колонках - минимальное и максимальное изменение.
- Контроллер dc1 берет свою собственную (такую же как запрашивал у dc2) таблицу RUV и сравнивает ее построчно по каждой реплике с таблицей, которую получил с контроллера dc2. И везде, если он находит строчку, что по этой реплике у него (на dc1) информации больше чем у реплики на dc2, которой он хочет отдать изменения, он берет дельту и отправляет ее на контроллер dc2.
- Контроллер dc2 вносит эти строчки в свой журнал изменений и обновляет свою таблицу векторов RUV.
Для чего нужна процедура полной инициализации. Если мы в данный момент делаем снапшот контроллера домена (dc2), то в журнале будет зафиксирован слепок этих изменений. И когда мы включим контроллер домена (реплику) и произведем какие-то изменения в домене (например, на этом контроллере буду созданы или удалены пользователи), то эти изменения в снапшот не попадут. И в случае восстановления контроллера домена (реплики) из бэкапа (снапшота) эти изменения не появятся (будут утеряны), потому что соседние контроллеры (dc1) наши собственные изменения нам не отдают. Поэтому нужно запустить процедуру полной инициализации. В рамках которой контроллер домена (реплика), например, dc2 забирает из реплики dc1 все данные. dc2 очищает свой журнал изменений и берет полную копию данных с реплики dc1. После этого он продолжает штатно работать с пустым журналом и актуальными данными на момент полной инициализации. Бэкап контроллеров домена все равно делать нужно, потому что гораздо проще восстановить контроллер из бэкапа и провести процедуру полной инициализации, чем вычищать данные о "потерянном" контроллере домена.
Просмотр соглашения о репликации
Зайдем на портал управления в раздел «Соглашения о репликации» ( Управление доменом - Сайты и службы - Соглашения о репликации ).
Если на вкладке «Соглашения о репликации» в графе «Направление соглашения» отображается не двунаправленная, а однонаправленная стрелка, это означает, что было создано не двунаправленное, а однонаправленное соглашение о репликации. В этом случае репликация будет осуществляться только в одну сторону. О причинах такого поведения и методе его устранения рассказано в следующем подразделе. Если вы столкнулись с созданием односторонней репликации, это необходимо исправить, перед тем как двигаться дальше.
Исправление односторонних отношений Left-Right
Перед созданием соглашения о репликации в LDAP-каталоге сначала создается такая сущность, как сегмент. Как только Topology плагин контроллера видит относящийся к нему сегмент, для которого не создано соглашение, он создает такое соглашение. Сначала создается соглашение в одном направлении, затем в обратном, и при наличии двух взаимонаправленных сегментов они удаляются и создается третий сегмент, у которого направление Both.
Если в домене наблюдается однонаправленное соглашение о репликации, т. е. стрелочка только в одну сторону, и она не становится двунаправленной, это означает, что второй сегмент не был создан и для устранения проблемы его нужно создать вручную.
Найдем однонаправленные Left-Right сегменты и запишем их в файл:
set +o history
ldapsearch -Q -xLLL -D "cn=directory manager" -w "P@ssw0rd" -b "cn=domain,cn=topology,cn=ipa,cn=etc,dc=ald,dc=local" "(ipaReplTopoSegmentDirection=left-right)" > direction.ldif
set -o history
Создадим python скрипт parcing_topology.py командой, а также этот файл можно скачать в личном кабинете:
with open('direction.ldif') as f:
lines = f.readlines()
ldif_change=""
text_block=""
for line in lines:
text_block=f"{text_block}{line}"
if "ipaReplTopoSegmentLeftNode" in line:
left_node=line.split(":")[1].strip()
if "ipaReplTopoSegmentRightNode" in line:
right_node=line.split(":")[1].strip()
if not line.strip():
text_block=text_block.replace(f"{left_node}-to-{right_node}",f"{right_node}-to-{left_node}")
text_block=text_block.replace(f"ipaReplTopoSegmentLeftNode: {left_node}",f"ipaReplTopoSegmentLeftNode: {right_node}")
text_block=text_block.replace(f"ipaReplTopoSegmentRightNode: {right_node}",f"ipaReplTopoSegmentRightNode: {left_node}")
ldif_change+=f"{text_block}"
text_block=""
with open('add_direction.ldif','w') as f:
f.write(ldif_change)
Запустим скрипт в той же папке и убедимся, что скрипт отработал корректно:
python3 parcing_topology.py
Результатом работы скрипта будет файл add_direction.ldif. Скрипт ищет однонаправленные соглашения о репликации и добавляет соглашения в другую сторону.
Теперь внесем изменения из LDIF файла в каталог от пользователя admin:
ldapadd -f add_direction.ldif
Проверим, что в системе не осталось Left-Right сегментов:
set +o history
ldapsearch -xLLL -D "cn=Directory Manager" -w "P@ssw0rd" -b "cn=domain,cn=topology,cn=ipa,cn=etc,dc=ald,dc=company,dc=lan" "(ipaReplTopoSegmentDirection=left-right)"
set -o history
Перезагружаем сервис ipa (или сами сервера) на всех контроллерах домена, где были проблемы с односторонними соглашениями, по одному, для того, чтобы плагин Topology создал недостающие соглашения:
sudo ipactl restart
Соглашение создается, но не всегда запускается репликация после рестарта реплик. Как решение можно использовать команду выполнив её на dc1:
ipa-replica-manage force-sync--from=dc2.ald.local
Проверка статуса репликации утилитой dsconf
Команда, показывающая информацию по соглашениям о репликации текущего сервера, нужно выполнять от пользователя root:
sudo dsconf -j ALD-LOCAL replication status --suffix dc=ald,dc=local
Для проверки состояния репликации между двумя конкретными серверами RedHat предлагает использовать утилиту ds-replcheck:
admin@dc2:~$ ds-replcheck online -D "cn=Directory Manager" -m ldap://dc2.ald.local:389 -r ldap://dc1.ald.local:389 -b dc=ald,dc=local
Enter password:
================================================================================
Replication Synchronization Report (Tue Apr 30 12:20:49 2024)
================================================================================
Database RUV's
=====================================================
Supplier RUV:
{replica 3 ldap://dc2.ald.local:389} 66169d72000100030000 6630b152000000030000
{replica 4 ldap://dc1.ald.local:389} 66169d6d000100040000 6630b0a9000000040000
{replicageneration} 66169d6d000000040000
Replica RUV:
{replica 3 ldap://dc2.ald.local:389} 66169d72000100030000 6630b152000000030000
{replica 4 ldap://dc1.ald.local:389} 66169d6d000100040000 6630b0a9000000040000
{replicageneration} 66169d6d000000040000
Replication State: Supplier and Replica are in perfect synchronization
Entry Counts
=====================================================
Supplier: 2395
Replica: 2395
Tombstones
=====================================================
Supplier: 10
Replica: 11
Entry Inconsistencies
=====================================================
uid=admin,cn=users,cn=accounts,dc=ald,dc=local
----------------------------------------------
- Supplier missing attribute: "krblastfailedauth"
- Supplier missing attribute: "krbloginfailedcount"
krbprincipalname=ldap/dc1.ald.local@ALD.LOCAL,cn=services,cn=accounts,dc=ald,dc=local
-------------------------------------------------------------------------------------
- Supplier missing attribute: "krbloginfailedcount"
krbprincipalname=DNS/dc2.ald.local@ALD.LOCAL,cn=services,cn=accounts,dc=ald,dc=local
------------------------------------------------------------------------------------
- Replica missing attribute: "krbloginfailedcount"
- Supplier's State Info: krbLoginFailedCount;vucsn-66169db2000900030000: 0
- Date: Wed Apr 10 17:09:54 2024
krbprincipalname=ipa-dnskeysyncd/dc2.ald.local@ALD.LOCAL,cn=services,cn=accounts,dc=ald,dc=local
------------------------------------------------------------------------------------------------
- Replica missing attribute: "krbloginfailedcount"
- Supplier's State Info: krbLoginFailedCount;vucsn-66169db3000500030000: 0
- Date: Wed Apr 10 17:09:55 2024
idnsname=ald.local.,cn=dns,dc=ald,dc=local
------------------------------------------
- Attribute 'idnssoaserial' is different:
Supplier:
- Value: 1714466679
- State Info: idnsSOAserial;adcsn-6630af92000000030000;vucsn-6630af92000000030000: 1714466679
- Date: Tue Apr 30 11:45:06 2024
Replica:
- Value: 1714456160
- State Info: idnsSOAserial;adcsn-66308660000000040000;vucsn-66308660000000040000: 1714456160
- Date: Tue Apr 30 08:49:20 2024
idnsname=2.0.10.in-addr.arpa.,cn=dns,dc=ald,dc=local
----------------------------------------------------
- Attribute 'idnssoaserial' is different:
Supplier:
- Value: 1714466679
- State Info: idnsSOAserial;adcsn-6630af92000100030000;vucsn-6630af92000100030000: 1714466679
- Date: Tue Apr 30 11:45:06 2024
Replica:
- Value: 1714456160
- State Info: idnsSOAserial;adcsn-66308660000100040000;vucsn-66308660000100040000: 1714456160
- Date: Tue Apr 30 08:49:20 2024
uid=ald-user1,cn=users,cn=accounts,dc=ald,dc=local
--------------------------------------------------
- Supplier missing attribute: "krbloginfailedcount"
uid=ald-user2,cn=users,cn=accounts,dc=ald,dc=local
--------------------------------------------------
- Supplier missing attribute: "krbloginfailedcount"
krbprincipalname=DNS/dc1.ald.local@ALD.LOCAL,cn=services,cn=accounts,dc=ald,dc=local
------------------------------------------------------------------------------------
- Supplier missing attribute: "krbloginfailedcount"
krbprincipalname=ipa-dnskeysyncd/dc1.ald.local@ALD.LOCAL,cn=services,cn=accounts,dc=ald,dc=local
------------------------------------------------------------------------------------------------
- Supplier missing attribute: "krbloginfailedcount"
Result
=====================================================
There are replication differences between Supplier and Replica
admin@dc2:~$
--------------------------------------------------------
Список (пополняемый) других вышедших материалов об ALD Pro:
1. Установка первого контроллера домена ALD Pro 2.2.1:
2. Ввод клиента в домен ALD Pro
3. Установка резервного контроллера домена ALD PRO 2.2.1:
4. Механизм репликации в ALD Pro 2.2.1
5. Служба синхронизации времени Chrony
- Видео (временно на бусти)