2026年6月9日
2026年6月9日
CoreDNS の監視方法|prometheus・health・ready プラグインと外形監視で応答の質を見張る
CoreDNS の監視は、prometheus プラグインで出すメトリクスを Prometheus で集め、health と ready で生死と準備状態を確認し、さらに外から実際に名前を引く外形監視を組み合わせるのが基本です。この記事では、何を監視すべきか、Corefile への監視用プラグインの入れ方、主なメトリクスと PromQL の例、アラートルールの例、Kubernetes での確認ポイント、ログの絞り方までを説明します。
メトリクスの名前やラベルは CoreDNS の版によって追加・改名されることがあります。この記事の名前は一般的な例として示すので、導入時には手元の /metrics の出力と、公式ドキュメントのプラグインごとの説明で確認してください。記載は執筆時点(2026年10月現在)の情報です。監視の設定変更でも Corefile を書き換えるため、変更前にバックアップを取り、検証環境で起動を確かめてから本番に反映します。
何を監視するか
DNS の障害は「プロセスは動いているのに名前が引けない」形で起きることが多いため、プロセスの生死だけを見ていると気付くのが遅れます。次の層に分けて考えると、抜けが減ります。
- 生死:プロセスが動いているか、メトリクスを取得できるか
- 準備状態:プラグインが答えられる状態か(Kubernetes ではAPIとの同期など)
- 応答の質:SERVFAIL や REFUSED の割合、応答時間
- 上流:
forwardの転送先が応答しているか - キャッシュとリソース:キャッシュの効き具合、CPU・メモリ、パニックの発生
- 外から見た結果:利用者と同じ経路で問い合わせて、期待どおりの答えが返るか
1〜5 は CoreDNS 自身が出す情報、6 は外部から確かめる情報です。両方を持っておくと、「CoreDNS は正常と言っているのに利用者は引けない」(ネットワークやファイアウォールの問題)にも気付けます。
Corefile に監視用のプラグインを入れる
# 各サーバーブロックで共通に使う監視設定
(observe) {
prometheus 10.0.0.10:9153
errors
log . {
class denial error
}
}
.:53 {
import observe
health 10.0.0.10:8080 {
lameduck 5s
}
ready 10.0.0.10:8181
forward . 192.0.2.53 198.51.100.53
cache 300
}
example.com:53 {
import observe
file /etc/coredns/zones/db.example.com
}
- prometheus:指定したアドレスの
/metricsでメトリクスを出します。メトリクスにはサーバーブロックを表すラベルが付くため、上の例のようにスニペット((observe)とimport)で各ブロックに入れておくと、ブロックごとの状況を比べられます。 - health:
/healthに HTTP で問い合わせると、プロセスが動いていれば 200 を返します。lameduckは、停止の指示を受けてから実際に止まるまでの猶予で、その間に処理中の問い合わせを捌けます。プロセス全体の状態を返すため、1つのブロックに書けば足ります。 - ready:
/readyは、書いたブロックのプラグインが答えられる状態になると 200 を返します。Kubernetes のkubernetesプラグインのように、起動直後は準備が整っていないプラグインがある場合に意味を持ちます。
アドレスを省略すると、すべてのアドレスで待ち受けます。メトリクスやヘルスチェックの口をインターネットに開ける必要はないため、監視サーバーから届く社内側のアドレスに限定し、ファイアウォールでも Prometheus のサーバーからだけ許可します。
反映したら、まず手元でメトリクスが出ているかと、どんな名前があるかを確認します。
curl -s http://10.0.0.10:8080/health
curl -s http://10.0.0.10:8181/ready
curl -s http://10.0.0.10:9153/metrics | grep '^coredns_' | cut -d'{' -f1 | sort -u
主なメトリクス
最後のコマンドの出力から、次のようなメトリクスを探します。名前が異なる場合は、意味の近いものに読み替えてください。
coredns_dns_requests_total:受けた問い合わせの数。サーバーブロック、ゾーン、型(A・AAAA など)、プロトコルのラベルが付きます。coredns_dns_responses_total:返した応答の数。rcodeラベルで NOERROR・NXDOMAIN・SERVFAIL・REFUSED を区別できます。coredns_dns_request_duration_seconds:応答にかかった時間のヒストグラム。パーセンタイルの計算に使います。coredns_cache_entries、coredns_cache_hits_total、coredns_cache_misses_total:キャッシュの件数と当たり外れ。版によっては、外れの数の代わりに総数を表すメトリクスが用意されています。- 転送先の状態:
forwardの転送時間やヘルスチェック失敗のメトリクスは、版によってcoredns_forward_で始まるものとcoredns_proxy_で始まるものがあります。 coredns_panics_total、coredns_reload_failed_total:プラグイン内部での異常、Corefile の再読み込みの失敗。process_resident_memory_bytes、process_cpu_seconds_total:プロセスのメモリと CPU。
Prometheus での収集とクエリの例
# prometheus.yml(抜粋)
scrape_configs:
- job_name: coredns
static_configs:
- targets: ['10.0.0.10:9153', '10.0.0.11:9153']
よく使うクエリの例です。
# 秒間の問い合わせ数(インスタンスごと)
sum by (instance) (rate(coredns_dns_requests_total[5m]))
# SERVFAIL の割合
sum by (instance) (rate(coredns_dns_responses_total{rcode="SERVFAIL"}[5m]))
/ sum by (instance) (rate(coredns_dns_responses_total[5m]))
# 応答時間の99パーセンタイル(秒)
histogram_quantile(0.99,
sum by (instance, le) (rate(coredns_dns_request_duration_seconds_bucket[5m])))
# キャッシュのヒット率
sum(rate(coredns_cache_hits_total[5m]))
/ (sum(rate(coredns_cache_hits_total[5m])) + sum(rate(coredns_cache_misses_total[5m])))
SERVFAIL の割合は、上流の障害や DNSSEC の不整合、forward 先への到達不能を早く知らせてくれます。NXDOMAIN は存在しない名前への問い合わせなので、多くても異常とは限りません。急に増えた場合は、設定ミスのあるクライアントやマルウェアの通信を疑う材料になります。
アラートルールの例
groups:
- name: coredns
rules:
- alert: CoreDNSDown
expr: up{job="coredns"} == 0
for: 2m
labels:
severity: critical
- alert: CoreDNSHighServfail
expr: |
sum by (instance) (rate(coredns_dns_responses_total{rcode="SERVFAIL"}[5m]))
/ sum by (instance) (rate(coredns_dns_responses_total[5m])) > 0.05
for: 10m
labels:
severity: warning
- alert: CoreDNSSlowResponses
expr: |
histogram_quantile(0.99,
sum by (instance, le) (rate(coredns_dns_request_duration_seconds_bucket[5m]))) > 0.5
for: 10m
labels:
severity: warning
しきい値(SERVFAIL 5%、99パーセンタイル 0.5秒)は例です。まず1〜2週間ほど値を記録して平常時の幅をつかみ、それを明らかに外れたときに鳴るよう調整します。最初から厳しくすると誤報が続き、アラートが無視されるようになります。転送先のヘルスチェック失敗のメトリクスが手元の版にあれば、increase(...[5m]) > 0 のような条件で上流の異常も通知できます。
Kubernetes での確認ポイント
Kubernetes のクラスタ DNS として CoreDNS を使っている場合、多くのディストリビューションでは、Corefile に prometheus :9153、health、ready が最初から入っており、Pod の liveness プローブが /health、readiness プローブが /ready を見ています。
kubectl -n kube-system get configmap coredns -o yaml
kubectl -n kube-system get svc kube-dns -o yaml | grep -A3 ports
kubectl -n kube-system top pod -l k8s-app=kube-dns
kube-prometheus-stack などの監視スタックを入れていれば、CoreDNS のメトリクスの収集設定やダッシュボードが同梱されていることがあります。マネージドの Kubernetes では、クラスタ DNS の実装や設定の変更可否が事業者によって異なるため、各社のドキュメントで確認します。Pod の再起動回数(kubectl get pod の RESTARTS)が増えていないか、メモリの上限に近づいていないかも合わせて見ます。
外から実際に名前を引く外形監視
CoreDNS のメトリクスは「CoreDNS が受け取った問い合わせ」しか数えられません。ファイアウォールの変更で問い合わせが届かなくなった場合、メトリクス上は静かになるだけです。そこで、利用者と同じ経路から定期的に名前を引く監視を足します。Prometheus を使っているなら、blackbox_exporter の DNS プローブが使えます。
# blackbox.yml(抜粋)
modules:
dns_www:
prober: dns
timeout: 5s
dns:
query_name: "www.example.com"
query_type: "A"
valid_rcodes:
- NOERROR
権威DNSとして CoreDNS を使っている場合は、各サーバーの SOA のシリアルが揃っているかも定期的に比べます。セカンダリへの転送が止まっていると、古い内容を返し続けていても応答は NOERROR のままなので、ほかの監視では気付けません。
ログは「異常だけ」に絞る
log プラグインで全件を記録すると、問い合わせの多い環境ではログの量が膨大になり、ディスクと処理の負担になります。上の例のように class denial error で、拒否・NXDOMAIN・エラーだけに絞り、調査のときだけ一時的に広げる運用が扱いやすいです。errors プラグインには、同じ種類のエラーを一定時間ごとにまとめて1行にする consolidate の指定もあり、上流のタイムアウトが大量に出る場面でログが埋まるのを防げます。
まとめ
- 生死・準備状態・応答の質・上流・リソース・外から見た結果の層に分けて監視します。
prometheusはスニペットで各ブロックに、healthとreadyは必要なブロックに入れ、待ち受けは社内側のアドレスに限定します。- SERVFAIL の割合と応答時間のパーセンタイルを中心にアラートを作り、しきい値は平常時の値を見てから決めます。
- メトリクスだけでは届かない問い合わせに気付けないため、blackbox_exporter などの外形監視を組み合わせます。