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,...
Pro scans all 2 files and shows the line behind each finding
Scanned 9/24/2026
npx -y skills add chrishuffman5/domain-expert --skill coredns --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Coredns?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/chrishuffman5-coredns)More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.
---
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
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!