インフラ

CoreDNSとは?Kubernetesの名前解決の仕組みとCorefile設計を解説

CoreDNSは、Kubernetesクラスタの中でService名やPod名をIPアドレスへ変換する権威DNSサーバーです。2018年12月のKubernetes 1.13でkube-dnsに代わる既定の実装となり、EKSでもAKSでもGKEでも同じものが動いています。ところが、クラスタで起きるDNSの詰まりは、CoreDNS本体ではなくPodのresolv.confやconntrackが原因のことが少なくありません。プラグインチェーンの処理モデル、kubernetesプラグインの既定値、ndots:5が生む空振り、遅延の切り分け手順を実装目線でたどります。

まとめ:CoreDNSで最初に確認するCorefileと3つの設定

最初に開くのはkube-system名前空間のConfigMap「coredns」です。ここにCorefileが入っており、errors・health・ready・kubernetes・prometheus・forward・cache・loop・reload・loadbalance というプラグイン名が並びます。問い合わせはこの並びをチェーンとして通り抜けます。

手を入れる優先度が高いのは3つ。kubernetesプラグインのpodscacheforwardです。PodのIPから逆算した名前を引く必要がないなら、podsは既定のdisabledで据え置いてください。オンプレのDNSへ条件付き転送をかけたいときだけforwardにサーバーブロックを足します。

そして、実務で持ち込まれるDNS遅延の相談はndots:5が原因のケースが目立ちます。Corefileを書き換える前に、Pod側のdnsConfigとNodeLocal DNSCacheの導入可否を確認してください。

CoreDNSの位置づけ|Kubernetes 1.13で既定になったクラスタ内DNS

CoreDNSはGo言語で書かれた単一バイナリのDNSサーバーで、Miek Giebenが2016年3月に始めたプロジェクトです。CNCFは2019年1月24日に卒業(Graduated)を発表しました。Kubernetes専用ではなく、単体の権威DNSやフォワーダーとしても動きます。

kube-dnsを置き換えた背景とdnsmasq依存を解消した経緯

kube-dnsは、kube-dns・dnsmasq・sidecar という3つのコンテナを1つのPodに詰めた構成でした。キャッシュ層をC実装のdnsmasqに任せていたため、dnsmasq側の脆弱性がそのままクラスタDNSの弱点になります。

CoreDNSはこの分業をやめ、キャッシュもKubernetes連携も同一プロセスのプラグインとして持ちました。コンテナは1つ。Kubernetes 1.13のリリース告知(2018年12月3日)で既定のDNSとしてGAになりました。移行の動機は機能追加ではなく、依存を減らして障害点を削ることにあります。

プラグインチェーン方式の処理順とCorefileの基本的な構造

Corefileは「ゾーン名 { プラグイン群 }」というサーバーブロックの集まりです。1つのブロックに書いたプラグインは、上から順に実行されるわけではありません。CoreDNS本体が持つ既定の実行順に並び替えられ、その順でチェーンを構成します。

この仕様は落とし穴にもなりました。後述するCVE-2026-26017は、aclプラグインがrewriteより先に評価される既定順のせいでアクセス制御を回避できたというものです。記述順と実行順が一致しない点は、Corefileを書く前に頭へ入れておいてください。クラスタのネットワーク層全体の組み方はKubernetesネットワーク設計におけるService・Ingress・CNIの選定で扱っています。

Serviceとpodのレコード命名規則とSRVレコードの形式

通常のServiceはmy-svc.my-namespace.svc.cluster.localでA・AAAAレコードを持ち、ClusterIPを返します。ヘッドレスServiceは同じ名前で、選択されたPod群のIPをすべて返す点が違います。

名前付きポートにはSRVレコードが作られ、書式は_port-name._port-protocol.my-svc.my-namespace.svc.cluster.localです。ヘッドレスServiceならバックエンドPodごとに1件ずつ返ります。PodのAレコードはIPのドットをハイフンに置き換えた形式で、172.17.0.3のPodなら172-17-0-3.default.pod.cluster.localになります。

Podからの名前解決の流れ|ndots:5と検索ドメイン展開の実際

Pod内のアプリが名前を引くとき実際に何回パケットが飛ぶのかを把握すると、遅延の見積もりが変わります。

resolv.confのsearch行とndots:5が生む最大4回の空振り

kubeletはPodごとにresolv.confを書き込みます。nameserverにクラスタDNSのIP、search行に{namespace}.svc.cluster.local svc.cluster.local cluster.local、options行にndots:5という内容です。

ndots:5は「ドットが5個未満の名前は相対名とみなし、search行を順に付けて試す」という指示になります。api.example.comはドット2個なので、まずsearch行の3つを付けた名前で問い合わせ、いずれもNXDOMAINで返ってきてから、ようやく絶対名で引きます。1回の解決に4往復。IPv6のAAAAも同時に引く環境なら往復数は倍になります。

クラスタ内のService名を短く書く用途にはこの既定が効きます。外部APIを叩く回数が多いワークロードでは、そのまま無駄になります。

dnsPolicyの4種類とdnsConfigで検索ドメインを削る判断

Pod仕様のdnsPolicyには4つの値があり、何も指定しなければClusterFirstです。

挙動 使いどころ
Default ノードの設定を継承 クラスタ内名を引かないPod
ClusterFirst 既定。クラスタ優先 通常のワークロード
ClusterFirstWithHostNet hostNetwork時にも同様 ホストネットワークのPod
None すべてdnsConfigで指定 独自リゾルバを使う場合

外部通信が中心のPodは、dnsPolicyをClusterFirstに保ったままdnsConfigでoptionsのndotsを2程度へ下げると空振りが消えます。searchesを丸ごと削る方法もありますが、そのPodからクラスタ内Serviceを短縮名で呼べなくなるため、FQDN指定へ書き換える改修とセットでなければ採るべきではありません。

外部ドメインの問い合わせがforwardプラグインへ渡る条件

kubernetesプラグインが担当するのは、サーバーブロックに書かれたゾーン、標準構成ではcluster.localと逆引き用の2ゾーンだけです。ここに一致しない名前はチェーン後段のforwardプラグインへ渡ります。

マネージドKubernetesの既定では、forwardの転送先はノードのresolv.confを参照します。外部名の解決経路はCoreDNSではなくノード側のVPC DNS設定で決まる、と言い換えられます。オンプレの内部ドメインだけを別のDNSへ向けたいなら、その内部ドメイン名をゾーンとする独立したサーバーブロックを追加してください。既定ブロックにforwardを足すやり方は既存の転送設定と衝突します。

Corefile設計の実務|kubernetesプラグインの主要オプション

kubernetesプラグインとcacheプラグインの既定値を数値で押さえると、チューニングの余地がどこにあるかが見えます。

podsオプションのdisabled・insecure・verifiedの違い

PodのAレコードをどう扱うかはpodsの3値で決まります。

応答 コスト
disabled 既定。NXDOMAINを返す なし
insecure 検証せずAを返す なし。存在確認が甘い
verified Pod実在を確認して返す 全Podのwatchが必要

verifiedはクラスタ内の全Podを監視対象に加えるため、Pod数に比例してメモリとAPIサーバーへの負荷が増えます。後述するautopathを使う場合の前提条件ですが、そのautopath自体を採らないならdisabledのまま動かすのが無難です。

ttl既定5秒とcacheプラグインの9984件という容量上限

kubernetesプラグインのttlは既定5秒で、0秒から3600秒まで指定できます。Podの入れ替わりが激しいクラスタで長いTTLを返すと、消えたPodのIPをクライアントが掴み続けるためです。

その手前に置かれるcacheプラグインは256シャードに分かれ、各シャードが既定39件を保持します。合計で9984件。NOERROR応答は最大3600秒、否定応答は最大1800秒までキャッシュされ、最小は5秒です。prefetchは既定で直近1分のうちTTL残り10%を切った時点で先読みし、serve_staleは既定1時間、上流が落ちている間は期限切れの応答を返します。9984件という上限は、名前の種類が数万に達するクラスタでは足りません。

fallthroughとnamespacesで応答範囲を絞る設定例

fallthroughは、kubernetesプラグインがNXDOMAINを返す場面で応答を確定させず、次のプラグインへ処理を渡すオプションです。標準構成では逆引きゾーンに付いています。これがないと逆引きが打ち切られ、外部への転送が起きません。

namespacesを書くと、列挙した名前空間だけをDNSに露出できます。省略時は全名前空間が対象です。マルチテナントで名前空間をまたいだ探索を止めたいときの一手になります。ヘッドレスServiceの応答自体を止めるならnoendpointsを指定してください。起動時にKubernetes APIとの同期を待つstartup_timeoutは既定5秒です。

EKSアドオンがCorefileを上書きする挙動と回避の手順

Amazon EKSでは、CoreDNSはマネージドアドオンとして提供され、ConfigMapのdata.Corefileをアドオンが完全に管理します。kubectl editで直接書き換えた条件付き転送の設定は、次回のアドオン更新で消えます。

  1. 変更したいCorefile全文を用意する
  2. アドオンのconfigurationValuesにあるcorefileキーへ渡す
  3. 更新時の競合解決で上書きを選び、設定を反映させる

アドオン版はKubernetes版に紐づきます。2026年7月時点では、1.36と1.35がv1.14.3-eksbuild.3、1.34がv1.13.2-eksbuild.11、1.33がv1.12.4-eksbuild.18、1.32から1.30がv1.11.4-eksbuild.40という対応です。クラスタの提供形態ごとの違いはAmazon EKSのノード提供形態と料金モデルの解説にまとめています。

遅延と障害の切り分け|メトリクスとdigで詰まりを特定する手順

「DNSが遅い」という報告を受けたとき、CoreDNS側の数字とPod側の実測を分けて見ると原因が絞れます。

9153番ポートのcoredns_dns_requests_totalで見る負荷

prometheusプラグインは既定でlocalhost:9153にメトリクスを出します。まず見るのはcoredns_dns_requests_totalcoredns_dns_request_duration_seconds、そして応答コード別に集計されるcoredns_dns_responses_totalの3つです。

NXDOMAINの比率が異様に高ければ、search行の展開による空振りを疑ってください。CoreDNS本体は正常に応答しており、遅いのはクライアント側の往復回数という結論になります。coredns_panics_totalが増えているならプロセスのクラッシュ、coredns_build_infoは稼働中の版の確認に使えます。取り込み先とアラート閾値の設計はKubernetes監視におけるメトリクス・ログ・アラートの設計判断で整理しました。

digで応答元を確かめる手順とNXDOMAIN応答の読み分け

Pod内から実際に引いて、どこで詰まっているかを確かめます。

  1. Service名をFQDNで引き、応答時間とSERVERの行を確認する
  2. 同じ名前を短縮名で引き、往復回数の差を見る
  3. 外部ドメインを引き、forward先まで到達しているか確認する
  4. CoreDNSのPod IPを直接指定して引き、経路の問題と切り分ける

短縮名だけが遅くFQDNが速いならndots:5の空振りです。Pod IPを直接指定すると速くService経由で遅いなら、kube-proxyのDNATとconntrackを疑います。digの読み方やレコード種別の基本は名前解決の仕組みとdig・nslookupでの確認方法で解説しています。

NodeLocal DNSCacheが解くconntrack枯渇と30秒タイムアウト

NodeLocal DNSCacheはKubernetes v1.18でstableになった機能で、各ノードにキャッシュ用のCoreDNSをDaemonSetとして常駐させます。Podはリンクローカルアドレス(例として169.254.20.10)へ問い合わせ、ノードをまたぐ通信とiptablesのDNATを避けます。

効き目が大きいのはUDPまわりです。UDPのconntrackエントリは既定30秒残るため、DNSのようにセッションが短く量の多い通信ではテーブルが埋まりやすくなります。パケットが落ちると、リゾルバは3回の再送と10秒のタイムアウトで最大30秒待ちます。上流へTCPで接続するNodeLocal DNSCacheなら、エントリはクローズと同時に解放されるのが違いです。キャッシュ既定は10000件、満杯時のメモリはおよそ30MB。否定応答もキャッシュされるため、ndots:5の空振りがノード内で完結します。

CoreDNSに手を入れるべき場面と触らずに済ませる場面の線引き

CoreDNSは既定のまま動く時間が長いミドルウェアであり、設定を増やすほど更新時の衝突点が増えます。

autopathを採用しない理由とWindowsノードでの非対応

autopathは、search行の展開をサーバー側で肩代わりし、CNAMEを付けて1往復で返すプラグインです。ndots:5の空振りを消す仕組みとしては筋が通っています。それでもKubernetes環境では採用しない判断を推奨します。

理由は4つ。第一に、クライアントPodの名前空間を推定するためpods verifiedが必須で、全Podのwatchによるメモリ増を引き受けることになります。第二に、Pod IPが短時間で再利用されるとAPI watchの通知が間に合わず、誤った名前空間を返す可能性が公式ドキュメントに明記されています。第三に、Windowsノード上のPodには対応しません。第四に、最終的にNXDOMAINになる名前ではクライアント側の探索が結局走り、外部API向けの効果が消えます。

同じ課題には、NodeLocal DNSCacheの導入かdnsConfigの調整を採ってください。どちらもCorefileを触らずに済み、効果もcoredns_dns_requests_totalの減少として素直に出ます。

レプリカ数2のまま放置して詰まるクラスタ規模と増設の判断基準

EKSは、ノードが何台であろうとCoreDNSを2レプリカで起動します。20ノード規模までなら据え置きで問題は起きにくい一方、DNSクエリの多いマイクロサービスを数百Pod動かす構成では、2レプリカが先に飽和します。

増設に踏み切る条件は2つです。coredns_dns_request_duration_secondsの99パーセンタイルが恒常的に100ミリ秒を超えている場合と、CoreDNS PodのCPUがlimitに張り付いてスロットリングが出ている場合。どちらも出ていないのに予防的にレプリカを10へ増やすのは過剰で、APIサーバーへのwatch接続が増えるだけに終わります。増設より先にNodeLocal DNSCacheを入れたほうが、クエリ総量そのものが減ります。

可用性側の既定も見ておいてください。EKSアドオンはPodDisruptionBudgetをmaxUnavailable: 1で設定し、topologySpreadConstraintsをmaxSkew: 1でゾーンに分散させます。2レプリカのまま単一ゾーンへ寄せる構成は避けるべきです。

1.14.2で塞がれたACLバイパスと版を上げる優先度の判断

CoreDNS 1.14.2では脆弱性が2件修正されました。CVE-2026-26017は、aclプラグインがrewriteプラグインより先に評価される既定の実行順に起因するTOCTOU型のアクセス制御回避で、マルチテナントクラスタのDNS分離を崩します。CVE-2026-26018は、loopプラグインが検出用のクエリ名を予測可能な擬似乱数で生成していたため、細工したクエリでプロセスを落とせるDoS(CVSS 7.5)でした。

版上げの優先度はこう判断します。aclプラグインで名前空間間の問い合わせを制限しているクラスタは、1.14.2以降への更新を最優先で計画してください。単一テナントでも、外部から到達可能なDNSを公開していればCVE-2026-26018の影響を受けます。

直近では、1.14.5(2026年7月10日公開)でforwardプラグインがDoHに対応し、kubernetesプラグインのAXFR時のpanicも直りました。同日公開の1.14.6は、dd-trace-goをv2.8.2へ戻してARMとMIPSのビルドを修復したパッチ版です。EKSアドオンを使う環境は本家の版を直接追えないため、上の対応表を上限として計画してください。

クラスタ内DNSの設計を外部委託する際に確認する見積もり項目

クラスタ内DNSの設計を外部に任せる場合、設定作業そのものより既存環境との接続条件の洗い出しに工数がかかります。見積もりで確認しておく項目は次のとおりです。

  • オンプレ内部ドメインへの条件付き転送の有無とゾーン数
  • マネージドアドオンか自己管理かと、Corefileの更新手順
  • NodeLocal DNSCacheの導入可否と、IPVSモードかどうか
  • マルチテナント要件とaclプラグインによる分離の必要性
  • メトリクス収集先とDNS遅延のアラート閾値

とくに3番目は、kubeletの起動フラグ変更を伴うためノードの入れ替えが必要になる場合があり、見積もりの幅を左右します。既存のVPC DNSやオンプレDNSを含めた設計から相談したい場合は、AWS・Google Cloud・Azureのインフラ構築支援で対応しています。

よくある質問

CoreDNSの導入・運用で問い合わせの多い5点をまとめます。

CoreDNSとkube-dnsの違いは何ですか?

kube-dnsはkube-dns・dnsmasq・sidecarの3コンテナ構成で、キャッシュ処理をC実装のdnsmasqに委ねていました。CoreDNSはGoの単一バイナリで、キャッシュもKubernetes連携も同一プロセスのプラグインとして持ちます。Kubernetes 1.13で既定が入れ替わりました。なお、Service名は互換のため今もkube-dnsのままである点に注意してください。

CoreDNSのCorefileはどこにありますか?

kube-system名前空間のConfigMap「coredns」の中にあり、data配下のCorefileキーが実体です。Amazon EKSのマネージドアドオンを使っている場合、このConfigMapはアドオンが管理しており、直接編集した内容は次回のアドオン更新で上書きされます。恒久的な変更はアドオンのconfigurationValuesにあるcorefileキーで渡してください。

Podの名前解決が遅くなるのはなぜですか?

多くはCoreDNSの処理時間ではなく、UDPパケットの取りこぼしによる再送待ちです。Linuxのリゾルバは応答が返らないと再送し、3回の再送と10秒のタイムアウトで最大30秒待たされます。背景にはconntrackテーブルの競合があり、UDPエントリが既定30秒残ることも影響しました。NodeLocal DNSCacheで上流をTCP化してください。

ndots:5は下げてしまって問題ありませんか?

Pod単位でdnsConfigのoptionsに指定する形なら、影響範囲を限定できます。外部APIへの通信が中心のPodでndotsを2へ下げると空振りが減ります。ただし、そのPodからクラスタ内Serviceを短縮名で呼んでいると解決できなくなるため、事前に接続先をFQDNへ書き換えてください。クラスタ全体の既定値を変える方法は影響が読みにくく、避けたほうが安全です。

CoreDNSのレプリカ数はいくつにすべきですか?

EKSの既定は2レプリカで、ノード数に連動しません。増設の判断は数字で行ってください。応答時間の99パーセンタイルが恒常的に100ミリ秒を超える、またはCPUがlimitに張り付いている場合が目安です。どちらも出ていないなら据え置きで足ります。クエリ総量を減らしたいなら、レプリカ増設よりNodeLocal DNSCacheの導入が先です。

関連記事

資料請求

RELATED POSTS 関連記事