Хотел бы написать небольшую заметку о том как настроить репликацию OpenLDAP между несколькими серверами. Итак…

Дано:
1. Организация с филиалами. В главном офисе и в каждом филиале есть сервер LDAP который хранит у себя логины/пароли пользователей.

Задача:
Сделать так, что бы между главныи офисом и филиалами было «единое пространство имен», то есть что бы каждый LDAP сервер «знал» о логинах/паролях всех остальных филиалов и главного офиса.

Решение:
1. Установку Linux, OpenLDAP, настройку OpenVPN (главный офис и филиалы связаны через OpenVPN) описывать не буду. Будем считать что у вас это уже установлено и настроено.
2. У нас есть три сервера. Главный 192.168.1.1, и два филиала 192.168.1.2 и 192.168.1.3 соответственно. Все они связаны друг с другом через OpenVPN.

2. Теперь настройка OpenLDAP. В главном офисе (192.168.1.1) в LDAP заносятся все логины/пароли который нужны.

В файле slapd.conf главного сервера помимо всего прочего необходимо в самом начале добавить строку ServerID 001. Это идентификатор сервера.
Еще нужно раскоментировать строку moduleload syncprov.la. Это необходимо сделать для загрузки модуля синхронизации.

В файлах slapd.conf серверов филиала помимо всего прочего необходимо в самом начале добавить строку ServerID 002 и ServerID 003 соответственно. Это идентификатор сервера и раскоментировать строку moduleload syncprov.la. Это необходимо сделать для загрузки модуля синхронизации.

Далее. В файле slapd-hdb-db01.conf (файл настройки собственно базы), ПОСЛЕ описания типа БД, директории хранения базы и т. д. Добавляем следующие строки:

# это главный сервер. Имеет адрес 192.168.1.1. и такие строки должны быть добавлены для каждого из серверов (то есть в файле главного сервера должны быть добавлены строки для остальных филиалов).

# база для сервера 192.168.1.2
syncrepl rid=000
provider=ldap://192.168.1.2 # адрес сервера филиала
type=refreshAndPersist # тип обновления. После соединения потребителя и поставщика, происходит синхронизация, и по окончании синхронизации связь поддерживается. То есть соединение является постоянным
retry=«60 20 300 +» # повторы соединения. Здесь реконнект каждую минуту, для 20 попыток. После неудачных 20 попыток — новые реконнекты производить каждые 5 минут.
searchbase=«dc=test-1,dc=office,dc=com» # каталог который будет синхронизирован между серверами (в данном случае это весь каталог)
scope=sub # глубина поиска. В данном случае по всей области которая находится ниже относительно searchbase.
bindmethod=simple
binddn=«cn=admin,dc=test-1,dc=office,dc=com» # пользователь от имени которого будет производиться синхронизация. В данном случае это admin и его пароль который описан директивой ниже.
credentials=хххххххххх

# база для сервера 192.168.1.3
syncrepl rid=001
provider=ldap://192.168.1.3 # адрес сервера филиала
type=refreshAndPersist # тип обновления. После соединения потребителя и поставщика, происходит синхронизация, и по окончании синхронизации связь поддерживается. То есть соединение является постоянным
retry=«60 20 300 +» # повторы соединения. Здесь реконнект каждую минуту, для 20 попыток. После неудачных 20 попыток — новые реконнекты производить каждые 5 минут.
searchbase=«dc=test-1,dc=office,dc=com» # каталог который будет синхронизирован между срверами(в данном случае это весь каталог)
scope=sub # глубина поиска. В данном случае по всей области которая находится ниже относительно searchbase.
bindmethod=simple
binddn=«cn=admin,dc=test-1,dc=office,dc=com» # пользователь от имени которого будет производиться синхронизация. В данном случае это admin и его пароль который описан директивой ниже.
credentials=хххххххххх

ПОСЛЕ описания всех серверов добавляем строки
mirrormode TRUE # запись изменений на главном сервере. Без включения этой директивы вы не сможете сохранить изменения в своем каталоге LDAP.
overlay syncprov
syncprov-checkpoint 100 1
syncprov-sessionlog 100

Для сервера с адресом 192.168.1.2 соответственно строки относящиеся к синхронизации будут выглядеть так:

# база для сервера 192.168.1.1
syncrepl rid=000
provider=ldap://192.168.1.1# адрес главного сервера
type=refreshAndPersist # тип обновления. После соединения потребителя и поставщика, происходит синхронизация, и по окончании синхронизации связь поддерживается. То есть соединение является постоянным
retry=«60 20 300 +» # повторы соединения. Здесь реконнект каждую минуту, для 20 попыток. После неудачных 20 попыток — новые реконнекты производить каждые 5 минут.
searchbase=«dc=test-1,dc=office,dc=com» # каталог который будет синхронизирован между срверами(в данном случае это весь каталог)
scope=sub # глубина поиска. В данном случае по всей области которая находится ниже относительно searchbase.
bindmethod=simple
binddn=«cn=admin,dc=test-1,dc=office,dc=com» # пользователь от имени которого будет производиться синхронизация. В данном случае это admin и его пароль который описан директивой ниже.
credentials=хххххххххх

# база для сервера 192.168.1.3
syncrepl rid=001
provider=ldap://192.168.1.3 # адрес сервера филиала
type=refreshAndPersist # тип обновления. После соединения потребителя и поставщика, происходит синхронизация, и по окончании синхронизации связь поддерживается. То есть соединение является постоянным
retry=«60 20 300 +» # повторы соединения. Здесь реконнект каждую минуту, для 20 попыток. После неудачных 20 попыток — новые реконнекты производить каждые 5 минут.
searchbase=«dc=test-1,dc=office,dc=com» # каталог который будет синхронизирован между срверами(в данном случае это весь каталог)
scope=sub # глубина поиска. В данном случае по всей области которая находится ниже относительно searchbase.
bindmethod=simple
binddn=«cn=admin,dc=test-1,dc=office,dc=com» # пользователь от имени которого будет производиться синхронизация. В данном случае это admin и его пароль который описан директивой ниже.
credentials=хххххххххх

overlay syncprov
syncprov-checkpoint 100 1
syncprov-sessionlog 100

ну и для сервера 192.168.1.3 соответственно:
# база для сервера 192.168.1.1
syncrepl rid=000
provider=ldap://192.168.1.1 # адрес главного сервера
type=refreshAndPersist # тип обновления. После соединения потребителя и поставщика, происходит синхронизация, и по окончании синхронизации связь поддерживается. То есть соединение является постоянным
retry=«60 20 300 +» # повторы соединения. Здесь реконнект каждую минуту, для 20 попыток. После неудачных 20 попыток — новые реконнекты производить каждые 5 минут.
searchbase=«dc=test-1,dc=office,dc=com» # каталог который будет синхронизирован между срверами(в данном случае это весь каталог)
scope=sub # глубина поиска. В данном случае по всей области которая находится ниже относительно searchbase.
bindmethod=simple
binddn=«cn=admin,dc=test-1,dc=office,dc=com» # пользователь от имени которого будет производиться синхронизация. В данном случае это admin и его пароль который описан директивой ниже.
credentials=хххххххххх

# база для сервера 192.168.1.2
syncrepl rid=001
provider=ldap://192.168.1.2 # адрес сервера филиала
type=refreshAndPersist # тип обновления. После соединения потребителя и поставщика, происходит синхронизация, и по окончании синхронизации связь поддерживается. То есть соединение является постоянным
retry=«60 20 300 +» # повторы соединения. Здесь реконнект каждую минуту, для 20 попыток. После неудачных 20 попыток — новые реконнекты производить каждые 5 минут.
searchbase=«dc=test-1,dc=office,dc=com» # каталог который будет синхронизирован между срверами(в данном случае это весь каталог)
scope=sub # глубина поиска. В данном случае по всей области которая находится ниже относительно searchbase.
bindmethod=simple
binddn=«cn=admin,dc=test-1,dc=office,dc=com» # пользователь от имени которого будет производиться синхронизация. В данном случае это admin и его пароль который описан директивой ниже.
credentials=хххххххххх

overlay syncprov
syncprov-checkpoint 100 1
syncprov-sessionlog 100

Вроде бы все.

P. S. Таким образом если интернет работает исправно, на всех серверах LDAP будет одинаковая база. При создании/изменении пользователя на любом сервере, информация о нем сразу же поменяется на других серверах.
Каждый сервер при такой синхронизации является ГЛАВНЫМ. Подчинение отсутствует.
И если база создана на главном сервере то переносить ее в филиалы не надо. После настройки и после команды service slapd restart на сервере филиала, произойдет синхронизация и база с главного сервера зальется на филиальный и таким образом после синхронизации базы будут одинаковые.

Спасибо.

Комментарии (28)


  1. gto
    11.11.2015 12:27

    У вас на все филиалы одна подсеть? Рисковый вы человек.


  1. misha8282
    11.11.2015 12:31

    не на всех )))
    это ж для примера.
    сети могут быть и разные

    на практике у меня главный 192.168.1.1 и два 192.168.2.1 и 192.168.5.1
    у каждого своя подсеть


    1. gto
      11.11.2015 12:58

      Тогда, конечно, понятно. Еще такой вопрос, как проверяете консистентность нод?


      1. misha8282
        11.11.2015 13:04

        если вы про согласованность данных и их целостность, то при стабильной связи синхронизация происходит нормально. способ синхронизации — постоянное соеднинение. если оно пропадает то при появлении синхронизауия происходит штатно.
        если вы об этом спрашивали.


        1. gto
          11.11.2015 13:20

          Меня больше интересовал вопрос идентичности данных. Проще говоря, как проверяете, что базы одинаковые в определённый момент времени?


          1. misha8282
            11.11.2015 13:25

            при устойчвой связи, после нажатия кнопки ПРИНЯТЬ в GQ(ldap клиент) информация распространяется мгновенно.


            1. misha8282
              11.11.2015 13:26

              базы одинаковые сразу же после синхронизации


            1. gto
              11.11.2015 13:44

              Тогда повторюсь, рисковый вы человек, так доверять сервису. Мы вот себе проверялки на contextCSN поставили. Потому как были неприятные случаи.


              1. misha8282
                11.11.2015 13:51

                вы про то что бы добавить в файл contextCSN?
                для использовагия метки времени


                1. misha8282
                  11.11.2015 13:54

                  contextCSN
                  syncprov-checkpoint 10 10

                  # сохранение каждые 10 обновлений или каждые 10 минут


                1. gto
                  11.11.2015 14:13

                  Нет, я про то, чтобы contextCSN переодически проверять на всех машинах.


                  1. misha8282
                    11.11.2015 14:16

                    contextCSN
                    syncprov-checkpoint 10 10

                    доабвить на всех машинах


              1. kelevra
                11.11.2015 13:52

                тоже мучался от парнойи на тему идентичности данных, поэтому рядом со всеми ldap серверами стоит костыль из ldapsearch | sort | diff — перезапускает slapd, если содержимое различается. помогает отловить негодяев, которые решили писать в slapd, не являющийся мастером. а вот при штатной эксплуатации проблем ни разу не возникало, хотя каналы связи довольно стабильные.


                1. gto
                  11.11.2015 14:18

                  На любой стабильный канал найдётся безопасник с фаерволом и большим количеством свободного времени


                  1. misha8282
                    11.11.2015 14:19

                    ну это уже частности. где то есть безопасники, где то их нет.


                    1. gto
                      11.11.2015 14:22

                      Это для примера, просто были случаи когда репликация отваливалсь, а замечали это только после жалобы пользователей. Поэтому и поставили дополнительные проверялки на contextCSN.


  1. shtirlitsus
    11.11.2015 12:57

    reopenldap не смотрели? намного стабильней


    1. misha8282
      11.11.2015 13:04

      не смотрел.


      1. misha8282
        11.11.2015 13:07

        я так понимаю это промышленное решение? у меня нет адских нагрузок на сервер. поэтому пока использщую openldap


  1. kelevra
    11.11.2015 13:43
    +1

    молодец, что разобрался, но статья получилась не очень. для мультимастерной репликации весь конфиг принято хранить в slapd.d, для того, чтобы при его изменении не перелопачивать все сервера. синхронизируется он так же с помощью syncprov, но работать с ним, разумеется, сложнее, чем с текстовым конфигом. например, можно прострелить себе ногу, отключив этот самый оверлей. причём ноги, в этом случае, будут прострелены сразу у всех серверов :)

    к слову, в данной архитектуре, можно сделать мастерами лишь часть серверов. для этого достаточно, чтобы в списке мастеров были прописаны только те, серера, с которых нужно забирать изменения. такая схема позволяет держать свой slapd практически на каждом сервере или виртуалке, который должен использовать ldap, не нагружая мастеров.

    ну и, если уж до конца придираться, то статье не хватает оформления.


  1. Sleuthhound
    12.11.2015 22:54

    Было бы очень интересно и полезно, если бы автор рассказал как проверять статус репликации и отлаживать это дело. Потому как у меня на 2 серверах по вашей методике репликация не заработала и куда смотреть в чем дело непонятно :(

    Единственное что я знаю это на одном сервере

    # ldapsearch -z1 -LLLQY EXTERNAL -H ldapi:/// -s base contextCSN
    dn: dc=office,dc=myorg,dc=ru
    contextCSN: 20110218080539.685470Z#000000#000#000000
    contextCSN: 20151112195135.967095Z#000000#001#000000
    contextCSN: 20111130074952.286378Z#000000#002#000000

    на другом

    # ldapsearch -z1 -LLLQY EXTERNAL -H ldapi:/// -s base contextCSN
    dn: dc=office,dc=myorg,dc=ru
    contextCSN: 20110218080539.685470Z#000000#000#000000
    contextCSN: 20151112183400.865998Z#000000#001#000000
    contextCSN: 20111130074952.286378Z#000000#002#000000

    как видно строки разные, но а дальше то что?


    1. misha8282
      13.11.2015 00:12

      если вы не против, то можете дать мне доступ по ssh я бы зашел и посмотрел на настройки.


      1. misha8282
        13.11.2015 00:26

        да и еще. я забыл написать об этом. время на синхронизируемых серверах должно быть одинаковым. желательно что бы все они синхронизировали свое время с одного NTP сервера.


    1. gto
      13.11.2015 12:51

      запустите slapd вручную (на debian-е /usr/sbin/slapd -u openldap -d3), он вам сам расскажет, что ему не нравится


  1. saamich
    13.11.2015 02:02

    А что будет если сначала связь порвется и в 2 разных филиалах поменяют/создадут запись с одним и темже rdn, а потом связь восстановится?


    1. misha8282
      13.11.2015 08:57

      такой вариант я не пробовал. кстати надо воспроизвести.


      1. misha8282
        13.11.2015 09:43

        эксперимент такой.
        отключил сеть на обеих машинах, добавил с через ldif файл на обе машины юзера с одинаковыми данными и запустил сети на обеих машинах.

        результат:
        1. при отключенной связи на двух машинах — синхронизация произошла сразу же после включения сети. коллизий не наблюдалось.
        2. если связь отрубилась на какой то одной машине и в ее LDAP добавили/изменили что то — при появлении связи опять же без коллизий прошла синхронизация.


        1. misha8282
          13.11.2015 09:43

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