DNS Policy Configuration Kubernetes
Configure Kubernetes DNS policies: Default, ClusterFirst, ClusterFirstWithHostNet, and None. Custom resolv.conf, ndots tuning, and DNS performance.
π‘ Quick Answer: Customize pod DNS with
spec.dnsPolicyandspec.dnsConfig. UseClusterFirst(default),ClusterFirstWithHostNet,Default(nodeβs DNS), orNone(fully custom). Add nameservers and searches viadnsConfig.nameserversanddnsConfig.searches.Key config: For corporate domains, edit the CoreDNS ConfigMap with
forward corp.example.com 10.0.0.53for stub domains.Gotcha:
ndots:5default causes up to 5 DNS lookups before trying the absolute name β reduce tondots:2for external-heavy workloads.
The Problem
Kubernetes uses CoreDNS for service discovery and DNS resolution, but the defaults donβt fit every environment β corporate domains need stub-domain forwarding, external-heavy workloads suffer from ndots overhead, and some pods need to bypass cluster DNS entirely.
The Solution
CoreDNS ConfigMap
# kubectl get configmap coredns -n kube-system -o yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: coredns
namespace: kube-system
data:
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
}Add Custom Upstream DNS
apiVersion: v1
kind: ConfigMap
metadata:
name: coredns
namespace: kube-system
data:
Corefile: |
.:53 {
errors
health
ready
kubernetes cluster.local in-addr.arpa ip6.arpa {
pods insecure
fallthrough in-addr.arpa ip6.arpa
}
prometheus :9153
# Custom upstream DNS servers
forward . 8.8.8.8 8.8.4.4 {
max_concurrent 1000
policy sequential
}
cache 30
loop
reload
loadbalance
}Stub Domains for Corporate DNS
apiVersion: v1
kind: ConfigMap
metadata:
name: coredns
namespace: kube-system
data:
Corefile: |
# Corporate domain forwarding
corp.example.com:53 {
errors
cache 30
forward . 10.0.0.10 10.0.0.11 {
policy round_robin
}
}
# Internal services domain
internal.mycompany.com:53 {
errors
cache 30
forward . 192.168.1.53
}
# Default zone
.:53 {
errors
health
ready
kubernetes cluster.local in-addr.arpa ip6.arpa {
pods insecure
fallthrough in-addr.arpa ip6.arpa
}
prometheus :9153
forward . /etc/resolv.conf
cache 30
loop
reload
loadbalance
}Custom DNS Records (Static Entries)
apiVersion: v1
kind: ConfigMap
metadata:
name: coredns-custom
namespace: kube-system
data:
custom.server: |
hosts {
10.0.0.100 legacy-db.example.com
10.0.0.101 legacy-api.example.com
10.0.0.102 printer.office.local
fallthrough
}# Reference in CoreDNS config
apiVersion: v1
kind: ConfigMap
metadata:
name: coredns
namespace: kube-system
data:
Corefile: |
.:53 {
errors
health
ready
import /etc/coredns/custom/*.server
kubernetes cluster.local in-addr.arpa ip6.arpa {
pods insecure
fallthrough in-addr.arpa ip6.arpa
}
prometheus :9153
forward . /etc/resolv.conf
cache 30
loop
reload
loadbalance
}Pod DNS Policy Options
# Inherits node DNS
apiVersion: v1
kind: Pod
metadata:
name: dns-default
spec:
dnsPolicy: Default
containers:
- name: app
image: nginx
---
# Kubernetes DNS (default for pods)
apiVersion: v1
kind: Pod
metadata:
name: dns-clusterfirst
spec:
dnsPolicy: ClusterFirst
containers:
- name: app
image: nginx
---
# No auto-config, fully custom via dnsConfig
apiVersion: v1
kind: Pod
metadata:
name: dns-none
spec:
dnsPolicy: None
dnsConfig:
nameservers:
- 8.8.8.8
- 8.8.4.4
searches:
- default.svc.cluster.local
- svc.cluster.local
- cluster.local
options:
- name: ndots
value: "2"
- name: edns0
containers:
- name: app
image: nginxCustom DNS Config for Pods
apiVersion: v1
kind: Pod
metadata:
name: custom-dns-pod
spec:
dnsPolicy: ClusterFirst
dnsConfig:
nameservers:
- 10.0.0.53 # Additional nameserver
searches:
- mycompany.local
- prod.mycompany.local
options:
- name: ndots
value: "5" # Higher ndots for short names
- name: timeout
value: "3" # Query timeout seconds
- name: attempts
value: "2" # Retry attempts
- name: single-request-reopen
containers:
- name: app
image: nginxDeployment with DNS Config
apiVersion: apps/v1
kind: Deployment
metadata:
name: app-with-dns
spec:
replicas: 3
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
dnsPolicy: ClusterFirst
dnsConfig:
options:
- name: ndots
value: "2"
- name: single-request-reopen
containers:
- name: app
image: myapp:v1Headless Service DNS
apiVersion: v1
kind: Service
metadata:
name: database
spec:
clusterIP: None # Headless
selector:
app: postgres
ports:
- port: 5432
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: postgres
spec:
serviceName: database
replicas: 3
selector:
matchLabels:
app: postgres
template:
metadata:
labels:
app: postgres
spec:
containers:
- name: postgres
image: postgres:15DNS records created:
database.default.svc.cluster.localβ All pod IPspostgres-0.database.default.svc.cluster.localβ Pod 0 IPpostgres-1.database.default.svc.cluster.localβ Pod 1 IPpostgres-2.database.default.svc.cluster.localβ Pod 2 IP
Optimize DNS Performance
apiVersion: v1
kind: ConfigMap
metadata:
name: coredns
namespace: kube-system
data:
Corefile: |
.:53 {
errors
health
ready
kubernetes cluster.local in-addr.arpa ip6.arpa {
pods insecure
fallthrough in-addr.arpa ip6.arpa
ttl 60 # Increased TTL
}
prometheus :9153
forward . 8.8.8.8 8.8.4.4 {
max_concurrent 2000
policy random
health_check 5s
}
cache {
success 9984 300 # Cache up to 9984 entries for 5 min
denial 9984 60 # Cache negative responses for 1 min
}
loop
reload 10s
loadbalance round_robin
}Debug DNS Issues
kubectl run dns-test --image=busybox:1.28 --rm -it --restart=Never -- sh
nslookup kubernetes.default
nslookup myservice.mynamespace.svc.cluster.local
cat /etc/resolv.conf
nslookup google.com
nslookup kubernetes.default 10.96.0.10kubectl get pods -n kube-system -l k8s-app=kube-dns
kubectl logs -n kube-system -l k8s-app=kube-dns
kubectl port-forward -n kube-system svc/kube-dns 9153:9153
curl http://localhost:9153/metricsCommon Issues
Configuration not applying
Verify the ConfigMap edit was actually picked up β CoreDNS watches its ConfigMap and reloads via the reload plugin, but changes can take up to 30s. Check kubectl logs -n kube-system -l k8s-app=kube-dns for reload confirmation.
Stub domain forwarding not working
Zone blocks in the Corefile are matched by longest suffix; make sure the corporate zone block appears before (or independent of) the default .:53 block, and that the forwarded nameserver is actually reachable from CoreDNS pods.
Best Practices
- Lower
ndotsfor external-heavy workloads β defaultndots:5triggers up to 4 wasted search-domain lookups per external name - Use stub domains, not full ConfigMap forwarding, for corporate DNS β keeps cluster-internal resolution isolated
- Increase cache TTL for stable environments to cut CoreDNS query volume
- Monitor CoreDNS metrics (
:9153/metrics) forcoredns_dns_response_rcode_count_totaland forward latency - Use
dnsPolicy: Nonesparingly β only when a pod genuinely needs to bypass cluster DNS
Key Takeaways
dnsPolicycontrols the DNS behavior tier;dnsConfigfine-tunes nameservers, searches, and options- Stub domains via CoreDNS Corefile zone blocks route specific domains to specific upstream resolvers
ndotstuning is the single biggest DNS-latency lever for external-heavy workloads- Headless Services get per-pod DNS records automatically via StatefulSet ordinals
- CoreDNS metrics on port 9153 are the primary tool for diagnosing DNS performance issues
π Go Further with Kubernetes Recipes
Love this recipe? Thereβs so much more! This is just one of 100+ hands-on recipes in our comprehensive Kubernetes Recipes book.
Inside the book, youβll master:
- β Production-ready deployment strategies
- β Advanced networking and security patterns
- β Observability, monitoring, and troubleshooting
- β Real-world best practices from industry experts
βThe practical, recipe-based approach made complex Kubernetes concepts finally click for me.β
π Get Your Copy Now β Start building production-grade Kubernetes skills today!

Recommended
Kubernetes Recipes β The Complete Book100+ production-ready patterns with detailed explanations, best practices, and copy-paste YAML. Everything in one place.
Get the Book βLearn by Doing
CopyPasteLearn β Hands-on Cloud & DevOps CoursesMaster Kubernetes, Ansible, Terraform, and MLOps with interactive, copy-paste-run lessons. Start free.
Browse Courses βπ Deepen Your Skills β Hands-on Courses
Courses by CopyPasteLearn.com β Learn IT by Doing
