Skip to main content
Version: main 🚧

Why does CoreDNS become a DNS bottleneck?

CoreDNS handles DNS resolution for every pod in the tenant cluster. By default, it runs a single replica (controlPlane.coredns.deployment.replicas: 1) as a separate Deployment, sized for small and medium tenant clusters. See CoreDNS configuration for the full deployment and configuration reference, and Scale CoreDNS for large node counts for how to raise the ceiling described below.

Why total query volume matters more than node count​

A single CoreDNS replica is CPU-bound at vCluster's default 1 CPU limit. What matters is total query volume, not node count on its own. Pod count, lookups per pod, and search-domain expansion all factor in. ndots:5 search-domain expansion means a single unqualified lookup can generate several sequential queries before it resolves, so it's a significant multiplier on the raw pod-and-lookup count.

Measure your own fleet's query rate rather than reasoning from node count alone. See What to watch for the exact queries.

Why GPU node pools are a common trigger, but not for the obvious reason​

GPU node pools are a common trigger for this, but not for the reason pod density suggests. GPU nodes typically run fewer pods per node than general-purpose nodes, so steady-state DNS load per node is often light. The pressure point is the job-launch burst. A batch job scheduling hundreds of pods at once produces a synchronized spike in DNS lookups. Every pod resolves the same handful of names within seconds of each other, so query rate spikes around scheduling events, not just steady-state averages.

What an overloaded CoreDNS looks like​

Tenant workloads see an overloaded CoreDNS as DNS resolution timeouts, intermittent SERVFAIL responses, and slower pod startup when init containers or sidecars wait on DNS lookups. Sustained NXDOMAIN for a Service the tenant API server can still resolve is a real signal. Ordinary ndots:5 expansion doesn't explain a resolution failure for a name that exists. Treat it alongside SERVFAIL and latency rather than as a standalone capacity trigger, since ndots:5 search-path expansion also produces NXDOMAIN as a normal byproduct of everyday lookups, whether or not CoreDNS is under load.

Already seeing these symptoms right now? See Resolve CoreDNS DNS timeouts and SERVFAIL errors to diagnose and fix an active incident.

Why embedded CoreDNS can't scale the same way​

With controlPlane.coredns.embedded: true (a Pro feature), CoreDNS components run as child processes of the syncer, in the same pod, instead of as their own Deployment. There's no coredns Deployment in kube-system for controlPlane.coredns.deployment.replicas or a Deployment-scaling autoscaler to act on, so both are silently ignored rather than rejected with an error.

If you're running embedded CoreDNS and hitting a DNS capacity wall, two options add capacity instead of a replica count. Raising controlPlane.statefulSet.resources resizes the whole control-plane pod, not CoreDNS specifically, covered in Choose a resource profile. Raising controlPlane.statefulSet.highAvailability.replicas also adds DNS capacity. More syncer replicas means more active CoreDNS instances, since the kube-dns Service points at the syncer pods (TCP/UDP 1053) rather than at CoreDNS Deployment pods when embedded is on.

You can switch a live tenant cluster between embedded and separate CoreDNS without redeploying it. You may see a brief DNS gap during the switch.