Expert coverage of CoreDNS cloud-native DNS server: Corefile plugin-chain configuration, Kubernetes DNS (cluster.local, services, pods, headless, ExternalName), NodeLocal DNSCache, custom Go plugins, forward/cache/rewrite/prometheus plugins, ConfigMap management, and DNS performance in large clusters. Use for \"CoreDNS\", \"Corefile\", \"Kubernetes DNS\", \"kube-dns\", \"NodeLocal DNSCache\", \"CoreDNS plugin\", \"cluster.local\", \"CoreDNS ConfigMap\". Do NOT use for cross-vendor comparison,...
Installs into .claude/skills of the current project.
Are you the author of Coredns?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/chrishuffman5-coredns)
---
name: coredns
description: "Expert coverage of CoreDNS cloud-native DNS server: Corefile plugin-chain configuration, Kubernetes DNS (cluster.local, services, pods, headless, ExternalName), NodeLocal DNSCache, custom Go plugins, forward/cache/rewrite/prometheus plugins, ConfigMap management, and DNS performance in large clusters. Use for \"CoreDNS\", \"Corefile\", \"Kubernetes DNS\", \"kube-dns\", \"NodeLocal DNSCache\", \"CoreDNS plugin\", \"cluster.local\", \"CoreDNS ConfigMap\". Do NOT use for cross-vendor comparison, platform selection, or category-wide architecture -- use the `dns` skill."
license: MIT
---
# CoreDNS
This skill covers CoreDNS (1.13), the cloud-native DNS server written in Go that serves as the default DNS service for Kubernetes (since 1.13). Areas of expertise include:
- Plugin-chain architecture with Corefile configuration
- Kubernetes DNS specification: service/pod resolution, headless services, ExternalName, SRV records
- NodeLocal DNSCache for high-performance per-node caching in large clusters
- Core plugins: kubernetes, forward, cache, loop, loadbalance, rewrite, prometheus, errors, health, ready
- ConfigMap-based hot-reload for Kubernetes deployments
- Custom Go plugin development (plugin.Handler interface)
- Conditional forwarding for hybrid DNS (Kubernetes + corporate DNS)
- DNS performance optimization in microservices architectures
## How to Approach Tasks
1. **Classify** the request:
- **Kubernetes DNS** -- Service discovery, pod resolution, ConfigMap configuration
- **Plugin configuration** -- Corefile syntax, plugin chaining, conditional forwarding
- **Performance** -- NodeLocal DNSCache, cache tuning, conntrack issues
- **Custom development** -- Go plugin development, build system, plugin.cfg
- **Architecture** -- Load `references/architecture.md` for plugin chain, Kubernetes integration, NodeLocal DNSCache
2. **Identify deployment** -- Kubernetes CoreDNS (most common), standalone CoreDNS, or NodeLocal DNSCache DaemonSet.
3. **Identify cluster scale** -- Small (< 100 pods) vs large (1000+ pods). Scale determines whether NodeLocal DNSCache is needed and cache sizing.
4. **Recommend** -- Provide Corefile configuration blocks. For Kubernetes, show ConfigMap edits with `kubectl edit configmap coredns -n kube-system`.
## Core Architecture
### Plugin Chain
CoreDNS processes queries through an ordered chain of plugins:
- Each `server block` in the Corefile binds to an address:port and chains plugins
- Plugins execute in the order specified in `plugin.cfg` (compile-time), not Corefile order
- First plugin to handle a query responds; remaining plugins are skipped
- Plugin writes a response OR calls `plugin.NextOrFailure()` to pass to next plugin
### Corefile Structure
```
.: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
}
```
Multiple server blocks for different zones:
```
cluster.local:53 {
kubernetes cluster.local
cache 30
}
corp.internal:53 {
forward . 10.0.0.53
cache 60
}
.:53 {
forward . 8.8.8.8 1.1.1.1
cache 30
}
```
## Kubernetes DNS
### Record Types
| Query Pattern | Record Type | Resolution |
|---|---|---|
| `<svc>.<ns>.svc.cluster.local` | A/AAAA | ClusterIP |
| `<pod-ip-dashes>.<ns>.pod.cluster.local` | A | Pod IP |
| `_<port>._<proto>.<svc>.<ns>.svc.cluster.local` | SRV | Named port endpoints |
| Headless service | A | All pod IPs (multiple records) |
| ExternalName service | CNAME | External FQDN |
### Kubernetes Plugin Configuration
```
kubernetes cluster.local in-addr.arpa ip6.arpa {
pods insecure # pod record mode: disabled|insecure|verified
fallthrough in-addr.arpa ip6.arpa # pass unresolved reverse to next plugin
ttl 30 # TTL for DNS records
endpoint_pod_names # use pod names in A record responses
namespaces <ns1> <ns2> # restrict to specific namespaces
}
```
Pod modes:
- `disabled`: no pod records
- `insecure`: return pod IP for any query matching pod IP format (default)
- `verified`: verify pod exists in Kubernetes API before returning record
### ConfigMap Hot-Reload
The `reload` plugin watches for ConfigMap changes and hot-reloads without pod restart:
```bash
kubectl edit configmap coredns -n kube-system
```
Changes take effect within the reload interval (default 30s, configurable).
### Conditional Forwarding (Hybrid DNS)
Add stub domains for corporate/internal DNS resolution:
```
corp.internal:53 {
errors
cache 30
forward . 10.0.0.53 10.0.0.54
}
consul.local:53 {
errors
cache 15
forward . 10.0.0.8600
}
```
## NodeLocal DNSCache
Improves DNS performance in large Kubernetes clusters:
```
Pod ──► NodeLocal DNSCache (169.254.20.10) ──► kube-dns ClusterIP ──► CoreDNS
(per-node DaemonSet) (on cache miss)
```
- Runs CoreDNS as DaemonSet on every node
- Each node has local cache at link-local IP `169.254.20.10`
- **Eliminates iptables DNAT and conntrack for DNS** -- critical at scale
- Conntrack table exhaustion is a common DNS failure mode in large clusters
- Cache misses forwarded to kube-dns ClusterIP
- Reduces p99 DNS latency significantly for DNS-heavy workloads
### Deployment
```bash
kubectl apply -f https://raw.githubusercontent.com/kubernetes/kubernetes/master/cluster/addons/dns/nodelocaldns/nodelocaldns.yaml
```
Requires kubelet `--cluster-dns=169.254.20.10` configuration.
## Core Plugins
| Plugin | Purpose | Key Config |
|---|---|---|
| `kubernetes` | Kubernetes service/pod resolution | Zone, pod mode, fallthrough |
| `forward` | Upstream forwarding | Servers, max_concurrent, policy |
| `cache` | Response caching | TTL, max size, denial caching |
| `loop` | Loop detection (prevent forwarding loops) | Auto-detection |
| `loadbalance` | Round-robin A/AAAA records | Automatic |
| `health` | Health probe endpoint (:8080/health) | lameduck duration |
| `ready` | Readiness probe endpoint (:8181/ready) | Per-plugin readiness |
| `prometheus` | Metrics endpoint (:9153/metrics) | Automatic |
| `errors` | Error logging | Consolidation period |
| `log` | Query logging | Response class filter |
| `rewrite` | Name/type/class rewriting | Pattern, answer rewriting |
| `hosts` | Zone from hosts file format | Inline entries, fallthrough |
| `dnssec` | Inline DNSSEC signing | Key file, zones |
| `transfer` | AXFR zone transfer | To/from configuration |
| `etcd` | SkyDNS v1 compatibility | etcd endpoints |
| `grpc` | gRPC DNS backend | Server address |
### Forward Plugin Options
```
forward . 8.8.8.8 1.1.1.1 {
max_concurrent 1000 # concurrent queries per upstream
policy round_robin # round_robin | random | sequential
health_check 5s # upstream health check interval
tls_servername dns.google # for DNS over TLS
force_tcp # force TCP transport
expire 10s # connection expiry
}
```
### Rewrite Plugin
```
rewrite name exact old.example.com new.example.com
rewrite name suffix .old.example.com .new.example.com answer auto
rewrite type AAAA A # rewrite query type
```
## CoreDNS 1.13 Features
- **DoH3 (DNS over HTTP/3)**: experimental QUIC/HTTP3 transport support
- **Regex length limit**: security hardening in `rewrite` plugin
- **QUIC listener initialization**: safer startup preventing race conditions
- **Kubernetes API rate limiting**: improved rate limiting with metrics
- **Reduced SOA warnings**: fewer misleading log entries
- **Data race fix in `uniq` plugin**: stability for response deduplication
## Custom Go Plugins
Extend CoreDNS by implementing `plugin.Handler`:
```go
package myplugin
import (
"github.com/coredns/coredns/plugin"
"github.com/miekg/dns"
)
type MyPlugin struct {
Next plugin.Handler
}
func (m MyPlugin) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (int, error) {
// Custom logic here
return plugin.NextOrFailure(m.Name(), m.Next, ctx, w, r)
}
func (m MyPlugin) Name() string { return "myplugin" }
```
Build with custom `plugin.cfg`:
```
# Add custom plugin to plugin chain
myplugin:github.com/myorg/coredns-myplugin
```
Compile: `go generate && go build`
## Common Pitfalls
1. **Loop detection false positive** -- The `loop` plugin detects forwarding loops by sending a test query. If CoreDNS forwards to itself (e.g., via /etc/resolv.conf pointing to localhost), it shuts down. Fix: ensure `forward . <upstream>` does not point back to CoreDNS.
2. **Conntrack exhaustion without NodeLocal DNSCache** -- In large clusters, DNS queries through kube-proxy iptables consume conntrack entries. At scale, conntrack table exhaustion causes DNS failures. Deploy NodeLocal DNSCache.
3. **ConfigMap edit syntax errors** -- YAML indentation errors in CoreDNS ConfigMap cause CoreDNS to crash-loop. Always validate YAML before applying. Use `kubectl logs -n kube-system -l k8s-app=kube-dns` to check for errors.
4. **Stub domain ordering** -- More specific zones must have separate server blocks. Zone matching is longest-suffix-first, but plugin chain order within a block matters.
5. **Cache TTL too high for dynamic environments** -- Default 30s cache is fine for stable services. For rapidly changing endpoints (canary, blue-green), reduce or disable cache for specific zones.
6. **Missing `fallthrough` on kubernetes plugin** -- Without `fallthrough`, reverse DNS queries for non-Kubernetes IPs return NXDOMAIN instead of forwarding to upstream. Add `fallthrough in-addr.arpa ip6.arpa`.
## Reference Files
- `references/architecture.md` -- Plugin architecture, Corefile, Kubernetes DNS, NodeLocal DNSCache