DNS & CoreDNS
Kubernetes uses DNS for service discovery, allowing pods to find Services by name instead of IP address. CoreDNS is the default DNS server in Kubernetes, replacing the earlier kube-dns. Understanding how DNS works in Kubernetes is essential for service discovery and troubleshooting connectivity issues.
What is CoreDNS?
CoreDNS is a flexible, extensible DNS server written in Go. In Kubernetes, CoreDNS:
- Resolves Service names to Service IP addresses
- Provides pod DNS configuration automatically
- Supports custom DNS records via plugins
- Replaces kube-dns as the default DNS solution
How DNS Works in Kubernetes
Every pod is automatically configured to use CoreDNS:
- Pod created - Gets DNS configuration
- DNS server - Points to CoreDNS service IP
- DNS search domains - Configured for namespace and cluster
- Service discovery - Pods can resolve Service names
DNS Configuration in Pods
Pods automatically get DNS configuration:
# Pod DNS configuration (automatically injected)
nameservers:
- 10.96.0.10 # CoreDNS Service IP
search:
- default.svc.cluster.local
- svc.cluster.local
- cluster.local
options:
- ndots:5
Key settings:
nameservers- CoreDNS Service IPsearch- DNS search domains (namespace, svc, cluster)ndots- Number of dots before absolute query
Service DNS Names
Services are discoverable via DNS with different name formats:
Short Name (Same Namespace)
# From pod in same namespace
my-service
Resolves to: my-service.default.svc.cluster.local
Fully Qualified Domain Name (FQDN)
# From any namespace
my-service.default.svc.cluster.local
Components:
my-service- Service namedefault- Namespacesvc- Service typecluster.local- Cluster domain
Cross-Namespace
# From different namespace
my-service.production.svc.cluster.local
DNS Record Types
CoreDNS creates different DNS record types:
A Records
Service IP address:
$ nslookup my-service
Name: my-service.default.svc.cluster.local
Address: 10.96.0.1
SRV Records
Service port information:
$ dig SRV my-service.default.svc.cluster.local
# Returns:
my-service.default.svc.cluster.local. 30 IN SRV 10 50 80 my-service.default.svc.cluster.local.
SRV record fields:
- Priority (10)
- Weight (50)
- Port (80)
- Target (Service FQDN)
CoreDNS Architecture
CoreDNS runs as a Deployment in the kube-system namespace:
apiVersion: apps/v1
kind: Deployment
metadata:
name: coredns
namespace: kube-system
spec:
replicas: 2
template:
spec:
containers:
- name: coredns
image: coredns/coredns:1.10.1
args:
- -conf
- /etc/coredns/Corefile
CoreDNS Configuration
CoreDNS is configured via a ConfigMap:
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
cache 30
loop
reload
loadbalance
}
Key plugins:
kubernetes- Kubernetes service discoveryforward- Forward queries to upstream DNScache- DNS response cachingprometheus- Metrics endpoint
DNS Resolution Flow
When a pod makes a DNS query:
Headless Service DNS
Headless Services (clusterIP: None) return pod IPs:
# Regular Service
$ nslookup web-service
Name: web-service.default.svc.cluster.local
Address: 10.96.0.1 # Single Service IP
# Headless Service
$ nslookup web-headless
Name: web-headless.default.svc.cluster.local
Address: 10.244.1.5 # Pod 1 IP
Address: 10.244.1.6 # Pod 2 IP
Address: 10.244.2.3 # Pod 3 IP
With StatefulSets, pod-specific DNS names are available:
# Pod-specific DNS (StatefulSet)
web-0.web-headless.default.svc.cluster.local → 10.244.1.5
web-1.web-headless.default.svc.cluster.local → 10.244.1.6
web-2.web-headless.default.svc.cluster.local → 10.244.2.3
Custom DNS Entries
You can add custom DNS entries via CoreDNS configuration:
apiVersion: v1
kind: ConfigMap
metadata:
name: coredns
namespace: kube-system
data:
Corefile: |
.:53 {
kubernetes cluster.local in-addr.arpa ip6.arpa {
pods insecure
fallthrough in-addr.arpa ip6.arpa
}
hosts {
192.168.1.100 custom.example.com
fallthrough
}
forward . /etc/resolv.conf
}
DNS Troubleshooting
DNS Not Resolving
- Check CoreDNS pods:
kubectl get pods -n kube-system -l k8s-app=kube-dns - Test DNS from pod:
kubectl run -it --rm debug --image=busybox --restart=Never -- nslookup kubernetes.default - Check CoreDNS logs:
kubectl logs -n kube-system -l k8s-app=kube-dns - Verify Service exists:
kubectl get service -n kube-system kube-dns - Check DNS config:
kubectl get configmap coredns -n kube-system -o yaml
Service Not Resolving
- Verify Service exists:
kubectl get service <service-name> - Check namespace: Ensure Service is in expected namespace
- Test with FQDN: Try full FQDN instead of short name
- Check Endpoints:
kubectl get endpoints <service-name> - Review CoreDNS logs: Look for resolution errors
DNS Slow
- Check CoreDNS performance: Review CoreDNS metrics
- Increase replicas: Scale CoreDNS Deployment
- Check cache settings: Verify cache configuration
- Review network policies: Ensure DNS traffic is allowed
- Check node resources: Ensure nodes have adequate resources
Best Practices
- Use Service names - Always use Service DNS names, not IPs
- Use FQDN for cross-namespace - Use full FQDN when accessing Services in other namespaces
- Monitor CoreDNS - Monitor CoreDNS health and performance
- Scale CoreDNS - Ensure adequate CoreDNS replicas for cluster size
- Allow DNS in Network Policies - Always allow DNS egress in Network Policies
- Test DNS resolution - Regularly test DNS resolution
- Document custom DNS - Document any custom DNS entries
- Keep CoreDNS updated - Update CoreDNS regularly
- Monitor DNS metrics - Track DNS query performance
- Use short names when possible - Use short names within same namespace
See Also
- Pod Connectivity Overview - How pods connect
- Services - Services that DNS resolves
- Headless Services - Headless Service DNS behavior
- StatefulSets - StatefulSets with pod-specific DNS