2026年7月6日

2026年7月6日

CoreDNSの設定と活用方法(Corefileの書き方とKubernetesでのカスタマイズ)

CoreDNSは、Corefileという設定ファイルに「どのドメインを、どのプラグインの順で処理するか」を書いて動かすDNSサーバーです。Kubernetesでは標準的なクラスターDNSとして使われており、単体でも社内向けの転送・キャッシュサーバーや小規模な権威サーバーとして動かせます。この記事では、Corefileの基本構造、単体での起動方法、Kubernetesでの安全なカスタマイズ、名前解決のトラブルを調べる手順を説明します。

CoreDNSの考え方:サーバーブロックとプラグイン

CoreDNSはひとつの実行ファイルに多数のプラグインを組み込んだ構成で、機能はすべてプラグインとして提供されます。Corefileは次のような「サーバーブロック」の並びです。

ゾーン:ポート {
    プラグイン 引数
    プラグイン 引数 {
        詳細設定
    }
}

問い合わせ名に最も長く一致するゾーンのブロックが選ばれ、その中のプラグインが処理を担当します。ゾーンに . を書くと「その他すべて」を意味します。

注意したいのは、プラグインが実行される順番はCorefileに書いた順ではなく、CoreDNSのビルド時に決められた順序だという点です。書く順番を入れ替えても挙動は変わりません。また、配布されているバイナリに含まれていないプラグインは使えないため、coredns -plugins で組み込み済みの一覧を確認できます。

よく使うプラグインは次のとおりです。

  • forward:上位のDNSサーバーへ問い合わせを転送する
  • cache:応答をキャッシュする(秒数で上限を指定)
  • file:BINDと同じ形式のゾーンファイルから権威応答を返す
  • hosts:hostsファイル形式で個別の名前を定義する
  • log / errors:問い合わせログとエラーログを出す
  • health / ready / prometheus:死活監視とメトリクスの提供
  • kubernetes:KubernetesのServiceやPodの名前を解決する

単体で動かす:転送・キャッシュサーバーの例

まずはローカルで試せる最小構成です。社内用の example.internal を自前のゾーンファイルで答え、それ以外は上位のリゾルバーへ転送します。

example.internal:1053 {
    file /etc/coredns/db.example.internal
    log
    errors
}

.:1053 {
    hosts {
        10.0.0.20 db.internal
        fallthrough
    }
    forward . 1.1.1.1 9.9.9.9
    cache 300
    log
    errors
}

hosts の fallthrough は、ここに書いていない名前を次のプラグイン(この例では forward)に回すための指定です。これを忘れると、hostsに無い名前がすべて「見つからない」になります。

ゾーンファイルはBINDと同じ書式です。

$TTL 300
@    IN SOA ns.example.internal. admin.example.internal. 2026101801 3600 900 604800 300
@    IN NS  ns.example.internal.
ns   IN A   10.0.0.53
app  IN A   10.0.0.10

実行ファイルはCoreDNSのGitHubリリースからダウンロードするか、公式のコンテナイメージを使います。

# バイナリで起動(待ち受けポートは Corefile の指定に従う)
./coredns -conf Corefile

# コンテナで起動する例(Corefile とゾーンファイルをカレントに置いた場合)
docker run -d --name coredns \
  -v "$(pwd)":/etc/coredns \
  -p 1053:1053/udp -p 1053:1053/tcp \
  coredns/coredns -conf /etc/coredns/Corefile

# 動作確認
dig @127.0.0.1 -p 1053 app.example.internal
dig @127.0.0.1 -p 1053 www.example.com

本番で53番ポートを使う場合、Ubuntu などでは systemd-resolved がループバック上の53番を使っており、ポートの競合で起動できないことがあります。bind プラグインで待ち受けるアドレスを限定するか、resolved の設定を見直してください。また、外部に公開すると誰でも使える再帰サーバー(オープンリゾルバー)になるため、ファイアウォールや acl プラグインで問い合わせ元を限定します。

Kubernetesでの既定の構成を読む

Kubernetesでは、CoreDNSの設定は kube-system 名前空間の ConfigMap(kubeadm で構築した場合の名前は coredns)に入っています。互換性のため、Service名は kube-dns のままになっていることが一般的です。

kubectl -n kube-system get configmap coredns -o yaml

kubeadm の既定に近い Corefile は次のような内容です。

.:53 {
    errors
    health {
       lameduck 5s
    }
    ready
    kubernetes cluster.local in-addr.arpa ip6.arpa {
       pods insecure
       fallthrough in-addr.arpa ip6.arpa
       ttl 30
    }
    prometheus :9153
    forward . /etc/resolv.conf {
       max_concurrent 1000
    }
    cache 30
    loop
    reload
    loadbalance
}

kubernetes プラグインが mysql.default.svc.cluster.local のようなService名を解決し、それ以外は forward でノードの resolv.conf に書かれた上位DNSへ送ります。reload はCorefileの変更を検知して再読み込みする設定、loop は転送のループを検出したときに停止して知らせる設定です。

Kubernetesでカスタマイズする

変更前には kubectl get configmap coredns -o yaml > coredns-backup.yaml で現在の設定を保存し、検証用クラスターで試してから本番に反映してください。DNSが止まると、クラスター内のほぼすべての通信に影響します。

特定ドメインだけ社内DNSへ転送する

社内のドメインを社内DNSで解決したい場合は、サーバーブロックを追加します。

corp.example.com:53 {
    errors
    cache 30
    forward . 10.10.0.53
}

既存の .:53 ブロックの外側(同じ階層)に追記し、kubectl -n kube-system edit configmap coredns で保存します。ConfigMapの更新がPodに届くまで少し時間がかかるため、すぐに反映されなくても慌てずに待ち、ログで再読み込みを確認します。

マネージドKubernetesの注意点

EKS・GKE・AKSなどのマネージドサービスでは、DNSの構成や推奨されるカスタマイズ方法が独自に決められています。たとえばAKSでは coredns を直接編集せず、coredns-custom という別のConfigMapで追加設定を行う方式が案内されています。GKEでは既定のクラスターDNSがCoreDNSではない構成もあります。EKSのアドオンで管理している場合は、アドオンの更新で手動の変更が上書きされることがあります。いずれも仕様が変わることがあるため、利用中のサービスの公式ドキュメントを確認してください(2026年10月現在)。

名前解決のトラブルを調べる

CoreDNS自体の状態を確認する

kubectl -n kube-system get pods -l k8s-app=kube-dns
kubectl -n kube-system logs -l k8s-app=kube-dns --tail=50

Podが再起動を繰り返していて、ログに loop の検出が出ている場合は、ノードの /etc/resolv.conf が 127.0.0.53 などのローカルアドレスを指していて、CoreDNSが自分自身に転送している状態が考えられます。kubelet が参照する resolv.conf を、systemd-resolved が管理する上位サーバーの一覧(多くの環境で /run/systemd/resolve/resolv.conf)に向けるのが一般的な対処です。

Podの中から確かめる

アプリのPodから問い合わせて、Service名と外部ドメインの両方が引けるかを確認します。nslookup や dig が入ったデバッグ用のイメージを一時的に起動すると便利です。次の例はKubernetesの公式ドキュメントのDNSデバッグ手順で使われているイメージです(タグは最新のドキュメントで確認してください)。

kubectl run dnstest --rm -it --restart=Never \
  --image=registry.k8s.io/e2e-test-images/jessie-dnsutils:1.3 -- \
  nslookup kubernetes.default.svc.cluster.local

Service名は引けるのに外部ドメインだけ失敗するなら forward 先、両方失敗するならCoreDNS自体かネットワークポリシーを疑います。調査中だけ Corefile に log を追加すると、どんな問い合わせが届いているかが見えます。問い合わせ量の多いクラスターではログが大量に出るため、確認が済んだら外してください。

外部名の問い合わせが多すぎる場合

Podの resolv.conf には通常 ndots:5 が設定されており、ドットが少ない名前は検索ドメインを付けた問い合わせが先に何回も行われます。外部APIを頻繁に呼ぶアプリ(WordPressから外部サービスへの通信など)でDNSの負荷や遅延が気になる場合は、末尾にドットを付けた完全修飾名を使うか、Podの dnsConfig で ndots を調整する方法があります。

まとめ

  • CoreDNSはサーバーブロックとプラグインで構成され、プラグインの実行順はビルド時に決まっています。
  • 単体なら forward・cache・file・hosts の組み合わせで、転送・キャッシュや小規模な権威サーバーとして動かせます。公開する場合は問い合わせ元を限定します。
  • Kubernetesでは kube-system の ConfigMap で設定し、変更前にバックアップを取り、検証環境で試します。マネージドサービスは各社の推奨方法に従います。
  • トラブル時はCoreDNSのPodとログ、Pod内からの名前解決、loopやndotsの影響を順に確認します。

お気軽にご相談ください

お見積りへ お問い合わせへ
▲