備忘録のため,内容の正当性については責任を持ちません。

BIND に代わる権威 DNS サーバの実装として巷で話題の PowerDNS と NSD を組み合わせて、DNS クラスタを構築してみる。


特徴

PowerDNS とは

PowerDNS とはオープンソースの DNS サーバで、バックエンドに MySQL などの RDB を使うことができる。その特徴から、多数のサードパーティ製 Web UI や API が存在する。権威サーバの pdns-server とキャッシュサーバの pdns-recursor がある。

NSD とは

NSD (Name Server Daemon) もまたオープンソースの権威 DNS サーバで、高性能でシンプルだと謳われている。キャッシュサーバの機能はない。バージョン4からは、ゾーンの動的な追加、削除が可能となっている。


要件

今回構築するシステムでは、次のような項目を要件とする。

  • レコード情報は RDB で管理する
  • 適当な Web UI を用意する
  • master にゾーンを追加、削除した際の slave への同期は自動化する
  • インターネットからの名前解決要求には NSD が答える

これを実現するために、次のような構成を検討する。

  • master: PowerDNS × 1台
  • slave: NSD × 2台以上

レジストリや NS レコードには、権威サーバとして slave のみを登録し、インターネットから master が直接参照されないようにする。

構成図

構成図

構築

それでは早速 master および slave サーバを構築していく。OS はいずれも Ubuntu 12.04.4 を使う。

$ cat /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=12.04
DISTRIB_CODENAME=precise
DISTRIB_DESCRIPTION="Ubuntu 12.04.4 LTS"

PowerDNS

まずは PowerDNS で master サーバを構築する。backend には MySQL を使う。

必要なパッケージを入れる。

# apt-get update
# DEBIAN_FRONTEND=noninteractive apt-get install -y pdns-server pdns-backend-mysql mysql-server mysql-client

設定を編集する。

# diff /etc/powerdns/pdns.conf.orig /etc/powerdns/pdns.conf
6c6
< # allow-axfr-ips=
---
> allow-axfr-ips=(slave の IP アドレスの範囲 (カンマ区切りで複数可))
57c57
< disable-axfr=yes
---
> disable-axfr=no
132c132
< # master=no
---
> master=yes

DNSSEC は使わないので無効にしておく。

# sed -i 's/^gmysql-dnssec=yes/gmysql-dnssec=no/' /etc/powerdns/pdns.d/pdns.local.gmysql

データベースのテーブルを作成する。スキーマは公式マニュアルの MySQL specifics からもらってくる。

# mysql -u root pdns
mysql> CREATE TABLE ...

リロードする。

# service pdns reload

ログの出力先を変更する。

# echo 'local0.*                /var/log/pdns.log' > /etc/rsyslog.d/pdns.conf
# echo 'local0.none             -/var/log/syslog' >> /etc/rsyslog.d/pdns.conf
# service rsyslog reload

これだけで PowerDNS がインストールできた。

Poweradmin

PowerDNS には多数のサードパーティ製 Web UI があるが、今回はそのうちの一つである Poweradmin を入れてみる。

Poweradmin

Poweradmin

まず必要なパッケージを入れる。

# apt-get install -y apache2 php5 php5-mcrypt php5-mysql git
# service apache2 reload

ソースコードを配置する。

# mkdir ~/src
# cd ~/src
# git clone https://github.com/poweradmin/poweradmin.git
# cp -pr poweradmin /var/www/
# chown -R www-data:www-data /var/www/poweradmin

Web ブラウザでインストール画面にアクセスする。

  • http://(IP アドレス)/poweradmin/install/

データベースの接続情報は PowerDNS の設定ファイルで確認できる。

# cat /etc/powerdns/pdns.d/pdns.local.gmysql

インストールが済んだら、インストール画面を無効化する。

# mv /var/www/poweradmin/install /var/www/poweradmin/install.bak
# chmod 0 /var/www/poweradmin/install.bak

ログイン画面にアクセスする。 (admin / 設定したパスワード)

  • http://(IP アドレス)/poweradmin/

試しに Add master zone から適当なゾーンを追加してみる。今回は example.com とする。その後、PowerDNS で引けるようになるか確認する。

$ dig @127.0.0.1 example.com. soa +short
ns1.example.jp. hostmaster.example.jp. 2014051100 28800 7200 604800 86400

これで master 側の準備ができた。

NSD

次は NSD で slave サーバを構築する。

Ubuntu 14.04 では apt で nsd4 が入るが、挙動が微妙だったのでソースからビルドすることにする。手順は下記の記事を参考にする。なお、現時点での最新バージョンは 4.0.3 だった。

make install できたら、設定ファイルを編集する。肝は pattern を定義すること。

# diff /etc/nsd4/nsd.conf.sample /etc/nsd4/nsd.conf
143c143
<       # control-enable: no
---
>       control-enable: yes
182c182,186
< # pattern:
---
> pattern:
>       name: "slavezone"
>       zonefile: "%s.zone"
>       allow-notify: (master の IP アドレス) NOKEY
>       request-xfr: (master の IP アドレス) NOKEY

起動スクリプトを配置する。

# install -o root -g root -m 755 /path/to/nsd-4.0.3/contrib/nsd.init /etc/init.d/nsd
# sed -i 's#/etc/nsd.conf#/etc/nsd4/nsd.conf#' /etc/init.d/nsd
# sed -i 's#^sbindir="/usr/sbin"#sbindir="/usr/local/sbin"#' /etc/init.d/nsd

起動する。

# /etc/init.d/nsd start

念のため master から AXFR でゾーン転送できるか確認しておく。

# dig @(master の IP アドレス) example.com. axfr +short
ns1.example.jp. hostmaster.example.jp. 2014051100 28800 7200 604800 86400
ns1.example.jp. hostmaster.example.jp. 2014051100 28800 7200 604800 86400

nsd-controladdzone で slave ゾーンを追加してみる (slavezone の部分は設定ファイルで指定した名前)。

# nsd-control addzone example.com slavezone
ok

master からゾーン転送できているか確認する。

# dig @127.0.0.1 example.com. soa +short
ns1.example.jp. hostmaster.example.jp. 2014051100 28800 7200 604800 86400

うまくいったようなので、2台目以降の slave も同様に構築する。

同期の自動化

これまでの手順で、PowerDNS の master と NSD の slave による DNS を構築できた。

ただし現時点では、master にゾーンを追加、削除するたびに、各 slave で nsd-controladdzonedelzone を実行しなければならない。これは面倒なので、master から slave へのゾーンリストの同期を自動化する。

流れとしては次のような感じ。

  1. master でゾーンのリストを作る
  2. slave でゾーンのリストを作る
  3. slave でリストを照合し、差分を追加、削除する

まずは master サーバ側で、ゾーンリストを生成するスクリプトを作成する。名前は ~ubuntu/zone_sync/master_zones.sh とする (ubuntu は任意のユーザ)。

#!/bin/sh

PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

DIR=$(cd $(dirname $0); pwd)
cd $DIR

mysql -BN -u root pdns -e "SELECT name FROM domains WHERE TYPE = 'master';" \
    | sort \
    > .master_zones.txt.tmp \
    && mv .master_zones.txt.tmp master_zones.txt

実行権を与える。

# chmod +x master_zones.sh

多重起動を防止するために daemontoolssetlock を使う。

# apt-get install -y daemontools

cron に登録する。実行間隔は適当に調整する。

# crontab -u ubuntu -e
* * * * * setlock -n /tmp/master_zones.lock /home/ubuntu/zone_sync/master_zones.sh

これで定期的に master サーバ上でゾーンのリスト (master_zones.txt) が吐き出されるようになった。

以降は slave で作業する。まず ssh の公開鍵を生成する。

# ssh-keygen

ssh の設定ファイルを作成する。

# vi /root/.ssh/config
Host (master の IP アドレス)
    StrictHostKeyChecking no
    UserKnownHostsFile /dev/null

master に鍵を配置する。

# ssh ubuntu@(master の IP アドレス) 'cat >> .ssh/authorized_keys' < .ssh/id_rsa.pub

master に鍵認証で ssh ログインできるか確認する。

# ssh ubuntu@(master の IP アドレス) hostname
Warning: Permanently added 'XXX.XXX.XXX.XXX' (ECDSA) to the list of known hosts.
ns0.example.jp

同期スクリプトを作成する。名前は /root/zone_sync/zone_sync.sh とする。

#!/bin/sh

PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

MASTER_HOST=(master の IP アドレス)
MASTER_USER=ubuntu

set -e

DIR=$(cd $(dirname $0); pwd)
cd $DIR

scp -p $MASTER_USER@$MASTER_HOST:zone_sync/master_zones.txt .
nsd-control zonestatus | grep '^zone:' | awk '{print $2}' | sort > slave_zones.txt

for i in $(diff master_zones.txt slave_zones.txt | grep '^<' | awk '{print $2}'); do
    nsd-control addzone $i slavezone > /dev/null || :
done

for i in $(diff master_zones.txt slave_zones.txt | grep '^>' | awk '{print $2}'); do
    nsd-control delzone $i > /dev/null || :
done

nsd-control write

同じく daemontools を入れる。

# apt-get install -y daemontools

cron に登録する。

# crontab -e
* * * * * setlock -n /tmp/zone_sync.lock /root/zone_sync/zone_sync.sh

これで自動的に同期されるようになった。試しに Poweradmin で適当にゾーンを追加、削除して、動作を確認してみると良い。

おわりに

以上で PowerDNS と NSD を組み合わせた DNS クラスタが構築できた。今後は大量のゾーン、レコードを投入しての動作検証や、dnsperf などを用いた負荷テストをやりたい。

参考ページ

コメント

コメントする




CAPTCHA