Skip to main content
RunBook Academy

KubernetesCXIII · Kubernetes DNS Advanced TroubleshootingDNS advanced troubleshooting

Stub domains and upstream resolvers — overriding DNS for specific zones

Advanced⏱ ~16 minkubectl

What you'll learn

  • Configure stub domains for specific zones
  • Configure upstream resolvers per zone
  • Reason about corporate DNS integration
  • Apply the operational discipline of testing DNS changes

Prerequisites

Verified against Kubernetes 1.34.x · kubeadm 1.34.x · kubectl 1.34.x · etcd 3.6.x · CoreDNS 1.11.x · containerd 1.7.x / 2.x · 2026-08-16

Not yet marked complete on this device.

Stub domains and upstream resolvers allow Kubernetes Pods to query specific DNS servers for specific zones. This lesson walks the configuration, the use cases, and the discipline.

The stub domain concept

flowchart LR
    A[Pod] -->|query billing.corp| B[CoreDNS]
    B -->|stub .corp| C[Corporate DNS]
    C -->|response| B
    B -->|response| A
    A -->|query api.example.com| B
    B -->|forward .| D[Upstream DNS]
    D -->|response| B
    B -->|response| A

The stub domain concept:

  • Stub domains. Queries for specific zones are sent to specific upstream DNS servers.
  • Upstream resolvers. Queries for everything else go to the default upstream.

A Pod that queries billing.corp is sent to the corporate DNS; a Pod that queries api.example.com goes to the upstream DNS (e.g., cloud DNS).

Pod-level stub domains (legacy)

apiVersion: v1
kind: Pod
metadata:
  name: myapp
spec:
  dnsConfig:
    stubDomains:
      - corp: [10.0.0.10]  # queries for .corp go to 10.0.0.10
      - internal: [10.0.0.11]  # queries for .internal go to 10.0.0.11
    nameservers:
      - 10.96.0.10  # CoreDNS
  containers:
    - name: app
      image: myapp

The Pod-level stub domains:

  • .corp is sent to 10.0.0.10 (corporate DNS).
  • .internal is sent to 10.0.0.11 (internal DNS).
  • Everything else goes to CoreDNS (10.96.0.10).

This is the legacy approach; the recommended approach is to configure CoreDNS directly.

CoreDNS forward plugin (preferred)

.:53 {
    errors
    kubernetes cluster.local in-addr.arpa ip6.arpa {
        pods insecure
        fallthrough in-addr.arpa ip6.arpa
    }
    forward . /etc/resolv.conf
    forward .corp 10.0.0.10 {
        prefer_health
    }
    forward .internal 10.0.0.11 {
        prefer_health
    }
    cache 30
    prometheus :9153
}

The CoreDNS forward plugin:

  • forward .corp 10.0.0.10 — queries for .corp zones go to 10.0.0.10.
  • forward .internal 10.0.0.11 — queries for .internal go to 10.0.0.11.
  • forward . /etc/resolv.conf — queries for everything else go to the upstream DNS in /etc/resolv.conf.

The CoreDNS approach is preferred because it’s cluster-wide, not per-Pod.

The use cases

flowchart LR
    A[Use cases] --> B[Corporate DNS integration]
    A --> C[Internal services not in Kubernetes]
    A --> D[Conditional forwarding]
    A --> E[Compliance requirements]

The use cases:

  • Corporate DNS integration. Resolve .corp zones via the corporate DNS.
  • Internal services not in Kubernetes. Resolve .internal zones (legacy systems, databases).
  • Conditional forwarding. Different upstreams for different zones.
  • Compliance. Some regulations require DNS resolution to stay within certain boundaries.

The verification

# Inside a Pod
kubectl exec -it myapp-pod -- nslookup billing.corp
Server:    10.96.0.10
Address:   10.96.0.10#53

Name:   billing.corp
Address: 10.0.5.10

The query goes to CoreDNS, which forwards to the corporate DNS (10.0.0.10), which returns the address (10.0.5.10).

kubectl exec -it myapp-pod -- nslookup api.example.com
Server:    10.96.0.10
Address:   10.96.0.10#53

Name:   api.example.com
Address: 93.184.216.34

The query goes to CoreDNS, which forwards to the upstream DNS, which returns the public address.

The operational trade-offs

flowchart LR
    A[Pod stubDomains] --> B[+ Per-Pod control]
    A --> C[- Per-Pod config]
    A --> D[- Difficult to manage at scale]
    E[CoreDNS forward] --> F[+ Cluster-wide]
    F --> G[- Affects every Pod]

The trade-offs:

Pod stubDomains:

  • Pros: Per-Pod control.
  • Cons: Per-Pod config; difficult to manage at scale.

CoreDNS forward:

  • Pros: Cluster-wide; one place to configure.
  • Cons: Affects every Pod; a misconfiguration affects all.

Quiz

Knowledge check · 4 questions

  1. Q1. How is a stub domain configured in the preferred, modern approach?

  2. Q2. A CoreDNS Corefile change takes effect without restarting the CoreDNS Pods.

  3. Q3. Make an internal corporate zone resolvable from Pods without sending those names to the public upstream.

    Applications need to reach ldap.corp.example.com, which exists only in the corporate DNS at 10.0.0.10. From a Pod, `dig ldap.corp.example.com` returns NXDOMAIN with the answer coming from 10.96.0.10. The Corefile contains a single `forward . /etc/resolv.conf` stanza and no zone-specific forwarding. Cluster names and public names both resolve correctly.

  4. Q4. In a Corefile, what is the first argument to the forward plugin, and what happens if two forward stanzas declare the same zone inside one server block?

Passing score: 75%. Answers are checked in this browser.

The operational discipline

Stub domains and upstream resolvers in production rest on five non-negotiable elements:

  • Use CoreDNS forward, not Pod stubDomains. Cluster-wide, easier to manage.
  • Test the configuration in staging. A misconfiguration can leak internal DNS to public.
  • Document the zones. Which zones are stubbed; which upstreams serve them.
  • Monitor CoreDNS. Ensure the forward is working; alert on upstream failures.
  • Restrict access to the corporate DNS. Use NetworkPolicy to allow only CoreDNS to query the corporate DNS.

Stub domains are production DNS configuration. The discipline is to test, document, and monitor.