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
graph TB A[Pod] --> B[DNS Query: my-service] B --> C[CoreDNS] C --> D[Service IP: 10.96.0.1] D --> E[Pod Connects to Service] style A fill:#e1f5ff style C fill:#fff4e1 style D fill:#e8f5e9

How DNS Works in Kubernetes

Every pod is automatically configured to use CoreDNS:

  1. Pod created - Gets DNS configuration
  2. DNS server - Points to CoreDNS service IP
  3. DNS search domains - Configured for namespace and cluster
  4. Service discovery - Pods can resolve Service names
graph LR A[Pod Created] --> B[DNS Config Injected] B --> C[nameserver: CoreDNS IP] B --> D[search: default.svc.cluster.local] C --> E[CoreDNS Resolves Queries] style A fill:#e1f5ff style C fill:#e8f5e9 style E fill:#fff4e1

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 IP
  • search - 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 name
  • default - Namespace
  • svc - Service type
  • cluster.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
graph TB A[CoreDNS Deployment] --> B[CoreDNS Pod 1] A --> C[CoreDNS Pod 2] B --> D[CoreDNS Service] C --> D D --> E[Service IP: 10.96.0.10] F[Pods] --> E style D fill:#e8f5e9 style E fill:#fff4e1

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 discovery
  • forward - Forward queries to upstream DNS
  • cache - DNS response caching
  • prometheus - Metrics endpoint

DNS Resolution Flow

When a pod makes a DNS query:

graph LR A[Pod] --> B[DNS Query: my-service] B --> C{Short or FQDN?} C -->|Short| D[Try with search domains] C -->|FQDN| E[Query directly] D --> F[CoreDNS] E --> F F --> G{Service exists?} G -->|Yes| H[Return Service IP] G -->|No| I[Forward to upstream] style A fill:#e1f5ff style F fill:#fff4e1 style H fill:#e8f5e9

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

  1. Check CoreDNS pods: kubectl get pods -n kube-system -l k8s-app=kube-dns
  2. Test DNS from pod: kubectl run -it --rm debug --image=busybox --restart=Never -- nslookup kubernetes.default
  3. Check CoreDNS logs: kubectl logs -n kube-system -l k8s-app=kube-dns
  4. Verify Service exists: kubectl get service -n kube-system kube-dns
  5. Check DNS config: kubectl get configmap coredns -n kube-system -o yaml

Service Not Resolving

  1. Verify Service exists: kubectl get service <service-name>
  2. Check namespace: Ensure Service is in expected namespace
  3. Test with FQDN: Try full FQDN instead of short name
  4. Check Endpoints: kubectl get endpoints <service-name>
  5. Review CoreDNS logs: Look for resolution errors

DNS Slow

  1. Check CoreDNS performance: Review CoreDNS metrics
  2. Increase replicas: Scale CoreDNS Deployment
  3. Check cache settings: Verify cache configuration
  4. Review network policies: Ensure DNS traffic is allowed
  5. Check node resources: Ensure nodes have adequate resources

Best Practices

  1. Use Service names - Always use Service DNS names, not IPs
  2. Use FQDN for cross-namespace - Use full FQDN when accessing Services in other namespaces
  3. Monitor CoreDNS - Monitor CoreDNS health and performance
  4. Scale CoreDNS - Ensure adequate CoreDNS replicas for cluster size
  5. Allow DNS in Network Policies - Always allow DNS egress in Network Policies
  6. Test DNS resolution - Regularly test DNS resolution
  7. Document custom DNS - Document any custom DNS entries
  8. Keep CoreDNS updated - Update CoreDNS regularly
  9. Monitor DNS metrics - Track DNS query performance
  10. Use short names when possible - Use short names within same namespace

See Also