前回の記事で、PowerDNS と NSD を組み合わせて DNS を構築した。
その後、検証のために大量のゾーンを突っ込んでみたところ、困った現象に遭遇したのでまとめておく。
その現象とはこの記事のタイトルの通りで、slave として動く NSD は refresh するとき master の serial
値を確認してくれないということだ。
master と slave の同期について
本題に入る前に、DNS の master と slave の同期についておさらいしておく。
あるゾーン example.com
において refresh
時間が経過したとき、slave は master との再同期を試みる。master と slave の同期については RFC 1034 の 4.3.5. Zone maintenance and transfers で定義されており、要約すると次のようなことが書かれてある (と思う)。
- slave から master に
example.com
のSOA
を問い合わせる。 - master は slave に
serial
他の情報を答える。 - slave は「master から返ってきた
serial
値」と「自身が持つserial
値」を比較する。 serial
が更新されていないなら処理を終了する。更新されていれば、slave は master にゾーン転送 (AXFR
) を TCP で要求する。- master は slave にゾーンを転送する。
この動作については、次の記事の図がわかりやすい。
再同期において、1〜2 の通信は UDP で行なわれ、serial
が更新されていなければその後のゾーン転送は行なわれないため、さほど負荷はかからないはずだ。
観測した事象
refresh
を 300
に設定したゾーンを4万件程度投入して master 側 (PowerDNS) のホストのリソースを見守っていたところ、激しく負荷がかかっていた。
原因
原因を調べるために tcpdump でゾーン同期の様子を眺めてみたところ、どうやら NSD は上記の 1〜3 をすっ飛ばしていきなり 4 から始めているようだった。ML の過去ログを漁ってみたところ、次のような投稿が見つかった。
An AXFR initiated by the built-in transfer process will not start with a SOA query at all.
この通り、refresh 時の serial
比較機能は NSD に実装されていないようだ。
BIND の場合
BIND 9.8.1 を slave にして同様の確認をしたところ、きちんと上記の流れで動作しており、高負荷は見られなかった。そして BIND 9.7.2 からは、NSD と同様に動的にゾーンを追加、削除できるようになっている。ということで NSD は諦めて BIND を使うか……。
コメント