В данной главе рассматриваются вопросы настройки систем LDAP для выполнения репликации, реализации отсылок и псевдонимов. Репликация — это операционная характеристика, реализуемая с помощью настроек конфигурации, а отсылки могут быть как общими (операционная характеристика), так и явными, указываемыми в DIT (с помощью объектного класса referral). Будет ли LDAP-сервер разрешать отсылки (процесс, называемый сцеплением) или возвращать их клиенту, зависит от настроек сервера LDAP. Кроме того, у LDAP-браузеров обычно есть возможность настройки на автоматическое следование по отсылкам (разрешение отсылок), а также на отображение записей, содержащих объекты-отсылки, чтобы иметь возможность редактировать эти объекты. Псевдонимы включены в этот раздел по тем сомнительным соображениям, что они демонстрируют "подобное отсылкам" поведение в том смысле, что они могут использоваться для изменения строгого иерархического потока DIT, вызывая переход к определённой пользователем альтернативной (или псевдопоименованной) записи, которая может существовать в совершенно несвязанной ветке данного DIT. Упрощённо отсылка может рассматриваться как переход к внешнему серверу LDAP, так как при её разыменовании используется LDAP URI, а псевдоним может рассматриваться как переход внутри сервера LDAP, поскольку при его разыменовании используется только DN.
Одним из наиболее мощных аспектов LDAP (и X.500) является их способность делегировать ответственность за поддержание части каталога другому серверу, сохраняя при этом общую картину каталога как единой и связанной сущности. Таким образом, можно создать в каталоге компании делегирование ответственности (отсылку (referral) в терминологии LDAP) той части всего каталога (DIT), в которой описан конкретный отдел, LDAP-серверу этого отдела. Делегированное DIT называется нижестоящим (subordinate) по отношению к тому DIT, откуда на него происходит отсылка. А то DIT, откуда происходит отсылка, называется вышестоящим (superior). В этом аспекте делегирование LDAP почти полностью отражает делегирование DNS, если эта концепция Вам знакома.
В отличие от системы DNS, в стандартах не предусмотрена возможность указать LDAP-серверу проследовать по отсылке (разрешить отсылку) (в различных документах есть только ссылки на черновые RFC), LDAP-клиенту оставлена возможность напрямую обращаться к новому серверу, используя возвращённую отсылку. Равным образом, поскольку в стандарте не определена организация данных LDAP, возможность перехода LDAP-сервера по ссылке (разрешение ссылки) не противоречит стандартам и некоторые LDAP-серверы выполняют эту функцию автоматически, используя процесс, обычно называемый сцеплением (chaining).
OpenLDAP буквально следует стандартам и по умолчанию не выполняет сцепление, а всегда возвращает отсылку. Однако OpenLDAP может быть настроен на выполнение сцепления с помощью наложения chain.
Встроенная функция репликации LDAP позволяет создать одну или несколько подчинённых (или реплицированных) копий каталога (DIT) от одной главной, таким образом, по сути, создаётся устойчивая структура. В OpenLDAP версии 2.4 представлена возможность реализовать полноценную конфигурацию разнонаправленной репликации с несколькими главными серверами (N-Way Multi-Master).
Важно, однако, подчеркнуть разницу между LDAP и транзакционными базами данных. При выполнении обновления на главном каталоге LDAP для обновления всех подчинённых каталогов может потребоваться некоторое время (в компьютерной терминологии) — главный и подчинённый каталоги могут быть рассинхронизированы в течение какого-то периода времени.
В контексте LDAP, временное отсутствие синхронизации DIT считается несущественным. В случае же транзакционной базы данных, даже временное отсутствие синхронизации считается катастрофическим. Это подчёркивает различия в характеристиках данных, которые должны храниться в каталоге LDAP и в транзакционной базе данных.
Конфигурация репликации (OpenLDAP и ApacheDS) и отсылок рассматривается далее в этой главе, а также в приводимых примерах.
Рисунок 7.1-1 демонстрирует поисковый запрос с базовым DN dn:cn=cheri,ou=uk,o=grommets,dc=example,dc=com к LDAP-системе с отсылками, ответ на который возвращается в результате серии отсылок к серверам LDAP2 и LDAP3:
Рисунок 7.1-1 — Запрос, генерирующий отсылки к LDAP2 и LDAP3
Примечания:
dn: cn=thingie,o=widget,dc=example,dc=com
dn: ou=us,o=grommets,dc=example,dc=com
dn: cn=cheri,ou=uk,o=grommets,dc=example,dc=com
Если LDAP-сервер сконфигурирован на выполнение сцепления (то есть на следование по отсылкам, как показано альтернативными пунктирными линиями), то LDAP-клиенту будет отправлен один единственный ответ. Сцепление контролируется конфигурацией LDAP-сервера и значениями в поисковых запросах. Информация по сцеплению здесь.
На рисунке показано явное сцепление с использованием объектного класса referral. Серверы OpenLDAP могут быть настроены так, чтобы возвращать общую отсылку в случае, если суффикс искомого DN не был найден ни в одном из обслуживаемых сервером DIT.
Функции репликации позволяют копировать обновления LDAP DIT на одну или несколько LDAP-систем в целях резервирования и/или повышения производительности. В этом контексте стоит подчеркнуть, что репликация работает на уровне DIT, а не на уровне LDAP-сервера. Так, если на одном сервере обслуживается несколько DIT, каждое из них может реплицироваться на разные серверы. Репликация происходит периодически, в течение промежутка времени, который мы называем временем цикла репликации. В OpenLDAP версии 2.3 был представлен новый мощный механизм репликации (обычно называемый syncrepl), который в версии 2.4 получил дальнейшее развитие и стал поддерживать возможность репликации с несколькими главными серверами (Multi-Master). Существует два возможных типа конфигураций репликации, у каждого из которых есть несколько вариантов.
Примечание: В OpenLDAP версий до 2.4 для выполнения репликации использовался отдельный демон, называемый slurpd. Сейчас этот механизм представляет интерес лишь с исторической точки зрения, и его описание до сих пор приводится исключительно для тех, кто всё ещё поддерживает работу систем OpenLDAP версий до 2.3. Остальные могут не обращать на slurpd внимания.
Главный-подчиненный (Master-Slave): В конфигурации главный-подчинённый для выполнения обновлений доступно единственное (главное) DIT, и эти обновления реплицируются или копируются на один или несколько указанных серверов, на которых запущены подчинённые DIT. Подчинённые серверы оперируют с доступной только для чтения копией главного DIT. Пользователи, которые выполняют только чтение, могут обращаться к серверам, содержащим подчинённые DIT. А пользователи, которым нужно вносить изменения в каталог, смогут это сделать, только обратившись к серверу, содержащему главное DIT. Чтобы ещё больше запутать своих несчастных пользователей, разработчики OpenLDAP ввели термины поставщик (provider) и потребитель (consumer) для репликации в стиле syncrepl. Каталог может рассматриваться как источник (поставщик) сервисов репликации (то, что простые смертные называют главным (master) DIT), и как назначение (или потребитель) сервисов репликации (то, что простые смертные называют подчинённым (slave) DIT). У конфигурации главный-подчинённый (или поставщик-потребитель) есть два очевидных недостатка:
Несколько мест размещения. Если всем или большинству клиентов требуется вносить изменения в DIT, то им потребуется получать доступ к одному серверу (на котором запущено подчинённое DIT) для осуществления чтения и к другому серверу (на котором запущено главное DIT) для выполнения обновлений. Другой вариант — клиенты всегда будут обращаться к серверу, на котором запущено главное DIT. В последнем случае репликация выполняет только функцию резервного копирования.
Низкая отказоустойчивость. Поскольку существует только один сервер, содержащий главное DIT, он представляет собой единую точку отказа, которая может повлиять на работоспособность всей системы.
Несколько главных (Multi-Master): В конфигурации с несколькими главными серверами могут обновляться несколько главных DIT, запущенных на одном или нескольких серверах, и результаты обновлений распространяются на остальные главные серверы.
Исторически OpenLDAP не поддерживал операции с несколькими главными серверами, но в версии 2.4 такие возможности введены. В этом контексте, наверное, стоит отметить две вариации общей проблемы конкуренции обновлений, специфичной для всех конфигураций с несколькими главными серверами, выявленные OpenLDAP и являющиеся верными для реализаций подобной репликации во всех системах LDAP:
Конкуренция значений. Если выполняется два обновления одного и того же атрибута в одно и то же время (в пределах времени цикла репликации) и при этом атрибуту назначаются разные значения, то, в зависимости от типа атрибута (SINGLE или MULTI-VALUED), результирующая запись может быть в неправильном или непригодном для использования состоянии.
Конкуренция удаления. Если один пользователь добавляет дочернюю запись в то же самое время (в пределах времени цикла репликации), когда другой пользователь удаляет оригинальную (родительскую) запись, то удалённая запись вновь появится.
Рисунок 7.1-2 показывает несколько возможных конфигураций репликации.
Рисунок 7.1-2 — Конфигурации репликации
Примечания:
В случае LDAP1 клиент взаимодействует с подчинённой системой, доступной только для чтения. Для выполнения операций записи клиенты должны обращаться к главной системе.
В случае LDAP2 клиент взаимодействует с главной системой, которая реплицируется на две подчинённые.
LDAP3 является системой с несколькими главными серверами и для выполнения операций чтения (поиска) и/или записи (модификации) клиенты могут обращаться к любому серверу. В данной конфигурации каждый главный сервер может, в свою очередь, иметь одно или несколько подчинённых DIT.
Репликация происходит на уровне DIT и описывает процесс копирования обновлений из DIT на одном сервере LDAP в такое же DIT на одном или нескольких других серверах. Конфигурации репликации могут быть типа "главный-подчинённый" (MASTER-SLAVE) или, в оригинальной терминологии OpenLDAP, типа "поставщик-потребитель" (Provider-Consumer) (подчинённая копия всегда доступна только для чтения) и типа "несколько главных" (MULTI-MASTER). Репликация настраивается на уровне конфигурации сервера (то есть является операционной сущностью), однако используемый syncrepl протокол синхронизации содержимого каталога определён в RFC 4533.
Начиная с OpenLDAP версии 2.4 существует только один метод репликации, известный как syncrepl по атрибуту olcSyncrepl (в OLC) или директиве syncrepl (в slapd.conf) конфигурации потребителя (подчинённого сервера), с помощью которых репликация настраивается. Предыдущие версии OpenLDAP (до 2.4) поддерживали репликацию в стиле slurpd, от которой сейчас полностью отказались.
В OpenLDAP версии 2.3 была представлена поддержка нового протокола синхронизации содержимого LDAP (LDAP Content Synchronization protocol), а начиная с версии 2.4 он стал единственной поддерживаемой возможностью репликации. LDAP Content Synchronization protocol определён в RFC 4533 и широко известен под именем атрибута/директивы настроек потребителя репликации, с помощью которых осуществляется управление им — olcSyncrepl/syncrepl. Функционал syncrepl предоставляет как классическую репликацию главный-подчинённый (master-slave), так и, начиная с версии 2.4, репликацию с несколькими главными серверами (multi-master). В протоколе используются термины поставщик (provider) (вместо главного (master)) для указания на источник реплицируемых обновлений, и потребитель (consumer) (вместо подчинённого (slave)) для указания назначения реплицируемых обновлений.
При репликации в стиле syncrepl процесс обновления всегда инициируется потребителем. Потребитель может быть настроен на периодические запросы (pull) обновлений у поставщика (refreshOnly), либо может запросить у провайдера выполнять посылки (push) обновлений (refreshAndPersist). Во всех вариантах репликации для однозначного указания на какую-либо запись сервер должен поддерживать универсальный уникальный номер (entryUUID) для каждой записи в DIT. Процесс синхронизации показан на рисунках 7.2-2 (refreshOnly) и 7.2-3 (refreshAndPersist):
7.2-2 Репликация syncrepl поставщик-потребитель — refreshOnly
Сервер slapd (1), желающий выполнить репликацию DIT (4) (поставщика репликации) в подчинённую копию (5) (потребитель репликации), сконфигурирован с использованием атрибута olcSyncrepl (OLC) или директивы syncrepl (slapd.conf) (7). В olcSyncrepl/syncrepl определяется расположение (LDAP URI) сервера slapd (3) (поставщика), содержащего главную копию DIT (4). Поставщик (3) сконфигурирован с использованием наложения syncprov.
При типе репликации refreshOnly потребитель (1) инициирует соединение (2) с поставщиком (3) — происходит синхронизация DIT и соединение разрывается (8). Периодически, через определённые в конфигурации промежутки, потребитель (1) устанавливает повторные соединения (2) с поставщиком (3) и пересинхронизируется. Синхронизацию refreshOnly можно рассматривать как операцию в повторяющемся режиме, а время цикла репликации — это время между повторными соединениями.
Подробности: Потребитель (1) устанавливает сессию (2) с поставщиком (3) и запрашивает синхронизацию refreshOnly. К поставщику может обращаться и запрашивать выполнение синхронизации любое количество потребителей — на поставщике нет никаких настроек относительно его потребителя (потребителей): если потребитель удовлетворяет требованиям безопасности поставщика, запросы синхронизации от этого потребителя будут выполнены. По существу, запрос на синхронизацию — это расширенная операция поиска LDAP, определяющая область репликации с помощью обычных поисковых параметров LDAP (базовый DN, диапазон, поисковый фильтр и атрибуты) — таким образом, в зависимости от критериев поиска, может быть реплицировано как всё содержимое DIT поставщика, так и его часть.
Поставщику не нужно хранить у себя сведения о текущем состоянии каждого потребителя. Вместо этого в конце сессии репликации/синхронизации он отправляет синхронизационное куки (SyncCookie — D), в этом куки содержится порядковый номер изменения (Change Sequence Number contextCSN) — по сути, метка времени, указывающая на последнее изменение каталога, отправленное этому потребителю, и которую можно рассматривать как контрольную точку изменений или синхронизации. При установке сессии потребителем, он передает поставщику последнее полученное от него куки (A), чтобы указать поставщику пределы данной сессии синхронизации. В зависимости от того, каким образом был инициализирован каталог потребителя, во время первого обращения к поставщику у потребителя может не быть SyncCookie, тогда первоначальная синхронизация охватит все записи в DIT поставщика (в пределах диапазона синхронизации). Побочный эффект этого процесса — то, что потребитель может быть первоначально запущен с пустым DIT, и, при первой репликации, полностью синхронизироваться с DIT поставщика.
В ответ на запрос синхронизации DIT поставщик (3) будет отвечать, используя одну из двух фаз или сразу обе фазы. Первая из них — фаза наличия (present phase) (B), указывающая на те записи, которые ещё остаются в DIT (или фрагменте DIT). В ней выполняются следующие действия:
Для каждой изменившейся записи (с момента последней синхронизации) посылается запись целиком, включая её DN и UUID (entryUUID). По этим данным потребитель может обновить свои записи без всяких разночтений.
Для каждой неизменившейся записи (с момента последней синхронизации) посылается пустая запись с её DN и UUID (entryUUID).
Для записей, которые были удалены, никаких сообщений не посылается. Теоретически, по окончании двух предыдущих процессов потребитель может удалить записи, не попавшие ни в один из них.
В фазе удаления (delete phase) (С):
Поставщик возвращает DN и UUID (entryUUID) для каждой записи, удалённой с момента последней синхронизации. Потребитель может удалить эти записи без всяких разночтений.
Необходимость использования при синхронизации обоих фаз определяется рядом дополнительных методов.
По окончании фазы (фаз) синхронизации поставщик посылает SyncCookie (текущий contextCSN — D) и закрывает сессию (8). Потребитель сохраняет это SyncCookie и, при инициировании другой сессии синхронизации (через промежуток времени, указанный в параметре interval определения olcSyncRepl/syncrepl), он отправит последнее полученное SyncCookie для ограничения диапазона следующей сессии синхронизации.
Примеры конфигурации приводятся ниже в разделе refreshAndPersist.
7.2-3 Репликация syncrepl поставщик-потребитель — refreshAndPersist
Сервер slapd (1), желающий выполнить репликацию DIT (4) (поставщика репликации) в подчинённую копию (5) (потребитель репликации), сконфигурирован с использованием атрибута olcSyncrepl (OLC) или директивы syncrepl (slapd.conf) (7). В olcSyncrepl/syncrepl определяется расположение (LDAP URI) сервера slapd (3) (поставщика), содержащего главную копию DIT (4). Поставщик (3) сконфигурирован с использованием наложения syncprov.
При типе репликации refreshAndPersist потребитель (1) инициирует соединение (2) с поставщиком (3) — сразу после этого происходит синхронизация DIT и по окончании этого процесса соединение продолжает поддерживаться (становится непрерывным (persist)). Последующие изменения (E) на поставщике (3) немедленно передаются потребителю (1).
Подробности: Потребитель (1) устанавливает сессию (2) с поставщиком (3) и запрашивает синхронизацию refreshAndPersist. К поставщику может обращаться и запрашивать выполнение синхронизации любое количество потребителей — на поставщике нет никаких настроек относительно его потребителя (потребителей): если потребитель удовлетворяет требованиям безопасности поставщика, запросы синхронизации от этого потребителя будут выполнены. По существу, запрос на синхронизацию — это расширенная операция поиска LDAP, определяющая область репликации с помощью обычных поисковых параметров LDAP (базовый DN, диапазон, поисковый фильтр и атрибуты) — таким образом, во время сессии синхронизации реплики, в зависимости от критериев поиска, может быть реплицировано как всё содержимое DIT поставщика, так и его часть.
Поставщику (3) не нужно хранить у себя сведения о текущем состоянии каждого потребителя. Вместо этого он периодически посылает синхронизационное куки (SyncCookie — D), в этом куки содержится порядковый номер изменения (Change Sequence Number contextCSN) — по сути, метка времени, указывающая на последнее изменение каталога, отправленное этому потребителю, и которую можно рассматривать как контрольную точку изменений или синхронизации. Когда потребитель репликации типа refreshAndPersist (1) устанавливает сессию (2) с поставщиком (3), они сначала должны синхронизировать состояния своих DIT (или фрагментов DIT). В зависимости от того, каким образом был инициализирован каталог потребителя, во время первоначального открытия сессии (2) с поставщиком (3) у потребителя может не быть SyncCookie, тогда областью изменений будет DIT целиком (или фрагмент DIT целиком). Побочный эффект этого процесса — то, что потребитель может быть первоначально запущен с пустым DIT, и, при первой репликации, полностью синхронизироваться с DIT поставщика. При последующих подключениях (2) потребителя (1) к поставщику (3), у потребителя уже будет SyncCookie (D). В случае репликации типа refreshAndPersist переподключения будут происходить только после сбоя на поставщике, потребителе или в сети, в результате которых соединение прерывается, в противном случае соединение будет поддерживаться постоянно.
Во время первоначального процесса синхронизации в ответ на запрос синхронизации DIT поставщик (3) будет отвечать, используя одну из двух фаз или сразу обе фазы. Первая из них — фаза наличия (present phase) (B), указывающая на те записи, которые ещё остаются в DIT (или фрагменте DIT). В ней выполняются следующие действия:
Для каждой изменившейся записи (с момента последней синхронизации) посылается запись целиком, включая её DN и UUID (entryUUID). По этим данным потребитель может обновить свои записи без всяких разночтений.
Для каждой неизменившейся записи (с момента последней синхронизации) посылается пустая запись со своим UUID (entryUUID).
Для записей, которые были удалены, никаких сообщений не посылается. Теоретически, по окончании двух предыдущих процессов потребитель может удалить записи, не попавшие ни в один из них.
В фазе удаления (delete phase) (C):
Поставщик возвращает DN и UUID (entryUUID) для каждой записи, удалённой с момента последней синхронизации. Потребитель может удалить эти записи без всяких разночтений.
Необходимость использования при синхронизации обоих фаз определяется рядом дополнительных методов.
По окончании фазы (фаз) синхронизации (D) поставщик обычно посылает SyncCookie (текущий contextCSN) и ПРОДОЛЖАЕТ ПОДДЕРЖИВАТЬ сессию. Последующие обновления (E) DIT поставщика (4) (изменения, добавления или удаления) будут немедленно отправляться (E) поставщиком (3) потребителю (1) для обновления DIT реплики (5). Изменения или дополнения посылаются в виде полной записи (со всеми атрибутами), а также периодически обновляется SyncCookie (D). DIT поставщика (4) и потребителя (5) поддерживаются в состоянии синхронизации, а время цикла репликации в данном случае соответствует времени передачи данных между поставщиком и потребителем.
Различия между настройками репликаций refreshOnly и refreshAndPersist настолько незначительны, что мы объединили их конфигурации и чётко обозначили единственное в них отличие.
Конфигурация главного сервера (поставщика): к записи olcDatabase с определением DIT, которое нам необходимо реплицировать, нужно добавить дочернюю запись наложения syncprov. Если мы, для простоты, предположим, что DIT, которое мы хотим реплицировать, определяется записью olcDatabase={1}bdb,cn=config, то задачу добавления наложения syncprov в качестве дочерней по отношению к ней записи будет решать следующий LDIF:
dn: olcOverlay=syncprov, olcDatabase={1}bdb,cn=config objectclass: olcSyncProvConfig olcOverlay: syncprov olcSpCheckpoint: 100 10
Примечания:
Для создания этой записи единственным обязательным (MUST) атрибутом является olcOverlay. Все остальные атрибуты могут быть добавлены позднее, если это имеет значение. Полный список атрибутов объектного класса olcSyncProvConfig можно посмотреть здесь. У этого специфичного для наложения объектного класса есть вышестоящий (SUP) класс olcOverlayConfig, список атрибутов которого можно посмотреть здесь.
После создания дочерней записи её DN будет olcOverlay={0}syncprov,olcDatabase={1}bdb,cn=config (подразумевается, что это первое наложение для рассматриваемого DIT). Индекс {0} будет назначен при добавлении записи. Тут можно узнать, что же означает эта цифра в фигурных скобках, если Вам очень этого хочется.
Использование LDIF — один из многих способов работы с OLC DIT. В качестве альтернативы можно использовать любой адекватный LDAP-браузер общего назначения или специализированные утилиты настройки OLC (cn=config), которые начали появляться в последнее время.
Если наложение syncprov собрано в виде динамически загружаемого модуля (политики сбора пакетов различных дистрибутивов Linux отличаются в этом вопросе), то соответствующие изменения должны быть внесены в запись cn=module{0},cn=config прежде чем добавлять дочернюю запись наложения syncprov. Добавление/удаление модулей с использованием OLC описано тут.
Общая организация OLC (cn=config) описывается отдельно. Более подробное описание добавления наложений здесь.
Конфигурация подчинённого сервера (потребителя): Необходимо добавить атрибут olcSyncrepl в определение olcDatabase DIT, содержащего реплику. Само собой, запись olcDatabase, в которую мы будем добавлять настройки репликации, должна к этому времени существовать. Первый фрагмент LDIF создаёт запись olcDatabase, если её ещё не существовало. Второй фрагмент LDIF просто добавляет в существующую запись атрибут olcSynrepl.
Создаём запись olcDatabase, если таковой не существует:
# Порядковый номер {} не указан, поэтому запись будет # добавлена в конец текущего списка баз данных. # Следует сменить тип olcDatabase на тот, который # реально используется, и соответствующим образом изменить # objectClass: olcBdbConfig dn: olcDatabase=bdb,cn=config objectClass: olcBdbConfig olcDatabase: bdb olcDbDirectory: /var/db/new-db olcSuffix: dc=example,dc=com
Примечания:
Полный список атрибутов объектного класса olcBdbConfig можно посмотреть здесь. У этого специфичного для базы данных bdb объектного класса есть вышестоящий (SUP) класс olcDatabaseConfig, список атрибутов которого можно посмотреть здесь.
Обязательными (MUST) атрибутами являются olcDatabase и olcDbDirectory. Указываемая в olcDbDirectory директория должна существовать и иметь надлежащие разрешения до запуска данного LDIF.
Атрибут olcSuffix не является обязательным, но без него запись добавляться не будет. Имейте ввиду.
Дополнительные атрибуты могут быть добавлены как при создании записи, так и в любой момент в дальнейшем. Сюда входят в том числе и такие очевидные атрибуты как olcRootDn и olcRootPw.
Если механизм манипуляции данными bdb собран в виде динамически загружаемого модуля (политики сбора пакетов различных дистрибутивов Linux отличаются в этом вопросе), то соответствующие изменения должны быть внесены в запись cn=module{0},cn=config прежде чем добавлять дочернюю запись базы данных. Добавление/удаление модулей с использованием OLC описано тут.
Общая организация OLC (cn=config) описывается отдельно. Более подробное описание добавления баз данных здесь.
Будем считать, что DIT, репликацию которого необходимо выполнять, определено записью olcDatabase={1}bdb. Добавление атрибута olcSyncrepl показано в следующем фрагменте LDIF:
# ПРИМЕЧАНИЕ: строки ниже, начинающиеся со знака # являются # комментариями-пояснениями и должны быть удалены # перед запуском данного LDIF dn: olcDatabase={1},cn=config changetype: modify add:olcSyncrepl olcSyncrepl: {0}rid=000 provider=ldap://master-ldap.example.com # замените на type=refreshonly если этот стиль предпочтительнее type=refreshAndPersist retry="5 5 300 +" searchbase="dc=example,dc=com" # требуются как пользовательские (*), так и операционные (+) атрибуты attrs="*,+" bindmethod=simple binddn="cn=admin,ou=people,dc=example,dc=com" # предупреждение: пароль посылается в открытом виде - небезопасно credentials=dirtysecret
Примечания:
Не выдвигается строгого требования указывать значение {0} в строке olcSyncrepl: {0}rid=000, если это первый атрибут olcSyncrepl в записи. Его можно опустить, и при добавлении атрибуту будет присвоено значение {0}. Однако, если в запись добавляется ещё один атрибут olcSyncrepl без указания его порядкового номера, то вместо того, чтобы выделить атрибуту следующий по порядку номер, добавление такого атрибута будет отклонено. Тут можно узнать, что же означает эта цифра в фигурных скобках, если Вам очень этого хочется.
Необязательный атрибут olcUpdateref (добавляется в глобальную запись cn=config) может быть использован для отсылки какого-либо клиента, пытающегося выполнить операцию записи (модификации) в подчинённом DIT (потребителе, который всегда доступен только для чтения) на соответствующий главный сервер (поставщика).
В этом примере репликация настраивается с использованием файла slapd.conf. Конфигурация slapd.conf главного сервера (подразумевается, что имя хоста master-ldap.example.com):
# slapd поставщика (главного сервера) # раздел глобальных настроек ... # раздел database database bdb ... # разрешаем потребителю доступ на чтение # может понадобиться слияние с другими ACL # указанный dn.base должен совпадать с параметром binddn= потребителя # access to * by dn.base="cn=admin,ou=people,dc=example,dc=com" read by * break # Примечание: # конфигурация поставщика не содержит данных о потребителях # указываем поставщику использовать наложение syncprov # (заключительные директивы в разделе database) overlay syncprov # contextCSN сохраняется в базу данных # через каждые 100 обновлений или 10 минут syncprov-checkpoint 100 10
Конфигурация slapd.conf потребителя:
# slapd потребителя # раздел глобальных настроек # раздел database database bdb ... # поставщик - ldap://master-ldap.example.com:389, # полное DIT (searchbase), синхронизируются все пользовательские атрибуты # простой уровень безопасности с паролем в открытом виде # Примечание: комментарии внутри директивы syncrepl приводят к ошибкам OpenLDAP # и приведены здесь лишь с целью дополнительных пояснений. # Их НЕ ДОЛЖНО быть в рабочем файле syncrepl rid=000 provider=ldap://master-ldap.example.com # замените на type=refreshonly если этот стиль предпочтительнее type=refreshAndPersist retry="5 5 300 +" searchbase="dc=example,dc=com" # требуются как пользовательские (*), так и операционные (+) атрибуты attrs="*,+" bindmethod=simple binddn="cn=admin,ou=people,dc=example,dc=com" # предупреждение: пароль посылается в открытом виде - небезопасно credentials=dirtysecret
Примечание: Необязательная директива updateref может быть использована для отсылки какого-либо клиента, пытающегося выполнить операцию записи (модификации) в подчинённом DIT (потребителе, который всегда доступен только для чтения) на соответствующий главный сервер (поставщика).
В OpenLDAP 2.4 представлена поддержка разнонаправленной репликации с несколькими главными серверами. При такой конфигурации любое количество главных серверов может синхронизироваться друг с другом. Функциональность репликации была описана ранее для типов refreshOnly и refreshAndPersist и здесь мы не станем повторяться. Приведённые далее заметки и примеры конфигурации относятся только к разнонаправленной репликации с несколькими главными серверами.
Примечание: Для разнонаправленной репликации с несколькими главными серверами жизненно необходимо, чтобы системное время на всех главных серверах (поставщиках) было синхронизировано с одним и тем же источником времени, например, на всех серверах должен быть запущен NTP (Network Time Protocol).
При разнонаправленной репликации с несколькими главными серверами каждый поставщик сервиса синхронизации является также потребителем сервиса синхронизации, как показано на рисунке 7.2-4:
Рисунок 7.2-4: Разнонаправленная репликация syncrepl с несколькими главными серверами
На рисунке 7.2-4 показана конфигурация разнонаправленной репликации с тремя главными серверами (1, 2, 3). Каждый главный сервер сконфигурирован (5, 6, 7) как поставщик (с помощью наложения syncprov) и как потребитель для всех остальных главных серверов (с помощью атрибутов olcSyncrepl (директив syncrepl)). Каждый поставщик должен быть уникально идентифицирован с помощью атрибута olcServerID (директивы ServerID). Кроме того, все поставщики, как уже было сказано, должны быть синхронизированы с одним источником времени. Итак, в конфигурации DIT (4) поставщика (1) содержатся настройки наложения syncprov (наложения поставщика) и два определения атрибута olcSyncrepl (директивы syncrepl) типа refreshAndPersist, по одному для каждого из двух других поставщиков (2, 3), как показано голубыми соединительными линиями. Два других поставщика имеют аналогичную конфигурацию — настройку поставщика и два атрибута olcSyncrepl (директивы syncrepl) типа refreshAndPersist для соответствующих других двух главных серверов (поставщиков).
В данной конфигурации подразумевается использование типа синхронизации refreshAndPersist (непонятно, что может сподвигнуть Вас даже подумать об использовании типа refreshOnly, но и такое возможно), поэтому изменения содержимого каталога любого из главных серверов будут немедленно распространены на все остальные главные серверы (серверы-поставщики), выступающие в этом случае в роли подчинённых серверов (потребителей).
В настоящий момент разнонаправленная репликация с несколькими главными серверами в версии 2.4 не поддерживает delta-синхронизацию.
Напоминаем, что каждое DIT будет выступать и как главное дерево (поставщик), и как подчинённое дерево (потребитель) по отношению ко всем остальным серверам в конфигурации с тремя (в данном примере) главными серверами. Подразумевается, что три наших сервера — это ldap1.example.com, ldap2.example.com и ldap3.example.com (знаем-знаем, фантазия не блещет).
Конфигурация главных серверов (поставщиков): к записям olcDatabase с определениями DIT, выступающими в роли главного дерева (поставщика) в разнонаправленной репликации с несколькими главными серверами, нужно добавить дочернюю запись наложения syncprov. Если мы, для простоты, предположим, что все наши DIT определяются записями olcDatabase={1}bdb,cn=config, то задачу добавления наложения syncprov к каждому из главных DIT в качестве дочерней записи будет решать следующий LDIF:
dn: olcOverlay=syncprov, olcDatabase={1}bdb,cn=config objectclass: olcSyncProvConfig olcOverlay: syncprov olcSpCheckpoint: 100 10
Примечания:
Подразумевается, что запись olcDatabase уже существует. Если это не так, создайте её с помощью описанной здесь процедуры.
Для создания этой дочерней записи единственным обязательным (MUST) атрибутом является olcOverlay. Все остальные атрибуты могут быть добавлены позднее, если это имеет значение. Полный список атрибутов объектного класса olcSyncProvConfig можно посмотреть здесь. У этого специфичного для наложения объектного класса есть вышестоящий (SUP) класс olcOverlayConfig, список атрибутов которого можно посмотреть здесь.
После создания дочерней записи её DN будет olcOverlay={0}syncprov,olcDatabase={1}bdb,cn=config (подразумевается, что это первое наложение для рассматриваемого DIT). Индекс {0} будет назначен автоматически при добавлении записи. Тут можно узнать, что же означает эта цифра в фигурных скобках, если Вам очень этого хочется.
Использование LDIF — один из многих способов работы с OLC DIT. В качестве альтернативы можно использовать любой адекватный LDAP-браузер общего назначения или специализированные утилиты настройки OLC (cn=config), которые начали появляться в последнее время.
Если наложение syncprov собрано в виде динамически загружаемого модуля (политики сбора пакетов различных дистрибутивов Linux отличаются в этом вопросе), то, прежде чем добавлять дочернюю запись наложения syncprov, в запись cn=module{0},cn=config должен быть добавлен соответствующий атрибут загрузки модуля.
Общая организация OLC (cn=config) описывается отдельно. Более подробное описание добавления наложений здесь.
Конфигурация подчинённых серверов (потребителей): и снова напомним, что каждый из наших серверов будет одновременно и главным (поставщиком) и подчинённым (потребителем) для каждого из трёх главных серверов. Следующий LDIF-файл вносит изменения в настройки ldap1.example.com:
dn: cn=config changetype: modify add: olcServerId olcServerId: 1 dn: olcDatabase={1}bdb,cn=config changetype: modify add: olcSyncrepl olcsyncrepl: {0}rid=000 provider=ldap://ldap2.example.com type=refreshAndPersist retry="5 5 300 +" searchbase="dc=example,dc=com" attrs="*,+" bindmethod=simple binddn="cn=admin,ou=people,dc=example,dc=com" credentials=dirtysecret olcsyncrepl: {1}rid=001 provider=ldap://ldap3.example.com type=refreshAndPersist retry="5 5 300 +" searchbase="dc=example,dc=com" attrs="*,+" bindmethod=simple binddn="cn=admin,ou=people,dc=example,dc=com" credentials=dirtysecret - add: olcAccess olcAccess: {x}to * by dn.base="cn=admin,ou=people,dc=example,dc=com" read by * break - add: olcDbIndex olcDbIndex: entryUUID eq olcDbIndex: entryCSN eq - replace: olcMirrorMode olcMirrorMode: TRUE
Примечания:
olcServerID всегда определяется в записи cn=config (это атрибут объектного класса olcGlobal).
Атрибуты olcDbIndex являются опциональными, но могут помочь ускорить обработку при поиске за счёт использования индексов.
Атрибут olcAccess необходим на каждом из поставщиков для предоставления полномочий доступа на чтение соответствующих фрагментов DIT (в данном случае всего DIT). Он приведён со значением порядкового номера {x} чтобы показать, что Вы должны самостоятельно выбрать необходимое значение для вставки данного правила в нужное место последовательности уже имеющихся атрибутов olcAccess. Если это первый или единственный атрибут olcAccess, Вы можете либо использовать значение {0}, либо вообще опустить его и тогда при добавлении атрибуту будет назначено то же значение {0}. Если добавление этого атрибута повлечёт за собой значительную перетасовку существующих атрибутов olcAccess, то простым, но более грубым решением может стать определение правила на глобальном уровне (если это не нарушит каких-либо политик безопасности) путём добавления этого атрибута в запись cn=config. В этом случае его нужно переместить выше в часть dn: cn=config данного LDIF.
Поскольку все главные серверы реплицируют одно и то же DIT, в нашем примере параметр binddn имеет одинаковое значение во всех направлениях. Это вполне допустимо. Однако, при успешном взломе одного из серверов, все остальные также будут взломаны. Возможно, более безопасная стратегия — использовать уникальный параметр binddn для каждого сервера. Для этого потребуется внести изменения в атрибуты olcSyncrepl и olcAccess.
Каждый параметр rid атрибутов olcSyncrepl должен быть уникальным в пределах DIT cn=config (то есть в пределах одного сервера). Значение olcServerId должно быть уникальным для каждого сервера (то есть среди всех серверов). Зависимостей между значениями rid и olcServerId нет.
Для конфигураций с несколькими главными серверами требуется (до сих пор, хотя и не ясно зачем) атрибут olcMirrormode: true. Отсутствие этого атрибута в какой-либо из конфигураций главного сервера приведёт к тому, что все операции записи будут завершаться неудачей!
Аналогичный LDIF может быть использован для всех трёх наших серверов. Нужно поменять значения атрибута olcServerId, чтобы оно отражало уникальный номер сервера (скажем, 2 и 3). Кроме того, нужно поменять параметры provider атрибутов olcSynrepl так, чтобы они отражали те LDAP-серверы, которые выступают в качестве главных (поставщиков) для каждой роли подчинённого сервера (потребителя).
Когда сервер настраивается как часть конфигурации с несколькими главными серверами, состояние его DIT не имеет принципиального значения. На самом деле в нашем примере с тремя серверами у одного или даже двух из них могут быть пустые DIT. Первоначальное соединение в любой паре потребитель-поставщик приведёт к первичной синхронизации. Подробнее смотрите в разделе syncrepl refreshAndPersist выше.
Для конфигураций с несколькими главными серверами требуется, чтобы на всех серверах было одинаковое время. Все серверы должны быть клиентами NTP, ссылающимися на один и тот же источник времени. Недостаточно просто использовать команду ntpdate при загрузке сервера или другой подобный метод, поскольку погрешность часов может быть на удивление большой.
Внесение изменений в каталог — один из болезненных вопросов репликации с несколькими главными серверами. Для осуществления этой операции в OpenLDAP используются метки времени. Так, если обновление одного и того же атрибута (атрибутов) происходит примерно в одно и то же время (с учётом времени распространения) на разных серверах, то одно из обновлений для запрашиваемого атрибута будет потеряно. Потерянным будет обновление с меньшим значением отметки времени — хотя разница может составлять всего лишь миллисекунды. Это неизбежный побочный эффект репликации с несколькими главными серверами. NTP позволяет свести к минимуму возникновение этой проблемы.
Подразумевается три главных сервера (ldap1.example.com, ldap2.example.com и ldap3.example.com), использующих разнонаправленную репликацию syncrepl с несколькими главными серверами. У них будут такие файлы slapd.conf:
slapd.conf для ldap1.example.com:
# slapd главного сервера ldap1.example.com # раздел глобальных настроек ... # уникальный идентификатор данного сервера serverID 001 # раздел database database bdb ... # разрешаем доступ на чтение всем потребителям # подразумевается, что на всех главных серверах будет использоваться binddn с этим значением # может понадобиться слияние с другими ACL access to * by dn.base="cn=admin,ou=people,dc=example,dc=com" read by * break # Примечание: # директивы syncrepl для каждого из остальных главных серверов # поставщик - ldap://ldap2.example.com:389, # полное DIT (searchbase), синхронизируются все пользовательские и операционные атрибуты # простой уровень безопасности с паролем в открытом виде syncrepl rid=000 provider=ldap://ldap2.example.com type=refreshAndPersist retry="5 5 300 +" searchbase="dc=example,dc=com" attrs="*,+" bindmethod=simple binddn="cn=admin,ou=people,dc=example,dc=com" credentials=dirtysecret # поставщик - ldap://ldap3.example.com:389, # полное DIT (searchbase), синхронизируются все пользовательские и операционные атрибуты # простой уровень безопасности с паролем в открытом виде syncrepl rid=001 provider=ldap://ldap3.example.com type=refreshAndPersist retry="5 5 300 +" searchbase="dc=example,dc=com" attrs="*,+" bindmethod=simple binddn="cn=admin,ou=people,dc=example,dc=com" credentials=dirtysecret ... # индексы, специфичные для syncprov (добавьте другие по необходимости) index entryCSN eq index entryUUID eq ... # зеркальный режим необходим для того, чтобы разрешить запись # эта директива должна определяться после всех директив syncrepl mirrormode TRUE # указываем поставщику использовать наложение syncprov # (заключительные директивы в разделе database) overlay syncprov # contextCSN сохраняется в базу данных # через каждые 100 обновлений или 10 минут syncprov-checkpoint 100 10
slapd.conf для ldap2.example.com:
# slapd главного сервера ldap2.example.com # раздел глобальных настроек ... # уникальный идентификатор данного сервера ServerID 002 # раздел database database bdb ... # разрешаем доступ на чтение всем потребителям # подразумевается, что на всех главных серверах будет использоваться binddn с этим значением # может понадобиться слияние с другими ACL access to * by dn.base="cn=admin,ou=people,dc=example,dc=com" read by * break # Примечание: # директивы syncrepl для каждого из остальных главных серверов # поставщик - ldap://ldap1.example.com:389, # полное DIT (searchbase), синхронизируются все пользовательские и операционные атрибуты # простой уровень безопасности с паролем в открытом виде syncrepl rid=000 provider=ldap://ldap1.example.com type=refreshAndPersist retry="5 5 300 +" searchbase="dc=example,dc=com" attrs="*,+" bindmethod=simple binddn="cn=admin,ou=people,dc=example,dc=com" credentials=dirtysecret # поставщик - ldap://ldap3.example.com:389, # полное DIT (searchbase), синхронизируются все пользовательские и операционные атрибуты # простой уровень безопасности с паролем в открытом виде syncrepl rid=001 provider=ldap://ldap3.example.com type=refreshAndPersist retry="5 5 300 +" searchbase="dc=example,dc=com" attrs="*,+" bindmethod=simple binddn="cn=admin,ou=people,dc=example,dc=com" credentials=dirtysecret ... # зеркальный режим необходим для того, чтобы разрешить запись # эта директива должна определяться после всех директив syncrepl mirrormode TRUE # индексы, специфичные для syncprov (добавьте другие по необходимости) index entryCSN eq index entryUUID eq ... # указываем поставщику использовать наложение syncprov # (заключительные директивы в разделе database) overlay syncprov # contextCSN сохраняется в базу данных # через каждые 100 обновлений или 10 минут syncprov-checkpoint 100 10
slapd.conf для ldap3.example.com:
# slapd главного сервера ldap3.example.com # раздел глобальных настроек ... # уникальный идентификатор данного сервера ServerID 003 # раздел database database bdb ... # разрешаем доступ на чтение всем потребителям # подразумевается, что на всех главных серверах будет использоваться binddn с этим значением # может понадобиться слияние с другими ACL access to * by dn.base="cn=admin,ou=people,dc=example,dc=com" read by * break # Примечание: # директивы syncrepl для каждого из остальных главных серверов # поставщик - ldap://ldap1.example.com:389, # полное DIT (searchbase), синхронизируются все пользовательские и операционные атрибуты # простой уровень безопасности с паролем в открытом виде syncrepl rid=000 provider=ldap://ldap1.example.com type=refreshAndPersist retry="5 5 300 +" searchbase="dc=example,dc=com" attrs="*,+" bindmethod=simple binddn="cn=admin,ou=people,dc=example,dc=com" credentials=dirtysecret # поставщик - ldap://ldap2.example.com:389, # полное DIT (searchbase), синхронизируются все пользовательские и операционные атрибуты # простой уровень безопасности с паролем в открытом виде syncrepl rid=001 provider=ldap://ldap2.example.com type=refreshAndPersist retry="5 5 300 +" searchbase="dc=example,dc=com" attrs="*,+" bindmethod=simple binddn="cn=admin,ou=people,dc=example,dc=com" credentials=dirtysecret # индексы, специфичные для syncprov (добавьте другие по необходимости) index entryCSN eq index entryUUID eq # зеркальный режим необходим для того, чтобы разрешить запись # эта директива должна определяться после всех директив syncrepl mirrormode TRUE # указываем поставщику использовать наложение syncprov # (заключительные директивы в разделе database) overlay syncprov # contextCSN сохраняется в базу данных # через каждые 100 обновлений или 10 минут syncprov-checkpoint 100 10
Примечания:
Поскольку все главные серверы реплицируют одно и то же DIT, в данном примере показано, что значения параметра binddn в директивах syncrepl одни и те же. Это вполне допустимо. Однако, при успешном взломе одного из серверов, все остальные также будут взломаны. Возможно, более безопасная стратегия — использовать разные записи в качестве binddn для каждого сервера. Для этого потребуется внести изменения в директивы syncrepl и access to.
Каждый параметр rid директивы syncrepl должен быть уникальным в пределах файла slapd.conf (то есть в пределах одного сервера). Значение serverid должно быть уникальным для каждого сервера. Зависимостей между значениями rid и serverid нет.
Для конфигураций с несколькими главными серверами требуется (до сих пор, хотя и не ясно зачем) директива mirrormode true. Она должна присутствовать после всех директив syncrepl в разделе database. Отсутствие этой директивы в какой-либо из конфигураций главного сервера приведёт к тому, что все операции обновления будут завершаться неудачей.
Для конфигураций с несколькими главными серверами требуется, чтобы на всех серверах было одинаковое время. Все серверы должны быть клиентами NTP, ссылающимися на один и тот же источник времени. Недостаточно просто использовать команду ntpdate при загрузке сервера или другой подобный метод, поскольку погрешность часов на разных серверах может быть на удивление большой.
Внесение изменений в каталог — один из болезненных вопросов репликации с несколькими главными серверами. Для осуществления этой операции в OpenLDAP используются метки времени. Так, если обновление одного и того же атрибута (атрибутов) происходит примерно в одно и то же время (с учётом времени распространения) на разных серверах, то одно из обновлений для запрашиваемого атрибута (атрибутов) будет потеряно. Потерянным будет обновление с меньшим значением отметки времени — хотя разница может составлять всего лишь миллисекунды. Это неизбежный побочный эффект репликации с несколькими главными серверами. NTP позволяет свести к минимуму возникновение этой проблемы.
Итак, до этого момента всё было на удивление просто. Теперь же добавим немного чёрной магии. И всё в интересах сокращения трафика между поставщиком и потребителем.
При синхронизации в режиме refreshOnly промежуток времени до распространения обновлений может быть значительным — в зависимости от значения параметра interval определения olcSyncrepl/syncrepl. Для уменьшения интервала между синхронизациями обновлений (чтобы минимизировать задержки распространения) эффективнее применять режим refreshAndPersist, но и в этом случае при каждом повторном подключении происходит начальная синхронизация всего каталога. Если в процессе синхронизации требуется выполнение фазы наличия, то, даже если с момента последней синхронизации изменения не происходили, каждая неизменённая запись всё равно будет отправлена в виде пустой записи (со своим идентификатором entryUUID), и такая синхронизация может занять значительное время.
В режиме refreshAndPersist пересинхронизация происходит только при начальном соединении (повторные соединения происходят только после крупных сбоев поставщика, потребителя или сети). Однако даже в этом режиме обновление какого-нибудь одного атрибута в записи приводит к тому, что данная запись передаётся целиком. Если в очень большой записи изменяется всего один атрибут, накладные расходы на пересылку получаются несоразмерно велики.
Наконец, непродуманные реализации LDAP могут создавать проблемы при обновлении. Для иллюстрации худшего варианта предположим, что есть приложение, которое выполняется раз в день и вносит изменения размером в 1 байт в каждую запись в DIT (скажем, записывает номер текущего дня недели). Это приведёт к тому, что всем потребителям репликации будет рассылаться всё DIT целиком. Это, пожалуй, не слишком удобно, а порой даже и неосуществимо за промежуток в 24 часа.
Для решения этих проблем OpenLDAP предоставляет два метода: журнал сессии (session log) и журнал доступа (access log). Цель обоих методов — минимизировать передачу данных, а в случае журналов доступа — реализовать так называемую delta-синхронизацию (пересылку только изменений записи, а не всей записи).
Наложение syncprov предоставляет возможность вести журнал сессии. Параметр журнала сессии имеет следующую форму:
olcSpSessionlog: ops # OLC (cn=config) syncprov-sessionlog ops # slapd.conf # здесь ops определяет количество операций, которые могут быть сохранены # при заполнении журнала старые операции удаляются # Примечание: в версии 2.3 был параметр sid, но в 2.4 он был удалён # LDIF для добавления дочерней записи syncprov # к записи olcDatabase={1}bdb dn: olcOverlay=syncprov, olcDatabase={1}bdb,cn=config objectclass: olcSyncProvConfig olcOverlay: syncprov olcSpSessionlog: 100 olcSpCheckpoint: 100 10 # пример определения syncprov в slapd.conf # с журналом сессии на 100 записей (изменений) overlay syncprov syncprov-checkpoint 100 10 syncprov-sessionlog 100
Журнал сессии — это журнал, размещаемый в оперативной памяти и содержащий сведения о всех выполненных операциях (за исключением операций добавления add). В зависимости от того, изменения за какой промежуток времени хранятся в журнале сессии на момент начала синхронизации, он может позволить поставщику пропустить необязательную фазу наличия и таким образом значительно ускорить процесс синхронизации. Например, если с момента последней синхронизации в журнале сессии не зафиксировано новых изменений, в фазе наличия нет нужды. Журнал сессии может использоваться с любым режимом репликации (refreshOnly или refreshAndPersist), но больше пользы он приносит при режиме refreshOnly. Если журнал сессии недостаточно велик, чтобы покрыть все изменения с момента последнего запроса на синхронизацию от потребителя, то будет выполняться полная последовательность действий по пересинхронизации (включая фазу наличия). Для использования журнала сессии не требуется указания никаких специальных параметров в атрибуте olcSyncrepl (директиве syncrepl) на стороне потребителя.
Журнал доступа accesslog позволяет вести журнал операций LDAP целевого DIT в связанном, но отдельном accesslog DIT. Функциональность accesslog обеспечивается наложением accesslog.
В нормальном случае, операция синхронизации реплики производит обновления, используя информацию из того DIT, к которому выполняется поисковый запрос, содержащийся в запросе синхронизации (при первоначальном подключении потребителя). Вместо этого можно выполнять синхронизацию, перенацелив атрибут olcSyncrepl (директиву syncrepl) на журнал доступа accesslog. Поскольку объекты, хранящиеся в журнале доступа, содержат только изменения (в том числе операции удаления, добавления, переименования и изменения rdn записей), объём данных получается значительно ниже, нежели при выполнении полной операции синхронизации на основном DIT (или даже на фрагменте DIT), когда при изменении любого атрибута запись пересылается целиком. Использование accesslog известно как delta-репликация или delta-синхронизация, и даже как delta-syncrepl.
Вопрос о том, стоит ли использовать эту достаточно сложную конфигурацию, должен оцениваться в свете операционных деталей. В общем случае, игра (возможно) будет стоить свеч, если соблюдаются одно или несколько из следующих условий:
Размеры записей, в среднем, больше чем 20Kb;
Примерный объём изменяемых записей в день или в период каких-либо пиковых нагрузок больше чем 20% DIT, и, при этом, каждая запись изменяется не больше чем, скажем, на 50%;
Сеть либо имеет ограниченную пропускную способность, либо перегружена.
Для того, чтобы использовать данную форму репликации, требуется определить accesslog DIT на поставщике и параметры logbase, logfilter и syncdata атрибута olcSyncrepl (директивы syncrepl) на потребителе, как показано в примере ниже.
В этом примере подразумевается, что имя главного сервера (поставщика) — ldap1.example.com, а имя подчинённого сервера (потребителя) — ldap2.example.com. Конечно, этот пример мог бы быть также применим и в конфигурации разнонаправленной репликации с несколькими главными серверами, добавляя ей некоторую сложность, но увы, в настоящий момент (версия OpenLDAP 2.4.35) для репликаций с несколькими главными серверами delta-синхронизация не поддерживается.
Конфигурация главного сервера (поставщика)
Следующий фрагмент LDIF расширяет существующую конфигурацию, в которой подразумевается наличие записи olcDatabase={1}bdb,cn=config (измените значение {Z} и тип базы данных так, как Вам требуется). Если этой базы данных (DIT) ещё не существует, используйте эту процедуру для её добавления. В LDIF было помещено несколько поясняющих комментариев, которые, при желании, можно опустить:
# slapd поставщика ldap1.example.com # запись глобальных настроек # Разрешаем потребителю доступ на чтение к целевому DIT и accesslog DIT. # В данной форме применяется глобальное правило доступа. # Указываемый DN ДОЛЖЕН совпадать с тем, который используется в # параметре binddn атрибута olcSyncrepl потребителя dn: cn=config changetype: modify add: olcAccess olcAccess: {x} to * by dn.base="cn=admin,ou=people,dc=example,dc=com" read by * break # индексы, специфичные для syncprov (добавьте другие по необходимости) # их определение не обязательно, но помогает повысить производительность dn: olcDatabase={1}bdb,cn=config changetype: modify add: olcDbIndex olcDbIndex: entryCSN eq olcDbIndex: entryUUID eq # определяем запись наложения accesslog и её атрибуты # ежедневная чистка accesslog: # удаляем записи старше двух дней # заносим в журнал операции записи writes (включаются add, delete, modify, modrdn) # заносим в журнал только успешные операции # accesslog DIT имеет суффикс cn=deltalog dn: olcOverlay={0}accesslog,olcDatabase={1}bdb,cn=config objectclass: olcAccessLogConfig olcOverlay: {0}accesslog olcAccessLogDb: cn=deltalog olcAccessLogOps: writes olcAccessLogSuccess: TRUE olcAccessLogPurge: 2+00:00 1+00:00 # добавляем дочернюю запись наложения syncprov # (последняя дочерняя запись) # contextCSN сохраняется в базу данных # через каждые 100 обновлений или 10 минут dn: olcOverlay={1}syncprov, olcDatabase={1}bdb,cn=config objectclass: olcSyncProvConfig olcOverlay: {1}syncprov olcSpCheckpoint: 100 10 # Теперь создадим запись accesslog DIT. # Нормальное определение базы данных. dn: olcDatabase={2}bdb,cn=config objectClass: olcBdbConfig olcDatabase: bdb olcSuffix: cn=deltalog olcDbDirectory: /var/db/delta olcDbIndex: entryCSN,objectClass, reqEnd, reqResult, reqStart eq # accesslog DIT также будет поставщиком # olcSpNoPresent подавляет фазу наличия при синхронизации # olcSpReloadHint TRUE обязательно при delta-синхронизации dn: olcOverlay={0}syncprov, olcDatabase={2}bdb,cn=config objectclass: olcSyncProvConfig olcOverlay: {0}syncprov olcSpCheckpoint: 100 10 olcSpNoPresent: TRUE olcSpReloadHint: TRUE
Примечания:
Полный перечень атрибутов объектного класса olcAccessLogConfig здесь.
В примере показано, что атрибут olcAccess добавляется в глобальную запись cn=config. Если это первый атрибут olcAccess, то {x} можно опустить или установить в {0}. Точно также этот атрибут olcAccess может быть добавлен (в корректном порядке) и в запись olcDatabase={1}bdb,cn=config.
Конфигурация подчинённого сервера (потребителя)
В данном примере подразумевается, что запись базы данных существует и её dn — olcDatabase={1}bdb,cn=config (измените на нужное Вам). Если это не так, используйте эту процедуру для добавления записи базы данных. Следующий фрагмент LDIF просто добавляет атрибут olcSyncrepl к существующей конфигурации:
dn: olcDatabase={1}bdb,cn=config changetype: modify add: olcSyncrepl olcSyncRepl: {0}rid=000 provider=ldap://ldap1.example.com type=refreshAndPersist retry="5 5 300 +" searchbase="dc=example,dc=com" attrs="*,+" bindmethod=simple binddn="cn=admin,ou=people,dc=example,dc=com" credentials=dirtysecret logbase="cn=deltalog" logfilter="(&(objectClass=auditWriteObject)(reqResult=0))" syncdata=accesslog
Примечания:
Поиск с фильтром ("(&(objectClass=auditWriteObject)(reqResult=0))"), указанным в параметре logfilter, считывает все стандартные записи в базе данных accesslog, которые имеют статус успешного выполнения (reqResult=0). Поскольку в настройках поставщика мы определили, что заноситься в журнал будут только записи успешных операций (olcAccessLogSuccess: TRUE), теоретически, это требование избыточно, тем не менее, оно не повредит.
Сервер-потребитель может быть запущен с пустым DIT, в этом случае первоначально произойдёт нормальная синхронизация, а затем выполнение последующих обновлений будет происходить через механизм accesslog.
При передаче изменений, зафиксированных в accesslog, потребителю предоставляется новое значение атрибута, а также значения entryCSN, modifiersName (DN) и modifyTimestamp. Последние три атрибута являются операционными и требуются для обеспечения точной копии DIT в реплике.
Конфигурация поставщика (подразумевается, что имя хоста ldap1.example.com):
# slapd поставщика ldap1.example.com # раздел глобальных настроек ... # Разрешаем потребителю доступ на чтение к целевому DIT и accesslog DIT. # В данной форме применяется глобальное правило доступа. # Указываемый DN ДОЛЖЕН совпадать с тем, который используется в # параметре binddn директивы syncrepl потребителя access to * by dn.base="cn=admin,ou=people,dc=example,dc=com" read by * break ... # раздел database - целевое DIT # с суффиксом dc=example,dc=com database bdb suffix "dc=example,dc=com" ... # индексы, специфичные для syncprov (добавьте другие по необходимости) # их определение не обязательно, но помогает повысить производительность index entryCSN,entryUUID eq ... # определяем наложение accesslog и его параметры # ежедневная чистка accesslog: # удаляем записи старше двух дней # заносим в журнал операции записи writes (включаются add, delete, modify, modrdn) # заносим в журнал только успешные операции # accesslog DIT имеет суффикс cn=deltalog overlay accesslog logdb "cn=deltalog" logops writes logsuccess TRUE logpurge 2+00:00 1+00:00 # указываем поставщику использовать наложение syncprov # (заключительные директивы в разделе database) overlay syncprov # contextCSN сохраняется в базу данных # через каждые 100 обновлений или 10 минут syncprov-checkpoint 100 10 # Теперь определяем accesslog DIT # нормальное определение database database bdb ... suffix "cn=deltalog" # это рекомендуется для оптимизации accesslog index default eq index entryCSN,objectClass,reqEnd,reqResult,reqStart ... # accesslog DIT также будет поставщиком # syncprov-nopresent подавляет фазу наличия при синхронизации # syncprov-reloadhint TRUE обязательно при delta-синхронизации overlay syncprov syncprov-nopresent TRUE syncprov-reloadhint TRUE
Конфигурация потребителя:
# slapd потребителя ldap2.example.com # раздел глобальных настроек ... # раздел database database bdb suffix "dc=example,dc=com" ... # Примечание: # директива syncrepl будет использовать accesslog # для delta-синхронизации # поставщик - ldap://ldap1.example.com:389, # полное DIT (searchbase), синхронизируются все пользовательские атрибуты # простой уровень безопасности с паролем в открытом виде # binddn используется для авторизации доступа к поставщику # logbase ссылается на logdb (deltalog) поставщика # logfilter позволяет запрашивать успешные операции add, delete, modify, modrdn # syncdata указывает использовать формат accesslog syncrepl rid=000 provider=ldap://ldap1.example.com type=refreshAndPersist retry="5 5 300 +" searchbase="dc=example,dc=com" attrs="*,+" bindmethod=simple binddn="cn=admin,ou=people,dc=example,dc=com" credentials=dirtysecret logbase="cn=deltalog" logfilter="(&(objectClass=auditWriteObject)(reqResult=0))" syncdata=accesslog ...
Примечания:
Поиск с фильтром ("(&(objectClass=auditWriteObject)(reqResult=0))"), указанным в параметре logfilter, будет возвращать все стандартные записи в accesslog, содержащие сведения об успешных операциях (reqResult=0). Поскольку в конфигурации поставщика мы определили, что в accesslog будут помещаться сведения только об успешных операциях (logsuccess TRUE), теоретически этот фильтр избыточен, но и вреда не приносит.
Определение database для accesslog (cn=deltalog) на поставщике не содержит директив rootdn или rootpw, поскольку необходимости в них нет. Там также нет директив access to, что означает применение глобального ACL, определённого в начале файла slapd.conf поставщика. Указанному в этом ACL пользователю предоставлены минимальные права доступа и к целевому, и к accesslog DIT, однако требуется, чтобы такая запись реально существовала в целевом DIT. Использование rootdn и rootpw целевого DIT в качестве параметра binddn директивы syncrepl поставщика также будет работать (при условии, что глобальная директива access to будет удалена, а соответствующая директива access to добавлена в определение accesslog DIT), однако это подвергает привилегированного пользователя угрозе потенциальных атак прослушивания сетевого трафика и не рекомендуется.
Потребитель может быть запущен с пустым DIT, в этом случае сначала произойдёт нормальная синхронизация, по завершении которой последующие обновления будут синхронизироваться через механизм accesslog.
При распространении изменений, зафиксированных в accesslog, потребителю предоставляется значение нового атрибута, а также entryCSN, modifiersName (DN) и modifyTimestamp. Последние три атрибута являются операционными и требуются для поддержания точной копии DIT у потребителя.
Существует две возможные стратегии первоначального запуска репликации в стиле syncrepl:
Не делать ничего. После конфигурации потребителя нет необходимости предпринимать что-либо ещё. Первоначальный запрос синхронизации выполнит синхронизацию реплики из пустого состояния. Однако, если DIT очень велико, это может занять неприемлемо долгое время.
Загрузка LDIF-копии реплики с сервера-поставщика с помощью slapadd до запуска репликации. В зависимости от того, как выполнялась эта процедура, первоначальная синхронизация может быть минимальной, либо её вообще может не быть. Следующая инструкция описывает данный процесс. Подразумевается, что поставщик использует OpenLDAP 2.3+ и уже настроен на репликацию:
Сохраните LDIF-копию DIT поставщика (с помощью LDAP-браузера или даже slapcat, если используется механизм манипуляции данными BDB или HDB). Нет нужды останавливать сервер-поставщик, поскольку изменения, произошедшие во время сохранения или в промежутке между сохранением копии DIT и её загрузкой на сервер-потребитель, будут синхронизированы во время первоначальной репликации.
Скопируйте LDIF-файл на сервер-потребитель.
Сконфигурируйте сервер-потребитель на выполнение репликации.
Загрузите LDIF в каталог потребителя с помощью slapadd с опцией -w для создания SyncCookie с наиболее поздним временем внесения изменений. Пример:
slapadd -l /path/to/provider/copy/ldif -w
Запустите сервер-потребитель.
Выполните тестовую транзакцию либо на поставщике (в конфигурации главный-подчинённый), либо на одном из поставщиков (в конфигурации с несколькими главными серверами) и убедитесь, что изменения были распространены.
В случае конфигурации главный-подчинённый Вы, возможно, захотите добавить атрибут olcReferral (директиву referral) и/или атрибут olcUpdateref (директиву updateref).
Проблемы, комментарии, предположения, исправления (включая битые ссылки) или есть что добавить? Пожалуйста, выкроите время в потоке занятой жизни, чтобы написать нам, вебмастеру или в службу поддержки. Оставшийся день Вы проведёте с чувством удовлетворения.
Нашли ошибку в переводе? Сообщите переводчикам!
Copyright © 1994-2017 ZyTrax, Inc. Все права защищены. Последнее изменение страницы: 16 апреля 2018 г.
Переведено участниками проекта Pro-LDAP.ru в 2012-2014 г.