OpenLDAPしか触ってなかった人が 389 Directory Serverでレプリケーション設定を行ってみる
はじめに
株式会社テイクーワンS.Nです。
LDAPサーバを実際に運用する際には,
複数台用意してレプリケーションさせて冗長性を確保することが必須かと思います。
実際に私の管理するOpenLDAPも,データ更新用と参照用の構成で稼働していますので
今回は,実際の運用形態に近い形まで持っていこうと思います。
![]()
【1回目:OpenLDAPしか触ってなかった人が389 Directory Serverを触ってみる】
https://www.tk-1.co.jp/tech_blog/linux/openldap389-directory-server.html
【2回目:389 Directory ServerでTLS設定を行ってみる】
https://www.tk-1.co.jp/tech_blog/linux/389-directory-server-tls.html
【公式:Configuring TLS/SSL Enabled 389 Directory Server】
https://www.port389.org/docs/389ds/howto/howto-ssl.html
参考情報としては,公式ドキュメントをはじめとしてGeamini等のAIにも助けてもらっています。
今回利用するレプリケーションの種類について
色々と種類があると思いますが,今回はシングルサプライヤーの構成を試していきます。
OpenLDAPだとマスター・スレーブ構成等の呼び方をしていたと思いますが
昨今はそれぞれをサプライヤー(プロバイダー),コンシューマと呼ぶようですね。
RedHat Documentation 解説がありますのでご確認ください
【15.2. Single-supplier Replication】
https://docs.redhat.com/en/documentation/red_hat_directory_server/11/html/administration_guide/single-supplier_replication
サプライヤー機(alph)とコンシューマ機(beta)の用意
本記事のサーバはKVMで稼働している仮想サーバですので複製しました。
今までホスト名は適当に記載していましたが役割ごとに作業が異なりますので
都度,どちらで実行しているか記載しています。
- サーバA:サプライヤー(送る側):alph.tk1.co.jp
- サーバB:コンシューマ(受け側):beta.tk1.co.jp
前準備
OSパッケージのアップデート
まず,前回から時間が経過していますので389dsパッケージを最新の状態にしておきます。
# rpm -qa | grep 389-ds
389-ds-base-libs-2.7.0-12.el9_7.x86_64
389-ds-base-2.7.0-12.el9_7.x86_64
389 Directory Serverは「2.7.0」で,
OSは「Rocky Linux release 9.7 (Blue Onyx)」です。
自己証明書を作成しない設定でインスタンスの再作成
自動で作成される自己証明書が最初からあるとLDAPS(636)周りがややこしいので,
389ds_take1.inf で自己証明書の作成を無効にしておきます。
# vim 389ds_take1.inf
~編集箇所~
# Default value: True
;self_sign_cert = True
self_sign_cert = False ←自己証明書の作成を無効にする
まずは,LDAP(389)のみの状態でレプリケーション構成を目指していきます。
以下コマンドで,サーバAとサーバB共に同じ状態にしておきます。
~サービス停止~
# dsctl tk-1 stop
# dsctl tk-1 remove --do-it
~インスタンス再作成と再構成~
# cd /etc/dirsrv/tk1_work/
# dscreate from-file 389ds_take1.inf
# ldapadd -H ldap://localhost -D "cn=Directory Manager" -W -f add_system4_ou.ldif
# ldapadd -H ldap://localhost -D "cn=Directory Manager" -W -f add_nomura.ldif
# ldapadd -H ldap://localhost -D "cn=Directory Manager" -W -f add_kanri_users.ldif
# ldapadd -H ldap://localhost -D "cn=Directory Manager" -W -f add_syain1.ldif
# ldapadd -H ldap://localhost -D "cn=Directory Manager" -W -f add_aci_system4.ldif
~サービスの再起動~
# systemctl restart dirsrv@tk-1.service
作業の流れ
ここからは,役割ごとの設定をいれていくことになります。
OpenLDAPでも同様かと思いますが,389dsではサプイラヤー(送る側)側にて
「レプリカ合意Replica Agreement」 なるものが必要になるようです。
これは独立した管理オブジェクトのようでして,OpenLDAPとの違いを感じた部分です。
【流れ】
- サーバAにて,サプライヤー(送る側)設定を投入
- サーバBにて,コンシューマ(受け側)設定を投入
- サーバAにて,レプリカ合意を投入
- サーバAにて,サーバBに対して初期化しつつレプリケーションを開始
サーバAでのサプライヤー(送る側)設定
では,さっそくサーバAから設定していきます。
こちらはサプライヤー(送る側)です。
投入するコマンドは以下の通りです。
dsconf -D "cn=Directory Manager" ldap://localhost replication enable \ ・・・レプリケーションの有効化
--suffix "dc=tk-1,dc=co,dc=jp" \ ・・・対象となるデータツリー
--role "supplier" \ ・・・このサーバの役割,サプライヤー(送る側)
--replica-id 1 \ ・・・サーバ固有の識別番号,サプライヤが多い場合は分ける必要あり
--bind-dn "cn=replication manager,cn=config" \ ・・・レプリケーション専用ユーザDN
--bind-passwd "take1passwd" ・・・レプリケーション専用ユーザDNのパスワード
投入します
サーバA:サプライヤー(送る側):alph.tk1.co.jpにて実行
# dsconf -D "cn=Directory Manager" ldap://localhost replication enable \
--suffix "dc=tk-1,dc=co,dc=jp" \
--role "supplier" \
--replica-id 1 \
--bind-dn "cn=replication manager,cn=config" \
--bind-passwd "take1passwd"
Enter password for cn=Directory Manager on ldap://localhost:(管理ユーザのPW)
Replication successfully enabled for "dc=tk-1,dc=co,dc=jp"
反映されているかエントリを確認します。
確認ポイントとしては以下のようです。
nsDS5Flags: 1 ・・・レプリカが有効になっている
nsDS5ReplicaId: 1 ・・・設定した識別番号
nsDS5ReplicaType: 3 ・・・これが3だとサプライヤー
サーバA:サプライヤー(送る側):alph.tk1.co.jpにて実行
# dsconf -D "cn=Directory Manager" ldap://localhost replication get --suffix "dc=tk-1,dc=co,dc=jp"
Enter password for cn=Directory Manager on ldap://localhost:(管理ユーザのPW)
dn: cn=replica,cn=dc\3Dtk-1\2Cdc\3Dco\2Cdc\3Djp,cn=mapping tree,cn=config
cn: replica
nsDS5Flags: 1
nsDS5ReplicaBindDN: cn=replication manager,cn=config
nsDS5ReplicaId: 1
nsDS5ReplicaName: d7e00e02-3d2711f1-a32481ef-66dfb4df
nsDS5ReplicaRoot: dc=tk-1,dc=co,dc=jp
nsDS5ReplicaType: 3
nsState:: AQAAAAAAAAC+3eZpAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAA==
nsds5ReplicaChangeCount: 1
nsds5replicareapactive: 0
objectClass: top
objectClass: nsds5Replica
また,同時にレプリケーションを行うユーザも作成されているようです
サーバA:サプライヤー(送る側):alph.tk1.co.jpにて実行
# ldapsearch -LLL -x -H ldap://localhost -D "cn=Directory Manager" -W -b "cn=config" "(cn=replication manager)" dn
Enter LDAP Password:
dn: cn=replication manager,cn=config
設定したPWもちゃんと適応されていますね。
サーバA:サプライヤー(送る側):alph.tk1.co.jpにて実行
# ldapsearch -x -H ldap://localhost -D "cn=replication manager,cn=config" -w "take1passwd" -b "cn=config" -s base
# extended LDIF
#
# LDAPv3
# base with scope baseObject
# filter: (objectclass=*)
# requesting: ALL
#
# search result
search: 2
result: 0 Success
# numResponses: 1
サーバBでのコンシューマ(受け側)設定
次に,サーバBの設定をします。
こちらはコンシューマ(受け側)です。
dsconf -D "cn=Directory Manager" ldap://localhost replication enable \ ・・・レプリケーションの有効化
--suffix "dc=tk-1,dc=co,dc=jp" \ ・・・対象となるデータツリー
--role "consumer" \ ・・・このサーバの役割,コンシューマ(受け側)
--bind-dn "cn=replication manager,cn=config" \ ・・・レプリケーション専用ユーザDN
--bind-passwd "take1passwd" ・・・レプリケーション専用ユーザDNのパスワード
投入します
サーバB:コンシューマ(受け側):beta.tk1.co.jpにて実行
# dsconf -D "cn=Directory Manager" ldap://localhost replication enable \
--suffix "dc=tk-1,dc=co,dc=jp" \
--role "consumer" \
--bind-dn "cn=replication manager,cn=config" \
--bind-passwd "take1passwd"
Enter password for cn=Directory Manager on ldap://localhost:(管理ユーザのPW)
Replication successfully enabled for "dc=tk-1,dc=co,dc=jp"
反映されているかエントリを確認します。
確認ポイントとしては以下のようです。
nsDS5Flags: 1 ・・・レプリカが有効になっている
nsDS5ReplicaId: 65535 ・・・識別番号,特にしてないしてないコンシューマなら大きい値
nsDS5ReplicaType: 2 ・・・これが2だとコンシューマ
サーバB:コンシューマ(受け側):beta.tk1.co.jpにて実行
# dsconf -D "cn=Directory Manager" ldap://localhost replication get --suffix "dc=tk-1,dc=co,dc=jp"
Enter password for cn=Directory Manager on ldap://localhost:
dn: cn=replica,cn=dc\3Dtk-1\2Cdc\3Dco\2Cdc\3Djp,cn=mapping tree,cn=config
cn: replica
nsDS5Flags: 0
nsDS5ReplicaBindDN: cn=replication manager,cn=config
nsDS5ReplicaId: 65535
nsDS5ReplicaName: f4287e82-3d1811f1-a32481ef-66dfb4df
nsDS5ReplicaRoot: dc=tk-1,dc=co,dc=jp
nsDS5ReplicaType: 2
nsState:: //8AAAAAAACzxOZpAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAA==
nsds5ReplicaChangeCount: 0
nsds5replicareapactive: 0
objectClass: top
objectClass: nsds5Replica
こちらでもレプリケーションユーザが作成されています。
サーバB:コンシューマ(受け側):beta.tk1.co.jpにて実行
# ldapsearch -LLL -x -H ldap://localhost -D "cn=Directory Manager" -W -b "cn=config" "(cn=replication manager)" dn
Enter LDAP Password:
dn: cn=replication manager,cn=config
サーバAにてレプリカ合意の設定
ここが本命ですね。
サプライヤー(送る側)のサーバAに,コンシューマ(受け側)であるサーバBの情報を入れていきます。
dsconf -D "cn=Directory Manager" ldap://localhost repl-agmt create \ ・・・レプリカ合意の作成
--suffix "dc=tk-1,dc=co,dc=jp" \ ・・・対象となるデータツリー
--host "beta.tk1.co.jp" \ ・・・相手となるコンシューマ(受け側)サーバのホスト名
--port 389 \ ・・・利用ポート
--conn-protocol LDAP \ ・・・利用プロトコル
--bind-dn "cn=replication manager,cn=config" \ ・・・レプリケーション専用ユーザDN
--bind-passwd "take1passwd" \ ・・・レプリケーション専用ユーザDNのパスワード
--bind-method SIMPLE \ ・・・パスワード認証
"agmt_svA_to_svB" ・・・任意のレプリカ合意の名前
投入します。
サーバA:サプライヤー(送る側):alph.tk1.co.jpにて実行
# dsconf -D "cn=Directory Manager" ldap://localhost repl-agmt create \
--suffix "dc=tk-1,dc=co,dc=jp" \
--host "beta.tk1.co.jp" \
--port 389 \
--conn-protocol LDAP \
--bind-dn "cn=replication manager,cn=config" \
--bind-passwd "take1passwd" \
--bind-method SIMPLE \
"agmt_svA_to_svB"
Enter password for cn=Directory Manager on ldap://localhost:(管理ユーザのPW)
Successfully created replication agreement "agmt_svA_to_svB"
サーバAからサーバBに対して初期化しつつレプリケーションを開始
最後に,サーバAのサプライヤー(送る側)から
サーバBのコンシューマ(受け側)に対して,初期化しつつ同期を開始します。
dsconf -D "cn=Directory Manager" ldap://localhost repl-agmt init \ ・・・初期化を行う
--suffix "dc=tk-1,dc=co,dc=jp" "agmt_svA_to_svB" ・・・対象のレプリカ合意
投入します
サーバA:サプライヤー(送る側):alph.tk1.co.jpにて実行
# dsconf -D "cn=Directory Manager" ldap://localhost repl-agmt init \
--suffix "dc=tk-1,dc=co,dc=jp" "agmt_svA_to_svB"
Enter password for cn=Directory Manager on ldap://localhost:(管理ユーザのPW)
Agreement initialization started...
データが少なければ一瞬で終わります。状態を確認しましょう。
dsconf -D "cn=Directory Manager" ldap://localhost repl-agmt status \ ・・・ステータス表示
--suffix "dc=tk-1,dc=co,dc=jp" "agmt_svA_to_svB" ・・・対象のレプリカ合意
確認ポイントは以下のようです
Last Update Status: Error (0) Replica acquired successfully: Incremental update succeeded ・・・エラーなし差分OK
Last Init Status: Error (0) Total update succeeded ・・・エラーなし,全データOK
サーバA:サプライヤー(送る側):alph.tk1.co.jpにて実行
# dsconf -D "cn=Directory Manager" ldap://localhost repl-agmt status \
--suffix "dc=tk-1,dc=co,dc=jp" "agmt_svA_to_svB"
Enter password for cn=Directory Manager on ldap://localhost:(管理ユーザPW)
Status For Agreement: "agmt_svA_to_svB" (tk1svb.tk1.co.jp:389)
Replica Enabled: on
Update In Progress: FALSE
Last Update Start: 20260421011307Z
Last Update End: 20260421011307Z
Number Of Changes Sent: 0
Number Of Changes Skipped: None
Last Update Status: Error (0) Replica acquired successfully: Incremental update succeeded
Last Init Start: 20260421011303Z
Last Init End: 20260421011307Z
Last Init Status: Error (0) Total update succeeded
Reap Active: 0
Replication Status: Not in Synchronization: supplier (Unknown) consumer (Unknown) State (green) Reason (error (0) replica acquired successfully: incremental update succeeded)
Replication Lag Time: unavailable
同期できているかの確認
サプライヤー(送る側)での社員「syain2」の追加
設定投入ができたので,今度はちゃんとデータ同期されるか見ていこうと思います。
追加前に「syain2」がいないこと確認します。
【サーバA】
サーバA:サプライヤー(送る側):alph.tk1.co.jpにて実行
# ldapsearch -LLL -H ldap://localhost -D "cn=Directory Manager" -b "ou=system4,dc=tk-1,dc=co,dc=jp" -W dn
Enter LDAP Password:(管理ユーザPW)
dn: ou=system4,dc=tk-1,dc=co,dc=jp
dn: uid=nomuras,ou=system4,dc=tk-1,dc=co,dc=jp
dn: uid=syain1,ou=system4,dc=tk-1,dc=co,dc=jp
【サーバB】
サーバB:コンシューマ(受け側):beta.tk1.co.jpにて実行
# ldapsearch -LLL -H ldap://localhost -D "cn=Directory Manager" -b "ou=system4,dc=tk-1,dc=co,dc=jp" -W dn
Enter LDAP Password:(管理ユーザPW)
dn: ou=system4,dc=tk-1,dc=co,dc=jp
dn: uid=nomuras,ou=system4,dc=tk-1,dc=co,dc=jp
dn: uid=syain1,ou=system4,dc=tk-1,dc=co,dc=jp
以下の通り社員「syain2」追加用のLDIFを作成し・・・
サーバA:サプライヤー(送る側):alph.tk1.co.jpにて実行
# vim add_syain2.ldif
# cat add_syain2.ldif
dn: uid=syain2,ou=system4,dc=tk-1,dc=co,dc=jp
objectClass: top
objectClass: posixAccount
userPassword:: e01ENX02RHRCNTBscHo1NzN2OU9BYkY1bStRPT0=
uid: syain2
cn: TAKE TWO2
uidNumber: 54323
gidNumber: 100
gecos: TAKE TWO2
homeDirectory: /home/system4/syain2
loginShell: /bin/bash
サプライヤーのサーバAにて適応します。
サーバA:サプライヤー(送る側):alph.tk1.co.jpにて実行
# ldapadd -H ldap://localhost -D "cn=Directory Manager" -W -f add_syain2.ldif
Enter LDAP Password:(管理ユーザPW)
adding new entry "uid=syain2,ou=system4,dc=tk-1,dc=co,dc=jp"
確認しましょう。両サーバに「syain2」が追加されています。
【サーバA】
サーバA:サプライヤー(送る側):alph.tk1.co.jpにて実行
# ldapsearch -LLL -H ldap://localhost -D "cn=Directory Manager" -b "ou=system4,dc=tk-1,dc=co,dc=jp" -W dn
Enter LDAP Password:(管理ユーザPW)
dn: ou=system4,dc=tk-1,dc=co,dc=jp
dn: uid=nomuras,ou=system4,dc=tk-1,dc=co,dc=jp
dn: uid=syain1,ou=system4,dc=tk-1,dc=co,dc=jp
dn: uid=syain2,ou=system4,dc=tk-1,dc=co,dc=jp ←追加されている
【サーバB】
サーバB:コンシューマ(受け側):beta.tk1.co.jpにて実行
# ldapsearch -LLL -H ldap://localhost -D "cn=Directory Manager" -b "ou=system4,dc=tk-1,dc=co,dc=jp" -W dn
Enter LDAP Password:(管理ユーザPW)
dn: ou=system4,dc=tk-1,dc=co,dc=jp
dn: uid=nomuras,ou=system4,dc=tk-1,dc=co,dc=jp
dn: uid=syain1,ou=system4,dc=tk-1,dc=co,dc=jp
dn: uid=syain2,ou=system4,dc=tk-1,dc=co,dc=jp ←レプリケーションで追加されている
サーバBではログファイルをみてみましょう。
レプリケーション設定を入れたときに作成したreplication managerによって追加されているのがわかります。
サーバB:コンシューマ(受け側):beta.tk1.co.jpにて実行
# grep conn=89 /var/log/dirsrv/slapd-tk-1/access | grep -w "BIND|ADD"
[22/Apr/2026:16:50:13.345169144 +0900] conn=89 op=0 BIND dn="cn=replication manager,cn=config" method=128 version=3
[22/Apr/2026:16:51:06.744346911 +0900] conn=89 op=7 ADD dn="uid=syain2,ou=system4,dc=tk-1,dc=co,dc=jp"
コンシューマ(受け側)側での社員削除
次にサーバBのコンシューマは読み取り専用になっているはずですので,
削除できないことを確認しおてみましょう。
サーバBにて削除用LDIFを作成し・・・
サーバB:コンシューマ(受け側):beta.tk1.co.jpにて実行
# vim del_syain2.ldif
# cat del_syain2.ldif
dn: uid=syain2,ou=system4,dc=tk-1,dc=co,dc=jp
changetype: delete
投入します。
無事に「Referral (10)」となりました。
これは,「ウチじゃないので書いてあるサーバで作業してね」という意味で
サプライヤー(送る側)であるサーバAの「alph.tk1.co.jp」が表示されています。
サーバB:コンシューマ(受け側):beta.tk1.co.jpにて実行
# ldapmodify -x -H ldap://localhost -D "cn=Directory Manager" -W -f del_syain2.ldif
Enter LDAP Password:(管理ユーザPW)
deleting entry "uid=syain2,ou=system4,dc=tk-1,dc=co,dc=jp"
ldap_delete: Referral (10)
matched DN: dc=tk-1,dc=co,dc=jp
referrals:
ldap://alph.tk1.co.jp:389 ←サプライヤはこっちだとよいう表示
もちろん削除はできていないことを確認します。
サーバB:コンシューマ(受け側):beta.tk1.co.jpにて実行
# ldapsearch -LLL -H ldap://localhost -D "cn=Directory Manager" -b "ou=system4,dc=tk-1,dc=co,dc=jp" -W dn
dn: ou=system4,dc=tk-1,dc=co,dc=jp
dn: uid=nomuras,ou=system4,dc=tk-1,dc=co,dc=jp
dn: uid=syain1,ou=system4,dc=tk-1,dc=co,dc=jp
dn: uid=syain2,ou=system4,dc=tk-1,dc=co,dc=jp
以上で,レプリケーションの設定ができました。
終わりに
OpenLDAPとの違いを感じるは「レプリカ合意」まわりの設定でした。
若干めんどうかな?と思いましたが,コンシューマ側はシンプルなので管理は楽そうです。
また,コンシューマ側で更新しようとしても Referral が表示されるのも,
運用的にはわかりやすくて良いと思いました。
次回はLDAPS(636)でのレプリケーションや,スキーマ拡張などをみていけたらと思います。
