Skip to content

8.13 CoreDNS in Kubernetes

Abstract

CoreDNS is the internal DNS service used by Kubernetes to provide service discovery inside the cluster.

It watches the Kubernetes API and automatically creates DNS records for Services and, when configured, Pods.

In production, CoreDNS must be monitored carefully because application communication often depends on DNS resolution.


Why Kubernetes Needs CoreDNS

In a small environment, name resolution can be done manually using /etc/hosts.

Example:

cat >> /etc/hosts
web 10.244.2.5

But this does not work well in Kubernetes because:

  • Pods are created and deleted frequently
  • Pod IPs change
  • Services are created dynamically
  • Clusters may have thousands of workloads
  • Manual /etc/hosts updates do not scale

Warning

Manual /etc/hosts entries are not suitable for production Kubernetes service discovery.


Manual DNS Problem

Example Pods:

Pod IP Address
test 10.244.1.5
web 10.244.2.5
db 10.244.2.15

Without DNS, each Pod would need manual entries like:

web   10.244.2.5
test  10.244.1.5
db    10.244.2.15

This becomes impossible to maintain at cluster scale.

Note

Kubernetes solves this by running a centralized internal DNS service.


Central DNS Approach

Instead of editing every Pod manually:

  1. Kubernetes runs a DNS service inside the cluster
  2. Pods use that DNS service as their nameserver
  3. CoreDNS watches Kubernetes objects
  4. DNS records are updated automatically

Example Pod resolver:

nameserver 10.96.0.10

Tip

10.96.0.10 is a common ClusterIP for the Kubernetes DNS Service, but the actual value depends on the cluster.


kube-dns Service

CoreDNS Pods are exposed through a Service, commonly named:

kube-dns

Check it:

kubectl get service -n kube-system

Example output:

NAME       TYPE        CLUSTER-IP   PORT(S)
kube-dns   ClusterIP   10.96.0.10   53/UDP,53/TCP

Success

Pods do not talk directly to CoreDNS Pod IPs. They use the stable kube-dns Service IP.


CoreDNS Components

CoreDNS usually runs as:

  • Deployment
  • ReplicaSet
  • Pods
  • ConfigMap
  • Service

Check CoreDNS Pods:

kubectl get pods -n kube-system -l k8s-app=kube-dns

Check ConfigMap:

kubectl get configmap -n kube-system

Common ConfigMap name:

coredns

Note

In kubeadm-based clusters, CoreDNS is normally deployed in the kube-system namespace.


Corefile

CoreDNS uses a configuration file called:

Corefile

In Kubernetes, the Corefile is usually stored in a ConfigMap.

View it:

kubectl get configmap coredns -n kube-system -o yaml

Edit it:

kubectl edit configmap coredns -n kube-system

Warning

Be careful when editing the CoreDNS ConfigMap. A bad Corefile can break DNS resolution for the whole cluster.


Example Corefile

.:53 {
    errors
    health

    kubernetes cluster.local in-addr.arpa ip6.arpa {
        pods insecure
        upstream
        fallthrough in-addr.arpa ip6.arpa
    }

    prometheus :9153

    forward . /etc/resolv.conf

    cache 30
    reload
}

Corefile Plugin Breakdown

Plugin Purpose
errors Logs DNS errors
health Provides health check endpoint
kubernetes Watches Kubernetes API and serves cluster DNS records
prometheus Exposes CoreDNS metrics
forward Sends external DNS queries to upstream resolvers
cache Caches DNS responses
reload Reloads Corefile changes automatically

Tip

The most important plugin for Kubernetes service discovery is the kubernetes plugin.


Kubernetes Plugin

The Kubernetes plugin enables CoreDNS to resolve Kubernetes objects.

Example:

kubernetes cluster.local in-addr.arpa ip6.arpa {
    pods insecure
    upstream
    fallthrough in-addr.arpa ip6.arpa
}

Meaning:

Option Description
cluster.local Cluster DNS root domain
pods insecure Enables Pod DNS records using IP-based names
upstream Uses upstream resolver behavior
fallthrough Sends unresolved reverse lookups to next plugin

Note

cluster.local is the default Kubernetes DNS domain, but it can be changed during cluster setup.


Service DNS Records

When a Service is created, CoreDNS creates DNS records automatically.

Example:

Service Namespace ClusterIP
web-service default 10.107.37.188

DNS names:

web-service
web-service.default
web-service.default.svc
web-service.default.svc.cluster.local

Success

Service records are the standard way applications discover each other in Kubernetes.


Pod DNS Records

Pod DNS records are different.

Kubernetes does not use the Pod name directly for default Pod DNS records.

Instead, the Pod IP is converted by replacing dots with dashes.

Example:

Pod IP: 10.244.2.5

Pod DNS name:

10-244-2-5.default.pod.cluster.local

Warning

Pod DNS records depend on CoreDNS configuration and should not be used as the main discovery method for applications.


Pod Resolver Configuration

Kubernetes automatically injects DNS configuration into Pods.

Check inside a Pod:

kubectl exec <pod-name> -- cat /etc/resolv.conf

Example:

nameserver 10.96.0.10
search default.svc.cluster.local svc.cluster.local cluster.local

Note

The kubelet is responsible for configuring Pod DNS settings when Pods are created.


DNS Search Domains

Search domains allow short names to work.

Example search list:

default.svc.cluster.local
svc.cluster.local
cluster.local

Because of this, a Pod in the default namespace can access:

curl http://web-service

Kubernetes expands it to:

web-service.default.svc.cluster.local

Tip

Search domains are why short Service names work inside the same namespace.


Service Name Resolution Examples

For a Service named web-service in namespace default:

curl http://web-service
curl http://web-service.default
curl http://web-service.default.svc
curl http://web-service.default.svc.cluster.local

All can resolve to:

10.107.37.188

Cross-Namespace Resolution

If the Service is in another namespace, use:

<service-name>.<namespace>

Example:

curl http://web-service.apps

Fully qualified:

curl http://web-service.apps.svc.cluster.local

Warning

Do not rely on short names for cross-namespace communication. Use service.namespace or the full FQDN.


DNS Query Flow

Application Pod
/etc/resolv.conf
kube-dns Service IP
CoreDNS Pod
Kubernetes plugin
Service / Pod DNS record

If the name is external, CoreDNS forwards the query:

Pod → CoreDNS → /etc/resolv.conf upstream resolver → internet DNS

Note

Internal Kubernetes names are resolved by the Kubernetes plugin. External names are forwarded upstream.


External DNS Resolution

CoreDNS forwards unmatched queries using:

forward . /etc/resolv.conf

Example:

nslookup google.com

Flow:

Pod
  → CoreDNS
  → upstream nameserver
  → external DNS result

Tip

If internal DNS works but external DNS fails, check CoreDNS forwarding and node DNS configuration.


CoreDNS and kubelet

The kubelet config includes cluster DNS settings.

Common kubelet fields:

clusterDNS:
  - 10.96.0.10
clusterDomain: cluster.local

These values are used to populate Pod /etc/resolv.conf.

Note

kubelet config decides what DNS server and domain Pods receive.


View CoreDNS Health

Check CoreDNS Pods:

kubectl get pods -n kube-system -l k8s-app=kube-dns

Check CoreDNS Service:

kubectl get svc -n kube-system kube-dns

Check logs:

kubectl logs -n kube-system -l k8s-app=kube-dns

Check endpoints:

kubectl get endpoints -n kube-system kube-dns

Success

Always check both the CoreDNS Pods and the kube-dns Service when troubleshooting DNS.


Test DNS from a Pod

Create a temporary BusyBox Pod:

kubectl run -it --rm dns-test \
  --image=busybox:1.28 \
  --restart=Never \
  -- nslookup kubernetes.default

Test a Service:

kubectl run -it --rm dns-test \
  --image=busybox:1.28 \
  --restart=Never \
  -- nslookup web-service.default.svc.cluster.local

Test external DNS:

kubectl run -it --rm dns-test \
  --image=busybox:1.28 \
  --restart=Never \
  -- nslookup google.com

Common DNS Issues

Issue Possible Cause
Service name not resolving Service does not exist
Service resolves but connection fails Endpoints missing or Pod not Ready
External DNS fails CoreDNS forwarder or node DNS issue
Short name fails Wrong namespace or search domain
Pod DNS fails Pod records disabled or wrong FQDN
Random DNS timeouts CoreDNS under-scaled or network issue

Debug order

First check Service, then Endpoints, then CoreDNS, then Pod /etc/resolv.conf.


Production Best Practices

Recommended

  • Run multiple CoreDNS replicas
  • Monitor CoreDNS latency, errors, and cache behavior
  • Use Service DNS names for app communication
  • Use fully qualified names for critical cross-namespace dependencies
  • Avoid depending on Pod DNS records
  • Keep CoreDNS ConfigMap changes controlled through GitOps
  • Validate CoreDNS after cluster upgrades
  • Ensure NetworkPolicies allow DNS traffic to CoreDNS

DNS and NetworkPolicy

Pods need access to CoreDNS, usually on:

UDP 53
TCP 53

If NetworkPolicies are enforced, allow traffic to CoreDNS in kube-system.

Danger

Restrictive NetworkPolicies can accidentally block DNS, causing applications to fail even when Services are healthy.


Do's

  • Use Services for stable DNS records
  • Use service.namespace for cross-namespace calls
  • Check CoreDNS logs during DNS failures
  • Monitor CoreDNS in production
  • Keep CoreDNS replicas highly available
  • Allow DNS traffic in NetworkPolicies
  • Use FQDNs for troubleshooting

Don'ts

  • Don't hardcode Pod IPs
  • Don't rely on Pod DNS for stable applications
  • Don't edit CoreDNS ConfigMap without testing
  • Don't ignore DNS latency
  • Don't assume DNS failure means the application is down
  • Don't block UDP/TCP 53 to CoreDNS

Troubleshooting Checklist

When DNS fails, verify:

  • Is CoreDNS running?
  • Is the kube-dns Service present?
  • Does kube-dns have endpoints?
  • Does the Pod have correct /etc/resolv.conf?
  • Is the Service name correct?
  • Is the namespace correct?
  • Does the Service have endpoints?
  • Are NetworkPolicies allowing DNS?
  • Are CoreDNS logs showing errors?
  • Is external DNS forwarding working?

Useful Commands

kubectl get pods -n kube-system -l k8s-app=kube-dns
kubectl get svc -n kube-system kube-dns
kubectl get endpoints -n kube-system kube-dns
kubectl logs -n kube-system -l k8s-app=kube-dns
kubectl get configmap coredns -n kube-system -o yaml
kubectl exec <pod-name> -- cat /etc/resolv.conf
kubectl run -it --rm dns-test --image=busybox:1.28 --restart=Never -- nslookup kubernetes.default

Summary

Quote

  • CoreDNS provides Kubernetes internal DNS
  • CoreDNS runs in the kube-system namespace
  • Pods use the kube-dns Service IP as their nameserver
  • Service DNS records are created automatically
  • Pod DNS records use IP-based names and are not ideal for stable discovery
  • CoreDNS configuration is stored in a ConfigMap
  • DNS issues often involve CoreDNS, Service endpoints, Pod resolver config, or NetworkPolicies