389 Directory Server では、ひとつのユーザデータベースに対して最大 4台までのマスターを置くことができる。コンシューマーの数には制限はない。レプリケーションの単位はデータベースで、特定のサブツリーのみをレプリケーションの対象とすることはできない。ひとつのサフィックスが複数のデータベースにまたがっているとレプリケーションは不可能なので、ディレクトリサーバの構成時に注意が必要だ。
まず、基本的な用語についてクリアにしておく;
レプリケーションにおけるサーバの役割には以下のものがある;
例として、主をマシン centos5u.hoge.com 上のディレクトリサーバインスタンス centos5u、もう 1台が centos5u2.hoge.com 上の centos5u2 インスタンスとする。
コンシューマー側にも、サプライヤーと同じディレクトリサフィックス (これからレプリケーション対象とするもの) があらかじめ存在していなければならない。ただし中身のデータや ACL は整えておく必要はない。インスタンス名はサプライヤー側と異なっていても構わない。
389 DS のレプリケーションはサプライヤー主導型 (Supplier-initiated Replication)。更新データは、コンシューマーが取りに行くのではなく、いつもサプライヤーからコンシューマーにプッシュされる。その時に更新権限の確保に使われるユーザエントリが、サプライヤーバインドDN だ。サプライヤーバインドDN は、コンシューマー側のサーバインスタンス上に作る。
この DN は、レプリケーション対象となるデータベース自体の中にあってはいけない。まだ空の状態のコンシューマーデータベースをサプライヤーからイニシャライズ(初期同期)する時のことを考えれば理由は飲み込めるだろう。通例、設定管理ディレクトリツリー cn=config の直下に作ることが多いようだ。作成方法を以下に示す。
コンシューマーのディレクトリサーバインスタンスを停止する。
root# service dirsrv stop centos5u2
コンシューマー側の /etc/dirsrv/slapd-centos5u2/dse.ldif に下記の定義を追加する。ファイル末尾に追加すればよい。後でサーバインスタンスを再開するとファイルが再パースされて然るべき位置に納まる。
dn: cn=Replication Manager,cn=config objectClass: inetorgperson objectClass: person objectClass: top cn: Replication Manager sn: RM userPassword: password passwordExpirationTime: 20380119031407Z nsIdleTimeout: 0
passwordExpirationTime の数値はパスワードを無期限にするもの。nsIdleTimeout はレプリケーション中にアイドルセッションが切られないようにするため。
root# service dirsrv start centos5u2
レプリケーションデータの流れを暗号化したい場合には、前ページを参照して SSL/TLS の設定を済ませておく。
対象データベースの一部パラメータはレプリケーションで同期されないように見える。筆者が気付いたのは、データベースのパスワード格納形式だった。デフォルトの SSHA から変更している場合は、コンシューマー側データベースのパスワードハッシュ形式をあらかじめサプライヤーと合わせておいたほうがよさそうだ。
実施する作業項目を、サーバの役割毎に分類するとこうなる。
ハブ以外の場合 | ハブの場合 | ||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
1-1. |
当該インスタンスの Configuration タブを開き、左ペインのツリーで Replication をハイライトし、右ペインの Supplier Settings タブを開く。ここはサプライヤーとしての設定だ。 Enable Changelog にチェック。チェンジログ(更新ログ) とはデータベースで言うところのトランサクションログにあたり、レプリケーションは、そこに記録されたトランザクションをコンシューマー側で再現することによって行われる。 Changelog database directory 欄に更新ログ保存ディレクトリパスを入力 (Use default ボタンを押せばデフォルトのパスが自動的に入る)。 更新記録が野放図に膨張しないよう、レコード数か期間のいずれかで記録の破棄を設定する。 必要事項がそろったら Save ボタンで保存する。 |
1-2. |
当該インスタンスの Replication ツリー配下のユーザデータベース (例では 1つしかないので UserRoot) をハイライトし、右ペインで、 Enable Replica にチェック。 Replica Role のからこのサーバの役割を選択。 Replica ID は、レプリケーションペアを識別するための番号 ( 1~65534) で、このデータベースがマスターである (つまりシングルマスターかマルチマスター) 時だけ指定が必要。ひとつのディレクトリサフィックスのレプリケーションに関わるサーバ群の中では、重複のないように割り振らなければならない。マルチマスター構成の場合、サーバどうしは主->副と副->主の2本のレプリケーション合意を確立するわけで、片方の Replica ID が 1 なら、もう一方では 2 など違った値にする。 Purge delay は、更新履歴データベースに古いステートレコードをどれだけの期間保持しておくかの設定。 |
1-3. |
前画面をスクロールすると Update Settings 設定パネルがある。ここはコンシューマーとしてのパラメータ群なので、送り手専門であるシングルマスターの時はグレーアウトしている。 サプライヤーDN 欄には、自サーバ上に登録しておいたサプライヤーバインドDN を入れる。 その下のリフェラル(referral)欄には、相手サプライヤーの LDAP URL を入れる。ただし、ハブからレプリケーションを受けるコンシューマーの場合は、ハブでなくその上位のサプライヤーを指定する。LDAP におけるリフェラル (RFC3296) とは、問い合わせを発したクライアントに対して検索結果の代わりに「それについては**サーバに問い合わせなさい」という返事を返すもので、クライアントは (リフェラルを辿る設定になっていれば) 紹介された URL に問い合わせをしなおす。この欄には ldap://centos5u.hoge.com:389 といったフォーマットで URL を入力。リファー先への問い合わせをセキュアLDAPプロトコルで行わせたければ ldaps://centos5u.hoge.com:636 のように指定すればいい。この設定によって、ディレクトリサフィックスのリフェラル設定が連動して切り替わる。 最後に Save ボタンで保存するのを忘れずに。 |
全てのレプリケーションサーバで上記の設定が終わったら、レプリケーション合意を締結する。カスケード構成の場合は、先にシングルマスターからハブへ向けて合意を結び、次にハブから専従コンシューマーへ締結する。
2-1. |
サプライヤー側の Configuration タブ のツリーで Replication を展開してレプリケーション対象のデータベースを右クリックし、New Replication Agreement を選択する。 |
2-2. |
レプリケーション合意の定義名と説明を入力。 |
2-3. |
Consumer 欄で相手のコンシューマーを指定。相手が同じ物理サーバ上にあるインスタンス (つまりマルチインスタンス) ならドロップダウンメニューで選べるが、そうでない場合は Other ボタンを押してホスト名とポート番号を打ち込む。ここで表示に上がるポート番号は対象インスタンスを特定するための便宜的なものなので、レプリケーションに関わる通信を SSL で行う予定だとしても標準ポートのほうで問題ない。 Connection 設定グループでは、通信を暗号化するかどうかと、認証方法を決める。SSL や TLS を使う場合は、あらかじめ SSL/TLS の設定を完了させておかなければならない。認証メカニズムでは、Simple を選択し、Bind as に相手コンシューマー上のサプライヤーバインドDN、Password にそのパスワードを入力する (389 DS で証明書ベースの認証をセッティングするのは非常に面倒くさい)。 |
2-4. |
Fractional Replication (部分レプリケーション) の設定。有効にすれば、特定の属性をレプリケーション対象から除外することができる。除外指定した属性は、実際はレプリケーションはされるのだが、値をヌルとみなしてコピーするので、結果として、コンシューマーに LDAP検索を掛けてもヒットしなくなる。 |
2-5. |
同期タイミングの指定。通常は Always keep ... つまり常時同期を選択するが、曜日と時間でスケジュールすることも可能なようだ。 |
2-6. |
レプリケーション合意締結と同時にコンシューマーデータベースのイニシャライズも実施するかどうか。イニシャライズでは、サプライヤーのデータベースがコンシューマーへフルコピーされる。 イニシャライズはサプライヤー/コンシューマーのペアに対して一度だけ行う。つまり、マルチマスターどうしでは、サーバA からサーバB へレプリケーション合意を結ぶ時にはイニシャライズを実行するが、B から A へ結ぶ際にはしてはいけない。 カスケードレプリケーション構成の場合は、シングルマスターからハブ、ハブから専従コンシューマーの両方でイニシャライズを実行する。 |
マルチマスター構成の場合、同一のディレクトリエントリ (例えばユーザ) がほぼ同時に両方のマスターに対して登録されると、レプリケーションの競合が発生することがある。そういった場合には手動でどちらかのエントリ削除してやらなければならないのだが、例えば mail 属性あるいは uid 属性の値の一意性に依存しているメールサーバなどの場合、競合の発生した途端にそのユーザはメールの送受信ができなくなってしまう。
競合発生時、389 DS のレプリケーションエンジンは、時間的に後で作られた方のエントリに nsds5ReplConflict という属性を加える。少なくとも業務が続けられるようにするには、この属性の付いているエントリが LDAP検索にヒットしないようにしておくとよい。
具体的には、ユーザ検索を代表ユーザだけで行っている場合は、その検索権限を規定している ACI (前述の ACL設定解説で言えば ou=People,dc=hoge,dc=com に掛けた ACI "UserDataAdminRetrieve") に、
(targetfilter = (!(nsds5ReplConflict=*)))
というターゲットフィルタを追加してやる。389 Management Console でやるなら、上図のように Filter for sub-entries にフィルタ部分だけを書いてやればいい。読み取りや検索をアノニマスバインドでやらせているディレクトリなら、デフォルトでディレクトリトップに規定されている "Enable anonymous access" ACI に同様の処置をしておけばよい。
サプライヤーは、コンシューマーを同期する時に相手レプリカに排他ロックを掛ける。マルチマスター構成では、更新の非常に頻繁なひとつのサプライヤーがコンシューマーへのロックを独占し続けてしまい、他のサプライヤーがレプリケーションを実行できなくなることがあるらしい。これを予防するには、各マスターレプリカのレプリケーション合意の持つ 2つの属性を調整する必要がある。この現象と対処方法は、Red Hat Directory Server Administration Guide の "Preventing Monopolization of the Consumer in Multi-Master Replication" に書かれている。
ここでは、ldapmodify コマンドでオンラインのままパラメータを変更することにする。dse.ldif に直接書いてもいいのだが、それだとサーバインスタンスを再起動しなければならない。オンラインで変更すると、次回の同期から有効になる。
まず、当該マスターサーバのアプリケーション合意の DN を調べる。
user$ ldapsearch -T -D "cn=Directory Manager" -w - \ -b "cn=config" objectclass=nsds5ReplicationAgreement version: 1 dn: cn=RepAgree, cn=replica, cn="Suffix", cn=mapping tree, cn=config objectClass: top objectClass: nsDS5ReplicationAgreement ...
dn: に出力されたものが目的の DN だ。それを元に、下記の LDIF ファイルを作る (ldapmodify で直接投入しても構わないが)。
dn: <上記検索で得たDN>
changetype: modify
replace: nsds5ReplicaBusyWaitTime
nsds5ReplicaBusyWaitTime: 3
-
replace: nsds5ReplicaSessionPauseTime
nsds5ReplicaSessionPauseTime: 4
nsds5ReplicaBusyWaitTime は、相手コンシューマーがロックされていた場合に再度レプリケーションを試みるまでの間隔。nsds5ReplicaSessionPauseTime は、ひとつの同期処理が終わってから次の同期処理を開始するまでの間隔。暗黙のデフォルトは前者が 3秒で、後者は 0秒。独占を防ぐには、SessionPauseTime を BusyWaitTime よりも最低 1秒は長くする。
上記内容を、例えば anti-monopolize.ldif として保存したとする。ldapmodify で読み込ませて投入するには;
user$ ldapmodify -D "cn=Directory Manager" -w - \
-f anti-monopolize.ldif