最初に
前回
これまで
syncreplが提供するレプリケーション
一般的なデータベースの冗長構成ではデータの完全同期が期待さることが多いかもしれません。たとえば、
一方、
OpenLDAPのsyncrepl機能もまた非同期のレプリケーションですが、
- 極力リアルタイムにレプリケーションを行う
 - 適度なインターバルをもってレプリケーションを行う
 
といったことが可能です。通常の用途では前者を選択することが多いと思いますが、
refreshOnlyとrefreshAndPersist
前述の2通りのレプリケーションですが、
refreshOnlyを指定する場合、
一方、
まず、
# レプリケーションのためのインデックス(後述)
index entryCSN,entryUUID eq 
index objectClass        eq,pres
# syncrepl用のモジュールをロード
overlay         syncprov
次に、
syncrepl rid=100                        # コンシューマ識別ID(数字3桁)
  provider=ldap://10.0.100.21:389       # プロバイダの接続先とポート
  type=refreshOnly                      # レプリケーション方式(定期的な更新確認)
  interval=00:00:05:00                  # 接続間隔(5分)
  searchbase="dc=example,dc=com"        # 同期を行う対象の検索ベース
  bindmethod=simple                     # 認証モード
  binddn="cn=Manager,dc=example,dc=com" # バインドDN
  credentials=secret                    # バインドパスワード
syncrepl rid=100                        # コンシューマ識別ID(数字3桁)
  provider=ldap://10.0.100.21:389       # プロバイダの接続先とポート 
  type=refreshAndPersist                # レプリケーション方式(接続維持を行う)
  retry="5 10 300 +"                    # 接続失敗した場合のリトライ間隔
  searchbase="dc=example,dc=com"        # 同期を行う対象の検索ベース
  bindmethod=simple                     # 認証モード
  binddn="cn=Manager,dc=example,dc=com" # バインドDN
  credentials=secret                    # バインドパスワード
これらの挙動の違いをさらに理解するために、
01:55:32.035247 IP 10.0.100.22.51995 > 10.0.100.21.389: S 2972302010:2972302010(0) win 5840 <mss 1460,sackOK,timestamp 66828619 0,nop,wscale 6> 
01:55:32.035493 IP 10.0.100.21.389 > 10.0.100.22.51995: S 2447691039:2447691039(0) ack 2972302011 win 5792 <mss 1460,sackOK,timestamp 217778436 66828619,nop,wscale 7> 
01:55:32.035510 IP 10.0.100.22.51995 > 10.0.100.21.389: . ack 1 win 92 <nop,nop,timestamp 66828619 217778436> 
01:55:32.035644 IP 10.0.100.22.51995 > 10.0.100.21.389: P 1:49(48) ack 1 win 92 <nop,nop,timestamp 66828619 217778436> 
01:55:32.035780 IP 10.0.100.21.389 > 10.0.100.22.51995: . ack 49 win 46 <nop,nop,timestamp 217778436 66828619> 
01:55:32.036386 IP 10.0.100.21.389 > 10.0.100.22.51995: P 1:15(14) ack 49 win 46 <nop,nop,timestamp 217778436 66828619> 
01:55:32.036394 IP 10.0.100.22.51995 > 10.0.100.21.389: . ack 15 win 92 <nop,nop,timestamp 66828619 217778436> 
01:55:32.036534 IP 10.0.100.22.51995 > 10.0.100.21.389: P 49:206(157) ack 15 win 92 <nop,nop,timestamp 66828619 217778436> 
01:55:32.036913 IP 10.0.100.21.389 > 10.0.100.22.51995: P 15:66(51) ack 206 win 54 <nop,nop,timestamp 217778436 66828619> 
01:55:32.036958 IP 10.0.100.22.51995 > 10.0.100.21.389: P 206:213(7) ack 66 win 92 <nop,nop,timestamp 66828619 217778436> 
01:55:32.037007 IP 10.0.100.22.51995 > 10.0.100.21.389: F 213:213(0) ack 66 win 92 <nop,nop,timestamp 66828619 217778436> 
01:55:32.037212 IP 10.0.100.21.389 > 10.0.100.22.51995: F 66:66(0) ack 213 win 54 <nop,nop,timestamp 217778436 66828619> 
01:55:32.037220 IP 10.0.100.22.51995 > 10.0.100.21.389: . ack 67 win 92 <nop,nop,timestamp 66828619 217778436> 
01:55:32.037228 IP 10.0.100.21.389 > 10.0.100.22.51995: . ack 214 win 54 <nop,nop,timestamp 217778436 66828619> 
02:00:32.037537 IP 10.0.100.22.40337 > 10.0.100.21.389: S 3389899619:3389899619(0) win 5840 <mss 1460,sackOK,timestamp 66903620 0,nop,wscale 6> 
02:00:32.037821 IP 10.0.100.21.389 > 10.0.100.22.40337: S 2858513305:2858513305(0) ack 3389899620 win 5792 <mss 1460,sackOK,timestamp 217808436 66903620,nop,wscale 7> 
02:00:32.037838 IP 10.0.100.22.40337 > 10.0.100.21.389: . ack 1 win 92 <nop,nop,timestamp 66903620 217808436> 
02:00:32.037917 IP 10.0.100.22.40337 > 10.0.100.21.389: P 1:49(48) ack 1 win 92 <nop,nop,timestamp 66903620 217808436> 
02:00:32.038052 IP 10.0.100.21.389 > 10.0.100.22.40337: . ack 49 win 46 <nop,nop,timestamp 217808436 66903620> 
02:00:32.038730 IP 10.0.100.21.389 > 10.0.100.22.40337: P 1:15(14) ack 49 win 46 <nop,nop,timestamp 217808436 66903620> 
02:00:32.038738 IP 10.0.100.22.40337 > 10.0.100.21.389: . ack 15 win 92 <nop,nop,timestamp 66903620 217808436> 
02:00:32.038827 IP 10.0.100.22.40337 > 10.0.100.21.389: P 49:206(157) ack 15 win 92 <nop,nop,timestamp 66903620 217808436> 
02:00:32.040482 IP 10.0.100.21.389 > 10.0.100.22.40337: P 15:694(679) ack 206 win 54 <nop,nop,timestamp 217808436 66903620> 
02:00:32.040492 IP 10.0.100.21.389 > 10.0.100.22.40337: P 694:1299(605) ack 206 win 54 <nop,nop,timestamp 217808436 66903620> 
02:00:32.040497 IP 10.0.100.22.40337 > 10.0.100.21.389: . ack 1299 win 134 <nop,nop,timestamp 66903620 217808436> 
02:00:32.040501 IP 10.0.100.21.389 > 10.0.100.22.40337: P 1299:1904(605) ack 206 win 54 <nop,nop,timestamp 217808436 66903620> 
02:00:32.040724 IP 10.0.100.21.389 > 10.0.100.22.40337: P 1904:2006(102) ack 206 win 54 <nop,nop,timestamp 217808436 66903620> 
02:00:32.040733 IP 10.0.100.22.40337 > 10.0.100.21.389: . ack 2006 win 153 <nop,nop,timestamp 66903620 217808436> 
02:00:32.055063 IP 10.0.100.22.40337 > 10.0.100.21.389: P 206:213(7) ack 2006 win 153 <nop,nop,timestamp 66903624 217808436> 
02:00:32.055077 IP 10.0.100.22.40337 > 10.0.100.21.389: F 213:213(0) ack 2006 win 153 <nop,nop,timestamp 66903624 217808436> 
02:00:32.055326 IP 10.0.100.21.389 > 10.0.100.22.40337: F 2006:2006(0) ack 214 win 54 <nop,nop,timestamp 217808438 66903624> 
02:00:32.055334 IP 10.0.100.22.40337 > 10.0.100.21.389: . ack 2007 win 153 <nop,nop,timestamp 66903624 217808438> 
02:05:32.040132 IP 10.0.100.22.56558 > 10.0.100.21.389: S 3801473658:3801473658(0) win 5840 <mss 1460,sackOK,timestamp 66978620 0,nop,wscale 6> 
02:05:32.040392 IP 10.0.100.21.389 > 10.0.100.22.56558: S 3269951867:3269951867(0) ack 3801473659 win 5792 <mss 1460,sackOK,timestamp 217838436 66978620,nop,wscale 7> 
02:05:32.040412 IP 10.0.100.22.56558 > 10.0.100.21.389: . ack 1 win 92 <nop,nop,timestamp 66978620 217838436> 
02:05:32.040441 IP 10.0.100.22.56558 > 10.0.100.21.389: P 1:49(48) ack 1 win 92 <nop,nop,timestamp 66978620 217838436> 
02:05:32.040664 IP 10.0.100.21.389 > 10.0.100.22.56558: . ack 49 win 46 <nop,nop,timestamp 217838436 66978620> 
02:05:32.041292 IP 10.0.100.21.389 > 10.0.100.22.56558: P 1:15(14) ack 49 win 46 <nop,nop,timestamp 217838436 66978620> 
02:05:32.041300 IP 10.0.100.22.56558 > 10.0.100.21.389: . ack 15 win 92 <nop,nop,timestamp 66978620 217838436> 
02:05:32.041398 IP 10.0.100.22.56558 > 10.0.100.21.389: P 49:206(157) ack 15 win 92 <nop,nop,timestamp 66978620 217838436> 
02:05:32.041893 IP 10.0.100.21.389 > 10.0.100.22.56558: P 15:66(51) ack 206 win 54 <nop,nop,timestamp 217838436 66978620> 
02:05:32.041937 IP 10.0.100.22.56558 > 10.0.100.21.389: P 206:213(7) ack 66 win 92 <nop,nop,timestamp 66978621 217838436> 
02:05:32.042001 IP 10.0.100.22.56558 > 10.0.100.21.389: F 213:213(0) ack 66 win 92 <nop,nop,timestamp 66978621 217838436> 
02:05:32.042186 IP 10.0.100.21.389 > 10.0.100.22.56558: F 66:66(0) ack 213 win 54 <nop,nop,timestamp 217838437 66978621> 
02:05:32.042194 IP 10.0.100.22.56558 > 10.0.100.21.389: . ack 67 win 92 <nop,nop,timestamp 66978621 217838437> 
02:05:32.042202 IP 10.0.100.21.389 > 10.0.100.22.56558: . ack 214 win 54 <nop,nop,timestamp 217838437 66978621> 
コンシューマ側のslapdを起動すると、
次はrefreshAndPersist時の結果です。
01:29:10.377858 IP 10.0.100.22.36157 > 10.0.100.21.389: S 3928508035:3928508035(0) win 5840 <mss 1460,sackOK,timestamp 66433204 0,nop,wscale 6> 
01:29:10.378147 IP 10.0.100.21.389 > 10.0.100.22.36157: S 3406805294:3406805294(0) ack 3928508036 win 5792 <mss 1460,sackOK,timestamp 217620270 66433204,nop,wscale 7> 
01:29:10.378165 IP 10.0.100.22.36157 > 10.0.100.21.389: . ack 1 win 92 <nop,nop,timestamp 66433205 217620270> 
01:29:10.378226 IP 10.0.100.22.36157 > 10.0.100.21.389: P 1:49(48) ack 1 win 92 <nop,nop,timestamp 66433205 217620270> 
01:29:10.378417 IP 10.0.100.21.389 > 10.0.100.22.36157: . ack 49 win 46 <nop,nop,timestamp 217620270 66433205> 
01:29:10.379048 IP 10.0.100.21.389 > 10.0.100.22.36157: P 1:15(14) ack 49 win 46 <nop,nop,timestamp 217620270 66433205> 
01:29:10.379056 IP 10.0.100.22.36157 > 10.0.100.21.389: . ack 15 win 92 <nop,nop,timestamp 66433205 217620270> 
01:29:10.379228 IP 10.0.100.22.36157 > 10.0.100.21.389: P 49:206(157) ack 15 win 92 <nop,nop,timestamp 66433205 217620270> 
01:29:10.379588 IP 10.0.100.21.389 > 10.0.100.22.36157: P 15:52(37) ack 206 win 54 <nop,nop,timestamp 217620270 66433205> 
01:29:10.421379 IP 10.0.100.22.36157 > 10.0.100.21.389: . ack 52 win 92 <nop,nop,timestamp 66433215 217620270> 
01:29:19.877158 IP 10.0.100.21.389 > 10.0.100.22.36157: P 52:711(659) ack 206 win 54 <nop,nop,timestamp 217621220 66433215> 
01:29:19.877173 IP 10.0.100.22.36157 > 10.0.100.21.389: . ack 711 win 112 <nop,nop,timestamp 66435579 217621220> 
01:29:24.507106 IP 10.0.100.21.389 > 10.0.100.22.36157: P 711:1370(659) ack 206 win 54 <nop,nop,timestamp 217621683 66435579> 
01:29:24.507118 IP 10.0.100.22.36157 > 10.0.100.21.389: . ack 1370 win 133 <nop,nop,timestamp 66436737 217621683> 
01:29:28.850948 IP 10.0.100.22.36157 > 10.0.100.21.389: P 206:213(7) ack 1370 win 133 <nop,nop,timestamp 66437823 217621683> 
01:29:28.850966 IP 10.0.100.22.36157 > 10.0.100.21.389: F 213:213(0) ack 1370 win 133 <nop,nop,timestamp 66437823 217621683> 
01:29:28.851690 IP 10.0.100.21.389 > 10.0.100.22.36157: F 1370:1370(0) ack 214 win 54 <nop,nop,timestamp 217622117 66437823> 
01:29:28.851703 IP 10.0.100.22.36157 > 10.0.100.21.389: . ack 1371 win 133 <nop,nop,timestamp 66437823 217622117> 
まず、
次に、
注意点としては、
このように、
同期対象エントリの把握
2通りのレプリケーションがあることはわかりましたが、
まずキーワードとなるのはentryCSN
% ldapsearch -x -D "cn=Manager,dc=example,dc=com" -w secret -b "dc=example,dc=com" "objectClass=*" entryCSN # example.com dn: dc=example,dc=com entryCSN: 20090328154606.075631Z#000000#000#000000 # Group, example.com dn: ou=Group,dc=example,dc=com entryCSN: 20090328154606.151415Z#000000#000#000000
内容から容易に想像できるように、
まずは、
このとき、
コンシューマに対する更新要求
同期のタイミングを考慮しないものとすれば、
adding new entry "ou=1238266045,dc=example,dc=com" ldap_add: Server is unwilling to perform (53) additional info: shadow context; no update referral
これは当然のことで、
そのため、
# 更新のためにプロバイダを使用する
updateref ldap://10.0.100.21:389
こうすることによってエラー内容が次のように変わります。
adding new entry "ou=1238266045,dc=example,dc=com" ldap_add: Referral (10) referrals: ldap://10.0.100.21:389/ou=1238266192,dc=example,dc=com
やはりエラーにはなってしまうのですが、
ちなみに、
セキュアなレプリケーション用DN
refreshOnly、
「レプリケーション用にcn=Manager,dc=example,dc=comを使用していますが、
といった記述を見かけます。事実筆者も今まで多くの場合このような解説をしてきました。ですが、
dn: cn=replication,dc=example,dc=com
というDNをレプリケーション専用のDNとすることにしましょう。まずはプロバイダ側でエントリの作成です
dn: cn=replication,dc=example,dc=com 
objectClass: person 
cn: replication 
sn: replication account 
userPassword: {SSHA}+cGs2GJzG38V76E3KZIu3W0ZsZWTZTLh 
ではいつものようにエントリを登録します。
% ldapadd -x -D "cn=Manager,dc=example,dc=com" -w secret -f replication.ldif adding new entry "cn=replication,dc=example,dc=com"
次に、
access to *
  by dn="cn=replication,dc=example,dc=com" write
としてしまっては、
- cn=replication用の権限は全エントリの閲覧のみ
(データ更新の必要はない)  - cn=replicationはコンシューマからのみ利用される
(接続元を指定)  
を実現することで、
access to attrs=userPassword 
  by self write 
  by dn="cn=replication,dc=example,dc=com" peername.ip=10.0.100.22 read 
  by dn="cn=replication,dc=example,dc=com" peername.ip=0.0.0.0%0.0.0.0 none 
  by anonymous auth 
  by * none 
access to * 
  by dn="cn=replication,dc=example,dc=com" peername.ip=10.0.100.22 read 
  by dn="cn=replication,dc=example,dc=com" peername.ip=0.0.0.0%0.0.0.0 none 
  by self write 
  by * read 
まとめ
今回はOpenLDAPの基本形となる2通りのレプリケーション方法を解説してきました。2台以上のLDAPサーバを立て、
しかし実際には様々な課題が存在します。まずはこの方式で冗長性を実現させるためには、
uri ldap://接続先1/ ldap://接続先2/
というフォーマットが許可されています。しかし、
それ以外でも、
設定ファイル
今回の設定ファイル全体を貼り付けておきますので、
include		/etc/openldap/schema/core.schema 
include		/etc/openldap/schema/cosine.schema 
include		/etc/openldap/schema/inetorgperson.schema 
include		/etc/openldap/schema/nis.schema 
pidfile		/var/run/openldap/slapd.pid 
argsfile	/var/run/openldap/slapd.args 
database	bdb 
suffix          "dc=example,dc=com" 
rootdn          "cn=Manager,dc=example,dc=com" 
rootpw		secret 
directory	/var/lib/ldap 
loglevel        256 
 
index objectClass         eq,pres 
index entryCSN,entryUUID  eq 
access to attrs=userPassword 
  by self write 
  by dn="cn=replication,dc=example,dc=com" peername.ip=10.0.100.22 read 
  by dn="cn=replication,dc=example,dc=com" peername.ip=0.0.0.0%0.0.0.0 none 
  by anonymous auth 
  by * none 
access to * 
  by dn="cn=replication,dc=example,dc=com" peername.ip=10.0.100.22 read 
  by dn="cn=replication,dc=example,dc=com" peername.ip=0.0.0.0%0.0.0.0 none 
  by self write 
  by * read 
overlay syncprov
include		/etc/openldap/schema/core.schema 
include		/etc/openldap/schema/cosine.schema 
include		/etc/openldap/schema/inetorgperson.schema 
include		/etc/openldap/schema/nis.schema 
pidfile		/var/run/openldap/slapd.pid 
argsfile	/var/run/openldap/slapd.args 
database	bdb 
suffix          "dc=example,dc=com" 
rootdn          "cn=Manager,dc=example,dc=com" 
rootpw		secret 
directory	/var/lib/ldap 
loglevel        256 
index objectClass         eq,pres 
index entryCSN,entryUUID  eq 
access to attrs=userPassword 
  by self write 
  by dn="cn=replication,dc=example,dc=com" peername.ip=0.0.0.0%0.0.0.0 none 
  by anonymous auth 
  by * none 
access to * 
  by dn="cn=replication,dc=example,dc=com" peername.ip=0.0.0.0%0.0.0.0 none 
  by self write 
  by * read 
# 即時レプリケーションを行う場合
syncrepl rid=100 
  provider=ldap://10.0.100.21:389 
  type=refreshAndPersist 
  retry="5 10 300 +" 
  searchbase="dc=example,dc=com" 
  bindmethod=simple 
  binddn="cn=Manager,dc=example,dc=com" 
  credentials=secret
# 定期的にレプリケーションを行う場合
#syncrepl rid=100 
#  provider=ldap://10.0.100.21:389 
#  type=refreshOnly 
#  interval=00:00:60:00 
#  searchbase="dc=example,dc=com" 
#  bindmethod=simple 
#  binddn="cn=Manager,dc=example,dc=com" 
#  credentials=secret 
updateref ldap://10.0.100.21:389 
