テック技報最新号へ →
インフラ

Kubernetes の名前解決を速くする: ndots:5 の総当たりを避ける接続先の書き方と CoreDNS の設定

@yosshi_ · 2026-11-10

Pod の DNS クエリは、接続先の書き方ひとつで 1 回にも 4 回にもなる。末尾ドット・<svc>.<ns> 形式・dnsPolicy: Default で無駄なクエリを減らす。

どんなときに使うか

  • 性能要件が厳しいアプリで、接続のたびの名前解決の遅れや CoreDNS の負荷が気になるとき
  • CoreDNS のログに xxx.default.svc.cluster.local のような NXDOMAIN が大量に並んでいるとき
  • ノードの conntrack テーブルが逼迫している(DNS は UDP なので 1 クエリごとにエントリができる)とき

仕組み

kubelet は dnsPolicy: ClusterFirst(既定)の Pod に次の /etc/resolv.conf を入れる。nameserver はクラスタ DNS(kube-dns Service の ClusterIP)だけに置き換えられる。

search <ns>.svc.cluster.local svc.cluster.local cluster.local
nameserver 10.96.0.10
options ndots:5

ドットが 5 個未満の名前は search の各ドメインを順に付けて試し、最後にそのままの名前を試す。そのため nginx.default.svc.cluster.local(ドット 4 個)と完全な名前を書いても、末尾ドットがなければ NXDOMAIN を 3 回もらってから 4 回目で解決する。外部ドメインの kubernetes.io も同じく 4 回になる。

接続先の書き方とクエリ回数(kind + CoreDNS の log で実測された値)

書き方クエリ回数
nginx(同じ Namespace)1 回
nginx.default(別 Namespace)2 回
nginx.default.svc.cluster.local(末尾ドットなし)4 回
nginx.default.svc.cluster.local.(末尾ドットあり)1 回
kubernetes.io4 回
kubernetes.io.1 回

やり方

  1. 同じ Namespace の Service は名前だけ(nginx)で書く。
  2. 別 Namespace の Service は <svc>.<ns> か、末尾ドット付きの完全な名前で書く。末尾ドットなしの FQDN は一番損。
  3. 外部ドメインは設定で書けるなら api.example.com. のように末尾ドットを付ける。
  4. 外部ドメインしか引かない Pod は dnsPolicy: Default にしてノードの resolv.conf を直接使う。ただしクラスタ内の Service 名は引けなくなり、CoreDNS の共有キャッシュも通らなくなるので、アプリ側で DNS 結果をキャッシュしていないと上流 DNS への問い合わせはむしろ増える。
yaml
spec:
  dnsPolicy: Default
  1. 確認は nicolaka/netshoot などの Pod から dig +search +noall +answer +comments A <名前> を打ち、Corefile に一時的に log を足して CoreDNS 側のクエリ行を数える(常時有効は性能に響く)。

CoreDNS 側の設定メモ

  • Corefile に書く順番と実行順は別物。実行順はビルド時の plugin.cfg で決まり、cache と autopath は kubernetes より先に動く。
  • cache に disable success cluster.local / disable denial cluster.local を入れると、クラスタ内の応答をキャッシュせず、Service や EndpointSlice の変更がすぐ反映される。
  • 上流 DNS の障害対策に prefetch 5 60s 10% と serve_stale 1h verify。verify の方が古い IP を返し続けるリスクが低い。古い CoreDNS には SERVFAIL が肯定キャッシュを上書きする不具合(coredns#8003)があったので版を確認する。
  • autopath @kubernetes は search の総当たりをサーバー側で肩代わりできるが、pods verified(全 Pod の watch でメモリ・CPU が増える)が必須で、IP 再利用時に Namespace を取り違えることがある。まずは上のクライアント側の書き方で減らし、それでも残るときに検討する。
  • health { lameduck 10s } で終了時の猶予を延ばし、EndpointSlice の反映待ちの間も応答を続けさせる。
  • 公式の forward . /etc/resolv.conf { max_concurrent 1000 } は上限超過で即 REFUSED を返す。外すかどうかは conntrack 逼迫とのトレードオフ。

注意

  • マネージド k8s では Corefile を触れないことが多い。クライアント側の書き方と dnsPolicy は使える。
  • 数字は記事の kind 検証(Kubernetes v1.37 / CoreDNS v1.14.6)の結果。

出典

  • @yosshi_ · 2026-11-09 (Qiita「CoreDNS の Kubernetes プラグインで、Service のドメイン名がクラスタ内で名前解決できるまで」の第 4 章が要点)

関連

X の元の投稿を開く