Tracing intermittent production timeouts to a provider-managed DNS add-on update, and the probe design that amplified it
A customer-facing document API on a large, multi-tenant AKS cluster started timing out intermittently. Nobody had deployed anything and no infrastructure had changed. Within a few hours I'd tied the onset to a provider-managed CoreDNS image update rolled out as part of routine add-on maintenance. I also found that a liveness probe in a downstream service was turning short DNS blips into a restart storm.
A consumer service in another namespace health-checked the API. Its liveness probe included that dependency check, which turned out to matter more than anyone expected.
The ReplicaSet history in kube-system showed a new CoreDNS ReplicaSet with a patch-level image bump. The first errors appeared within about two minutes of it rolling out.
kubectl -n kube-system get rs -l k8s-app=kube-dns \
-o custom-columns=NAME:.metadata.name,CREATED:.metadata.creationTimestamp,IMAGE:.spec.template.spec.containers[0].image
The same daily window had hundreds of errors on the incident day and zero on each of the two days before. That pattern points to a change, not load or slow capacity drift.
The new pods logged a steady stream of forward health-check failures and upstream i/o timeouts. Most were AAAA and HTTPS record lookups.
| Theory | Evidence | Verdict |
|---|---|---|
| Single-replica API emptied the endpoint pool | Every 503 was on the API's own readiness endpoint. There were zero customer-facing 503s | Ruled out |
| Burstable nodes out of CPU credits | Credits at maximum, node CPU around 20%, errors spread evenly across all CoreDNS pods | Ruled out |
| Database pressure | Well under the IOPS ceiling, negligible failed connections, healthy p95 latency | Ruled out |
| Managed CoreDNS update | Onset minutes after the image change, zero baseline before it | Root cause |
The consumer's liveness probe called the API's health endpoint, and failures were never cached. Every DNS blip made kubelet restart the consumer, and every probe sent a live request to one of the API's busiest endpoints.
ndots: 2 for high-volume external lookups, and a higher autoscaler ladder for CoreDNS.coredns-custom. Direct edits to the managed ConfigMap get reverted.# Illustrative: cut search-domain fan-out for workloads making many external calls
spec:
dnsConfig:
options:
- name: ndots
value: "2"
Evidence first, theory second. The obvious fix would have cost money and changed nothing. The lasting fixes were in probe design and DNS headroom.
About this case study: this write-up is drawn from my hands-on platform engineering experience. Organisation names, system names, figures and timelines have been changed or generalised, and all code, configuration and queries are illustrative examples written for this page.