そろそろLDAPにしてみないか?

第3回 もう一歩進んだUNIXアカウント

この記事を読むのに必要な時間:およそ 3 分

インデックス設定

ディレクトリエントリ数が少ない場合にはとくに問題ないのですが,データが多くなるにつれ大きなパフォーマンスダウンにつながるのが,インデックス関連の設定です。リスト3のスクリプトを図6のコマンドのように使うと,ダミーエントリを5,000個作成します。

リスト3 add.sh

#!/bin/sh
i=1
while [ $i -le 5000 ]; do
  echo "dn: uid=ldapuser$i,ou=People,dc=example,dc=com"
  echo "objectClass: account"
  echo "objectClass: posixAccount"
  echo "uid: ldapuser$i"
  echo "cn: ldapuser"
  echo "userPassword: ldapuser$i"
  echo "loginShell: /bin/bash"
  echo "uidNumber: 10$i"
  echo "gidNumber: 10$i"
  echo "homeDirectory: /home/ldapuser$i"
  echo ""
  i=`expr $i + 1`
done

図6 ダミーエントリの登録

% ./add.sh | ldapadd -x -c -D "cn=manager,dc=example,dc=com" -w secret

この状態で再びidコマンドを使って適当なエントリの情報を取得してみます(図7)。

図7 idコマンドの実行

% time id ldapuser996
uid=10996(ldapuser996) gid=10996 groups=10996

real    0m10.339s
user    0m0.002s
sys     0m0.055s

なんと,1ユーザのエントリを取得するのに約10秒もかかってしまいました.nscdが有効であるため,再び同じユーザ情報を得る場合にはそれほど時間がかかりませんが,最初の検索で10秒というのは大きな問題です。

LDAP,RDBMSにせよ,全文検索にしてもそうなのですが,インデックスとは検索を高速化するための効果的な手段です。いくらLDAPが検索重視のプロトコルだと言っても,インデックスを含め,適切な設定が行われていないサーバでは,その恩恵を実感することができません。

ということで,インデックスの設定を行ってみましょう。インデックスとは作成しさえすれば良いものではありません。不必要なインデックスは,ディスクを圧迫したり,かえってパフォーマンスダウンにつながる恐れもあるためです。用途に応じて適切なインデックスを作成する,これが正しい選択です。

今回問題となっているのは,idコマンドを実行した場合です。それではidコマンドを使用した場合にLDAPサーバ側ではどのようなエントリが検索されているのでしょうか?それはサーバ側のログを見ることで把握できます。

さて,ログを見るといっても,CentOSの場合/etc/syslog.confに適切な設定が存在しないため,そのままでは検索時のログを取得することができません.slapdはデフォルトでlocal4というファシリティを使用するため,LDAPサーバ側のsyslog.confをリスト4のように編集し,デーモンを再起動しておいてください(図8)。

リスト4 /etc/syslog.confに追加する内容

local4.*         /var/log/ldap.log

図8 ログファイルの作成とsyslogdの再起動

# touch /var/log/ldap.log
# chmod 600 /var/log/ldap.log
# /etc/init.d/syslog restart

syslog.confの設定が完了したら,まずは現在の設定のままで再びidコマンドを実行し,サーバ側でどのような検索が行われているのかを把握しておきます.LDAPサーバへ確実に接続できるよう,クライアント側のnscdは一時的に無効にしておくことをお勧めします。

それではidコマンドを実行しつつ,ldap.logの中身を確認してみます(図9,リスト5)。

図9 idコマンドの実行

% id ldapuser
/euid=1000(ldapuser) gid=1000 groups=1000

リスト5 /var/log/ldap.logの一部

Jul 15 17:19:31 localhost slapd[11014]: <= bdb_equality_candidates: (objectClass) index_param failed (18)
Jul 15 17:19:31 localhost slapd[11014]: <= bdb_equality_candidates: (uid) index_param failed (18)
Jul 15 17:19:31 localhost slapd[11014]: <= bdb_equality_candidates: (uidNumber) index_param failed (18)
Jul 15 17:19:31 localhost slapd[11014]: <= bdb_equality_candidates: (gidNumber) index_param failed (18)
Jul 15 17:19:31 localhost slapd[11014]: <= bdb_equality_candidates: (memberUid) index_param failed (18)
Jul 15 17:19:31 localhost slapd[11014]: <= bdb_equality_candidates: (uniqueMember) index_param failed (18)

このように,objectClassやuid属性などのインデックス検索に失敗していることがわかりますので,それぞれのインデックス設定を行います。インデックス設定には表2の項目が用意されています。

表2 インデックスの種類

設定値意味検索例
pres存在uid=*
eq等価uid=ldapuser
approx近似uid=ldapusr
sub部分一致uid=ldap*
none無し-

ldap.logからfilterというキーワードを検索することで,今回LDAPサーバでは次のような検索が行われています。

filter="(&(objectClass=posixAccount)(uid=ldapuser))" 
filter="(&(objectClass=posixAccount)(uidNumber=1000))" 
filter="(&(objectClass=posixGroup)(gidNumber=1000))" 
filter="(&(objectClass=posixGroup)(|(memberUid=ldapuser)(uniqueMember=uid=ldapuser,ou=people,dc=example,dc=com)))"

これにより,今回の検索ではobjectClass,uid,uidNumber,gidNumber,memberUid,uniqueMember属性に対して等価検索が行われていることがわかるはずです。ではこれに従ってLDAPサーバ側のslapd.confに設定を追加します(リスト6)。

リスト6 slapd.confに追加する内容

index objectClass,uid,uidNumber,gidNumber,memberUid,uniqueMember eq

このように,インデックスを適切に設定した上でslapdを停止,slapindexコマンドでインデックスを作成した後各ファイルのパーミッションを適切に設定,slapd起動,という順序で検索を高速化することが出来ます。ただ,今回検証に用いたCentOSでは

equality index of attribute "uniqueMember" disallowed

というエラーが表示され,slapdの起動に失敗してしまいました。どうやらこのバージョンでは文字通りこのインデックスに対する処理がインプリされていないようです。少々気持ちが悪いかもしれませんが,実際にはnss_ldapにおいては,uidやuidNumberなどによる検索でエントリが発見されれば,uniqueMemberを使った検索は当面現れません。したがって,今回は

index objectClass,uid,uidNumber,gidNumber,memberUid eq

というインデックスのみを設定してみました。ちなみに最近の新しいバージョンのOpenLDAPではこのエラーは出ないことを確認しています(図10,11)。

図10 LDAPサーバ側での作業

# /etc/init.d/ldap stop
# slapindex
# chown -R ldap:ldap /var/lib/ldap
# /etc/init.d/ldap start

図11 クライアントからのidコマンド

# time id ldapuser3008
uid=103008(ldapuser3008) gid=103008 groups=103008

real    0m0.141s
user    0m0.021s
sys     0m0.102s

最終的には,ログ中にインデックス関連の警告が出なくなるまで設定を行ってみてください。

著者プロフィール

中満英生(なかみつひでお)

大学時代に出会ったSolarisがきっかけでUNIXの世界へ。その後ホスティングプロバイダ,データセンターで実務経験を積む傍ら,雑誌記事の執筆や技術セミナーの講師を務める。サーバ設定の他,セキュリティに関する著作や技術者エッセイも執筆経験あり。