2026年6月10日
2026年6月10日
CoreDNS のセカンダリ構成方法|secondary プラグインでのゾーン受信と transfer プラグインでの送信
CoreDNS でプライマリ・セカンダリの2台構成を作るには、プライマリ側で file プラグインと transfer プラグインを使ってゾーン転送(AXFR)を許可し、セカンダリ側で secondary プラグインを使ってゾーンを取り込みます。設定そのものは数行ですが、CoreDNS のセカンダリは受け取ったゾーンをディスクに保存しないという大きな特徴があり、ここを知らずに組むと再起動時に答えられなくなることがあります。この記事では、両側の Corefile の書き方、動作確認、運用上の注意点を順に説明します。
プラグインの仕様やオプションは版によって変わることがあるため、手元の版の公式ドキュメント(coredns.io の各プラグインのページ)と照らし合わせてください。以下は執筆時点の情報です(2026年10月現在)。作業前には Corefile とゾーンファイルをバックアップし、できれば検証環境で一度動かしてから本番に入れます。
構成の全体像を決める
2台の役割は次のどちらかになります。
- CoreDNS どうしで組む:プライマリの CoreDNS がゾーンファイルを持ち、セカンダリの CoreDNS が AXFR で取りに行きます。この記事の中心はこの形です。
- ほかのソフトと組む:プライマリが BIND や PowerDNS、セカンダリが CoreDNS という組み合わせも可能です。逆に、CoreDNS をプライマリにして BIND や NSD をセカンダリにする形もあります。ゾーン転送は標準の仕組みなので、相手が何であっても考え方は同じです。
どちらの場合も、2台は別のネットワーク(できれば別の事業者やデータセンター)に置きます。同じ回線や同じ電源の上に並べると、障害時に両方そろって止まり、セカンダリを置く意味が薄れます。
プライマリ側の Corefile
プライマリは file プラグインでゾーンファイルを読み込み、transfer プラグインでゾーン転送を許可します。
# /etc/coredns/Corefile(プライマリ 192.0.2.1)
example.com {
file /etc/coredns/db.example.com {
reload 1m
}
transfer {
to 198.51.100.2
}
log
errors
}
transfer の to には、転送を許可するセカンダリのアドレスを書きます。* と書くとどこからでも転送できてしまうため、インターネットに公開するサーバーでは使わず、必要なアドレスだけを並べます。to に具体的なアドレスを書いた場合、CoreDNS はゾーンが更新されたときにその相手へ NOTIFY を送ります。
file の reload は、ゾーンファイルの SOA シリアルが変わったかを確認する間隔です。シリアルが上がっていればゾーンを読み直し、セカンダリへの通知につながります。逆に言えば、レコードを書き換えてもシリアルを上げ忘れると、プライマリ自身も変更を反映しません。ゾーンファイルを編集したら、シリアル(例:2026101801 のような日付+連番)を上げる習慣をつけておきます。
; /etc/coredns/db.example.com(抜粋)
$ORIGIN example.com.
@ 3600 IN SOA ns1.example.com. hostmaster.example.com. (
2026101801 ; serial
3600 ; refresh
600 ; retry
1209600 ; expire
300 ) ; minimum
@ 3600 IN NS ns1.example.com.
@ 3600 IN NS ns2.example.com.
ns1 3600 IN A 192.0.2.1
ns2 3600 IN A 198.51.100.2
www 300 IN A 192.0.2.10
ファイアウォールでは、セカンダリからの TCP 53 番を許可します。ゾーン転送は TCP で行われるため、UDP だけ開けていると問い合わせには答えるのに転送だけ失敗する、という状態になります。
セカンダリ側の Corefile
セカンダリは secondary プラグインに、取りに行く先のアドレスを transfer from で指定します。
# /etc/coredns/Corefile(セカンダリ 198.51.100.2)
example.com {
secondary {
transfer from 192.0.2.1
}
log
errors
}
transfer from には複数のアドレスを並べられ、最初の相手に失敗したときは次の相手が試されます。プライマリが2台ある、または別のセカンダリからも取れる構成なら、並べておくと取得の失敗に強くなります。
セカンダリが受け取ったゾーンをさらに別のサーバーに渡したい場合は、セカンダリ側にも transfer ブロックを書きます。
example.com {
secondary {
transfer from 192.0.2.1
}
transfer {
to 203.0.113.3
}
}
ゾーンの更新は、プライマリからの NOTIFY と、SOA の refresh の間隔ごとのシリアル確認によって行われます。NOTIFY の扱いは版によって差が出やすい部分なので、変更がすぐに伝わらない場合は「最悪でも refresh の間隔で追いつく」前提で SOA の値を決めておくと安心です。
動作を確認する
まず、セカンダリのサーバー上からプライマリへゾーン転送を試し、許可設定が通っているかを確かめます。
# セカンダリ(198.51.100.2)で実行
dig @192.0.2.1 example.com AXFR
ゾーンの全レコードが表示されれば、プライマリ側の設定は問題ありません。Transfer failed. と表示される場合は、transfer の to に書いたアドレス、TCP 53 番の通過、セカンダリが NAT の内側にいて別のアドレスから出ていないか、の順に確認します。
次に、2台が同じ版のゾーンで答えているかを SOA シリアルで比べます。
for s in 192.0.2.1 198.51.100.2; do
printf '%s ' "$s"; dig +short +norec @"$s" example.com SOA
done
シリアルがそろっていれば同期できています。プライマリでシリアルを上げたあと、しばらくしてセカンダリ側も上がるかを見れば、更新の流れまで確認できます。セカンダリの log / errors の出力(systemd で動かしているなら journalctl -u coredns)には、転送の成功・失敗が記録されるので、あわせて見ておきます。
最後に、ゾーン内の NS レコードと、ドメインの登録事業者に登録したネームサーバーの両方に2台が含まれているかを確認します。片方にしか書かれていないと、セカンダリに問い合わせが来ず、冗長化が働きません。
運用で気をつける点
受け取ったゾーンはディスクに保存されない
CoreDNS の secondary プラグインは、AXFR で受け取ったゾーンをメモリに持つだけで、ファイルには書き出しません。そのため次のことが起こります。
- セカンダリの CoreDNS を再起動すると、すべてのセカンダリゾーンを取り直します。
- そのときプライマリが止まっていると、セカンダリはゾーンを取得できるまでそのゾーンに答えられません。取得は一定間隔で再試行されます。
プライマリの障害中にセカンダリを再起動すると、両方が答えられない状態になりえます。対策としては、プライマリ障害中はセカンダリの再起動や設定変更を避ける運用ルールを決めておくこと、transfer from に複数の取得元を並べること、またはセカンダリでもゾーン転送を使わず、プライマリのゾーンファイルを rsync などで配って file プラグインで読む「2台ともプライマリ」の形にすることが考えられます。後者は通知や転送の仕組みに頼らないぶん、構成管理ツールで配布を自動化しておくと扱いやすくなります。
SOA の expire を短くしすぎない
SOA の expire は、プライマリと連絡が取れない状態が続いたときに、セカンダリがそのゾーンに答えるのをやめるまでの時間です。短くしすぎると、プライマリの数時間の停止でセカンダリまで答えなくなります。一般的には1〜2週間程度の値がよく使われます。
ゾーン転送の許可は最小限にする
ゾーン転送を誰にでも許すと、ゾーン内のホスト名がすべて外部から一覧できてしまいます。transfer の to はセカンダリのアドレスだけにし、ファイアウォールでも同じ制限をかけます。TSIG による署名付き転送を使いたい場合は、CoreDNS 側の対応状況(tsig プラグインと secondary / transfer の組み合わせ)を手元の版のドキュメントで確認してから設計してください。
監視を入れておく
prometheus プラグインを有効にすると、問い合わせ数やエラー数をメトリクスとして取得できます。セカンダリについては、少なくとも「2台の SOA シリアルが一定時間以上ずれていないか」を外部から定期的に確認しておくと、転送の失敗に早く気づけます。
まとめ
- プライマリは
fileでゾーンを読み、transfer { to セカンダリ }で転送を許可します。レコードを変えたら SOA シリアルを上げます。 - セカンダリは
secondary { transfer from プライマリ }で取り込みます。取得元は複数並べられます。 dig AXFRで転送の可否を、2台の SOA シリアル比較で同期を確認し、ゾーン内と登録事業者の NS に2台が含まれているかも見ます。- CoreDNS のセカンダリはゾーンをディスクに保存しないため、プライマリ障害中の再起動に注意し、必要ならファイル配布で2台ともプライマリにする構成も検討します。