Cases4 cases
1 to 4 of 4
IL-0027All CoreDNS pods landed on one node, the node ran out of memory, and DNS for the whole service went downBackpackr2025- Symptoms
Services on the production Amazon EKS cluster behind the idus marketplace threw intermittent errors whose cause was hard to pin down. Calls to external services such as RDS and Redis failed now and then, and whenever DNS traffic spiked, domain lookups answered slowly or failed outright.
- Trigger
All CoreDNS pods were scheduled onto the same node, and that node's memory usage spiked until it ran out of memory.
- Root cause
- Component
- Contributing factor
- Detection
The write-up does not say how the full outage was noticed. The earlier DNS trouble showed up as intermittent service errors, and investigating failed calls to RDS and Redis led to DNS resolution failures.
- Remediation
- deployed NodeLocal DNSCache as a DaemonSet in front of CoreDNS
- added a PodDisruptionBudget (maxUnavailable 1) and topologySpreadConstraints across zones for CoreDNS
- lowered ndots from 5 to 2 with dnsConfig in the Deployments
- Lessons
The CoreDNS setup that EKS creates by default (two pods) can be enough for a small or development cluster but becomes a bottleneck in a large production cluster, and DNS is a single point of failure that needs high availability and room to scale. Tuning the CoreDNS cache and buffer size only relieved the symptoms; the real load came from the extra queries that ndots:5 generates for external names. A CoreDNS pod without a memory limit can share a node's fate with everything else on it.
IL-0059Single-master Kubernetes control plane kept dying because the kubelet restarted a healthy etcd on a failing kubeadm liveness probeNRE Labs2018- Symptoms
The daily NRE Labs statistics showed lesson activity collapsing, and kubectl could not reach the cluster: `The connection to the server 1.2.3.4:6443 was refused - did you specify the right host or port?`
- Trigger
Unknown. The liveness probe that kubeadm writes into the etcd static pod manifest (an `etcdctl get foo` against 127.0.0.1:2379, failureThreshold 8, timeoutSeconds 15) started failing. The author first suspected GCP maintenance the night before, but could not reproduce the probe failure by hand and does not know why it began.
- Root cause
- Component
- Contributing factor
- Detection
The author saw lesson activity drop in the daily NRE Labs statistics during his morning routine.
- Remediation
- removed the liveness probe section from the kubeadm-generated etcd static pod manifest and applied it between etcd restarts
- Action items
- Add monitoring, especially for the single-node master
- Run a basic "down for maintenance" page in Google Cloud Functions that points to Twitter for updates, to redirect to during outages
- Lessons
Because all of the infrastructure is managed as code, the cluster could be rebuilt quickly, but destroying it before finding the cause also destroyed the evidence. Monitoring matters, especially with a single-node master. Read the restart counts in kubectl output, not just the Running status. Remember the fundamentals instead of expecting the issue to be more complicated than it is, and do not let the urgency of an outage push you into hasty decisions. Put up a maintenance page instead of leaving the site failing halfway.
IL-0003linkerd lost Kubernetes service discovery after an etcd reconfiguration, and restarting every linkerd instance turned failed payments into a full platform outageMonzo2017- Symptoms
At 14:10 an engineer deployed a change to a service that Monzo's current account needs to process payments, and every request to that service started to fail. Current account customers saw payment failures; the prepaid card was not affected at first because it does not use that service. The change was rolled back at 14:12, but the errors continued.
- Trigger
At 14:10 an engineer deployed a change to a service needed to process current account payments. Two weeks earlier the etcd cluster had been upgraded and grown from three to nine nodes, and one day earlier another team had scaled a new service down to zero replicas while leaving its Kubernetes service in place.
- Root cause
- Component
- Contributing factor
- Detection
Payment failures began right after the 14:10 deploy. The team rolled back at 14:12 and declared an outage internally at 14:16. At 15:13, when no service could serve requests, practically all automated alerts fired.
- Remediation
- Rolled back the payments service change (the errors continued)
- Activated internal backup processes so most customers could still use their card
- Restarted all linkerd instances (this made the outage worse)
- Restarted the three Kubernetes API server processes so replacement linkerd instances could start
- Began deploying a newer linkerd version with the fix for empty services
- Deleted the Kubernetes service that had no endpoints, which let linkerd load service discovery again
- Action items
- Fix the bug in Kubernetes that can trigger timeouts after a cluster reconfiguration
- Roll out a new version of linkerd that fixes the parsing error
- Create better health checks, dashboards and alerts for the affected components so they give clearer signals about what is wrong and prevent human error
- Improve procedures to communicate outages internally and externally as clearly and quickly as possible
- Lessons
A large failure in a distributed system can be very hard to understand, and well-meant human action can compound it, as restarting every linkerd instance did here by exposing a second incompatibility. Because Monzo deploys often and its network changes constantly, the deployment and request-routing systems have to be trustworthy. Monzo committed to publishing a similar post-mortem for any incident of this severity.
IL-0040Parallel Helm installs saturated small gp2 root volumes on a kops cluster and left all three workers NotReady with the kubelet or Docker downSaltside2017- Symptoms
While running the CI process on a local machine to test an application Helm chart, the SRE lead watched the pods with watch kubectl get pods. All pods reached Running, and then some went back to Pending. Two hours later the problem had grown and some pods showed the phase Unknown.
- Trigger
A CI run installed the application's Helm charts for all four markets (Efritin.com, Tonaton.com, Ikman.lk and Bikroy.com) on the nonproduction cluster at the same time.
- Root cause
- Component
- Contributing factor
- Detection
The SRE lead saw pods go from Running back to Pending while watching kubectl get pods during the CI run; no monitoring raised an alert, even when all three workers were not ready.
- Remediation
- terminated the three worker nodes and let the auto scaling group replace them
- Action items
- Fix the Datadog integration for the nonproduction AWS account and repeat the installs with telemetry
- Increase the worker root EBS volumes from 20GB to 120GB
- Keep common base images pulled on every node with a DaemonSet until kops supports user hooks
- Configure different allocation limits for the different layers in Kubernetes
- Discuss a highly available Tiller with the Helm team
- Find a way to throttle the number of newly created pods
- Lessons
An ordinary deploy of the application could collapse the cluster, because the default 20GB gp2 root volumes could not keep up with parallel image pulls and container starts. Without node metrics and pod phase metrics, three NotReady workers raised no alert. A single Tiller replica can block the deploy that would fix an outage.
These 4 cases involve kubelet and etcd. kubegap audits a Kubernetes cluster for gaps like these, read-only, from Claude Code or Codex; its checks cite public reports like the ones in this library.
By root cause3
Capacity exhaustion2 cases
- Component
- Contributing factor
- Organisation
unknown1 case
- Component
- Contributing factor
- Organisation
Software defect1 case
- Contributing factor
- Organisation