تخطَّ إلى المحتوى

CoreDNS Cheat Sheet

Overview

CoreDNS is a DNS server written in Go that operates through a flexible plugin chain architecture. Each DNS request passes through a series of plugins that can perform actions like caching, forwarding, logging, rewriting, and serving zone data. CoreDNS replaced kube-dns as the default DNS server in Kubernetes starting with version 1.13, making it the most widely deployed DNS server in container environments. It serves as both an authoritative DNS server and a recursive resolver.

CoreDNS configuration uses a Corefile, inspired by Caddy’s configuration format. Server blocks define zones and the plugins that handle them. Plugins are executed in a fixed order regardless of their position in the config file. CoreDNS supports DNS over TLS (DoT), DNS over HTTPS (DoH), DNS over gRPC, and traditional UDP/TCP. It can read zones from files, databases, etcd, Kubernetes API, or serve dynamically generated records. Its lightweight footprint and extensive plugin ecosystem make it suitable for everything from simple caching resolvers to complex multi-zone authoritative servers.

Installation

Binary Installation

# Download latest release
wget https://github.com/coredns/coredns/releases/download/v1.11.3/coredns_1.11.3_linux_amd64.tgz
tar xzf coredns_1.11.3_linux_amd64.tgz
sudo mv coredns /usr/local/bin/

# Verify
coredns --version

# Run with default Corefile
coredns

Docker

docker run -d --name coredns \
  -p 53:53/udp -p 53:53/tcp \
  -v $(pwd)/Corefile:/Corefile \
  -v $(pwd)/zones:/zones \
  coredns/coredns

Systemd Service

[Unit]
Description=CoreDNS DNS Server
After=network.target

[Service]
Type=simple
ExecStart=/usr/local/bin/coredns -conf /etc/coredns/Corefile
Restart=on-failure
User=coredns
Group=coredns
LimitNOFILE=8192

[Install]
WantedBy=multi-user.target

Core Configuration (Corefile)

Basic Forwarding Resolver

. {
    forward . 8.8.8.8 8.8.4.4 {
        tls_servername dns.google
    }
    cache 300
    log
    errors
}

Authoritative Zone

example.com {
    file /etc/coredns/zones/example.com.zone
    log
    errors
}

. {
    forward . 8.8.8.8
    cache 3600
    log
}

Zone File Example

; /etc/coredns/zones/example.com.zone
$ORIGIN example.com.
$TTL 3600

@   IN  SOA ns1.example.com. admin.example.com. (
        2024010101  ; Serial
        3600        ; Refresh
        900         ; Retry
        604800      ; Expire
        86400       ; Minimum TTL
    )

    IN  NS  ns1.example.com.
    IN  NS  ns2.example.com.
    IN  A   203.0.113.10
    IN  MX  10 mail.example.com.

ns1     IN  A   203.0.113.1
ns2     IN  A   203.0.113.2
www     IN  A   203.0.113.10
mail    IN  A   203.0.113.20
api     IN  A   203.0.113.30
db      IN  A   10.0.0.50

Plugin Reference

PluginDescription
forwardProxy DNS requests to upstream resolvers
cacheEnable DNS response caching
fileServe zones from RFC 1035 zone files
logEnable query logging
errorsLog errors to stdout
hostsServe from /etc/hosts style file
rewriteRewrite queries before processing
templateGenerate responses from templates
healthHTTP health check endpoint
readyReadiness probe endpoint
prometheusExport Prometheus metrics
loadbalanceRandomize A/AAAA record order
loopDetect forwarding loops
kubernetesKubernetes service discovery
etcdServe records from etcd
aclAccess control lists

Kubernetes DNS

Default Kubernetes CoreDNS 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 {
           max_concurrent 1000
        }
        cache 30
        loop
        reload
        loadbalance
    }

Custom DNS Entries in Kubernetes

apiVersion: v1
kind: ConfigMap
metadata:
  name: coredns-custom
  namespace: kube-system
data:
  custom.server: |
    example.com:53 {
        forward . 10.0.0.53
    }
  internal.override: |
    rewrite name api.internal.svc.cluster.local api-service.default.svc.cluster.local

Advanced Configuration

DNS over TLS (DoT)

tls://.:853 {
    tls /etc/coredns/cert.pem /etc/coredns/key.pem
    forward . 8.8.8.8
    cache 300
    log
}

DNS over HTTPS (DoH)

https://.:443 {
    tls /etc/coredns/cert.pem /etc/coredns/key.pem
    forward . 8.8.8.8
    cache 300
}

Query Rewriting

example.com {
    rewrite name prefix old. new.
    rewrite name exact legacy.example.com modern.example.com
    rewrite stop {
        name regex (.*)\.old\.example\.com {1}.new.example.com
        answer name (.*)\.new\.example\.com {1}.old.example.com
    }
    forward . 8.8.8.8
}

Split DNS / Conditional Forwarding

internal.corp {
    forward . 10.0.0.53 10.0.0.54
    cache 600
}

aws.internal {
    forward . 10.0.0.2
    cache 60
}

. {
    forward . 8.8.8.8 1.1.1.1
    cache 3600
}

Template Plugin (Dynamic Records)

example.com {
    template IN A {
        match .*\.example\.com
        answer "{{ .Name }} 60 IN A 10.0.0.1"
        fallthrough
    }
}

ACL Plugin

. {
    acl {
        allow net 10.0.0.0/8
        allow net 192.168.0.0/16
        block
    }
    forward . 8.8.8.8
}

Monitoring

# Health check endpoint (default :8080)
curl http://localhost:8080/health

# Readiness endpoint (default :8181)
curl http://localhost:8181/ready

# Prometheus metrics (default :9153)
curl http://localhost:9153/metrics

Key Prometheus Metrics

MetricDescription
coredns_dns_requests_totalTotal DNS requests by zone and type
coredns_dns_responses_totalTotal responses by rcode
coredns_dns_request_duration_secondsRequest latency histogram
coredns_cache_hits_totalCache hit count
coredns_cache_misses_totalCache miss count

Troubleshooting

IssueSolution
bind: address already in useStop existing DNS service on port 53 (systemd-resolved)
Loop detectedRemove forward . /etc/resolv.conf if resolv.conf points to CoreDNS itself
Kubernetes DNS not resolvingCheck CoreDNS pods: kubectl -n kube-system get pods -l k8s-app=kube-dns
SERVFAIL responsesCheck upstream resolver connectivity; review errors plugin output
Slow DNS resolutionEnable cache plugin; check upstream latency with dig
Zone file not loadingValidate zone file syntax; check serial number incremented
Hot-reload not workingEnsure reload plugin is in the Corefile