CoreDNS is the default cluster DNS in every modern Kubernetes deployment. Every service discovery lookup, every inter-pod connection, every pod-to-external hostname resolution flows through it. When CoreDNS degrades — even partially — the blast radius is enormous: health checks time out, readiness probes fail, and entire application tiers silently disconnect from their dependencies.
Internal metrics from CoreDNS's built-in Prometheus endpoint tell you a lot, but they tell you nothing when the CoreDNS pods themselves are unreachable. This tutorial shows you how to layer Vigilmon external uptime monitoring on top of your CoreDNS observability stack so you catch DNS failures from the outside in.
Why CoreDNS needs external monitoring
The CoreDNS Prometheus plugin exports detailed per-plugin metrics, and you can build dashboards around query error rates, cache hit ratios, and upstream resolver latency. But internal monitoring has a blind spot: it depends on the same cluster DNS it's measuring.
External monitoring catches what internal tooling misses:
- CoreDNS pods crash-looping — the ReplicaSet eventually recovers, but DNS resolution fails cluster-wide for 30–120 seconds; external checks catch the gap immediately
- ConfigMap corruption — a bad
Corefileedit makes CoreDNS reject queries silently; internal dashboards stay green because the metrics server is still up - Upstream resolver timeouts — your pods can't resolve external hostnames but internal service discovery works fine; internal Prometheus misses this entirely
- Resource exhaustion — CoreDNS runs out of memory and starts dropping queries while appearing healthy to the node
- Node-level DNS (NodeLocal DNSCache) failure — the per-node DNS cache stops forwarding; a request hitting that node fails while the CoreDNS Deployment metrics look fine
External monitoring from Vigilmon gives you a ground-truth check from outside the cluster — the DNS availability your workloads actually experience.
What you'll need
- A Kubernetes cluster with CoreDNS (v1.9 or later recommended)
kubectlaccess with cluster-admin or sufficient RBAC to read Deployments and Services- A free Vigilmon account — no credit card required
Step 1: Verify CoreDNS metrics are exposed
CoreDNS ships with the prometheus plugin enabled by default. Confirm it's active:
kubectl get configmap coredns -n kube-system -o yaml | grep prometheus
# Should show: prometheus :9153
Port-forward to inspect available metrics:
kubectl port-forward -n kube-system deployment/coredns 9153:9153 &
curl -s http://localhost:9153/metrics | grep -E "^coredns_"
Key metrics to monitor internally:
coredns_dns_requests_total # total queries by type and zone
coredns_dns_responses_total # responses by rcode (NOERROR, SERVFAIL, NXDOMAIN)
coredns_forward_requests_total # upstream forwarder queries
coredns_forward_request_duration_seconds # upstream resolver latency
coredns_cache_hits_total # cache hit ratio numerator
coredns_cache_misses_total # cache miss ratio numerator
Useful Prometheus alert rules:
# High SERVFAIL rate — DNS is returning errors
- alert: CoreDNSHighServfailRate
expr: |
rate(coredns_dns_responses_total{rcode="SERVFAIL"}[5m]) /
rate(coredns_dns_responses_total[5m]) > 0.05
for: 2m
labels:
severity: critical
annotations:
summary: "CoreDNS SERVFAIL rate above 5%"
# Upstream resolver latency spike
- alert: CoreDNSForwarderLatencyHigh
expr: |
histogram_quantile(0.99,
rate(coredns_forward_request_duration_seconds_bucket[5m])
) > 2
for: 5m
labels:
severity: warning
annotations:
summary: "CoreDNS upstream resolver p99 latency > 2s"
# Cache hit ratio degraded
- alert: CoreDNSLowCacheHitRatio
expr: |
rate(coredns_cache_hits_total[10m]) /
(rate(coredns_cache_hits_total[10m]) + rate(coredns_cache_misses_total[10m])) < 0.3
for: 10m
labels:
severity: warning
annotations:
summary: "CoreDNS cache hit ratio below 30%"
Step 2: Expose a health endpoint for external checks
CoreDNS's health plugin exposes an HTTP health endpoint. Confirm it's enabled:
kubectl get configmap coredns -n kube-system -o yaml | grep health
# Should show: health
If missing, edit the ConfigMap to add it:
kubectl edit configmap coredns -n kube-system
Your Corefile should include:
.: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
}
The health plugin listens on port 8080 by default. Expose it via a NodePort or LoadBalancer Service for external access:
apiVersion: v1
kind: Service
metadata:
name: coredns-health
namespace: kube-system
spec:
selector:
k8s-app: kube-dns
ports:
- name: health
port: 8080
targetPort: 8080
nodePort: 32053
type: NodePort
kubectl apply -f coredns-health-svc.yaml
Test the endpoint:
curl http://<NODE_IP>:32053/health
# Returns: OK
Step 3: Add CoreDNS checks in Vigilmon
Log in to Vigilmon and add HTTP monitors for each CoreDNS health endpoint:
- Click Add Monitor → HTTP(S)
- Set URL to
http://<NODE_IP>:32053/health - Set check interval to 60 seconds
- Set expected keyword to
OK - Enable alert notifications for your team
If you have multiple control-plane nodes running CoreDNS, add one monitor per node IP. This catches node-level failures that a single endpoint check would miss.
For the ready endpoint (returns 200 only when CoreDNS is fully initialized):
curl http://<NODE_IP>:32053/ready
# Returns: OK when all plugins are loaded
Add a second Vigilmon monitor pointing to /ready with keyword OK — this catches stuck plugin initialization which /health alone doesn't surface.
Step 4: Validate the alert path end-to-end
Simulate a CoreDNS failure to confirm Vigilmon fires before your internal alerting:
# Scale CoreDNS to zero
kubectl scale deployment coredns -n kube-system --replicas=0
# Confirm DNS resolution breaks
kubectl run -it --rm debug --image=busybox --restart=Never -- nslookup kubernetes.default.svc.cluster.local
Vigilmon should alert within one to two check intervals (60–120 seconds). Check your notification channel — Slack, PagerDuty, email, or webhook — and then restore CoreDNS:
kubectl scale deployment coredns -n kube-system --replicas=2
Recommended monitoring checklist
| Signal | Source | Threshold | |--------|--------|-----------| | Query SERVFAIL rate | CoreDNS Prometheus | > 5% over 2 min | | Upstream forwarder p99 latency | CoreDNS Prometheus | > 2 s | | Cache hit ratio | CoreDNS Prometheus | < 30% | | Health endpoint reachability | Vigilmon (external) | Any downtime | | Ready endpoint reachability | Vigilmon (external) | Any downtime | | CoreDNS pod count | Kubernetes metrics | < desired replicas |
Conclusion
CoreDNS is the DNS backbone of your Kubernetes cluster. Combining its built-in Prometheus metrics with Vigilmon's external uptime checks gives you complete DNS observability: internal signals catch query-level degradation before it becomes an outage, while Vigilmon confirms end-to-end reachability from outside the cluster — the view your application pods actually experience.
Set up your first CoreDNS monitor at vigilmon.online in under five minutes.