Cases4 cases
1 to 4 of 4
IL-0204An etcd memory spike overloaded the control plane of a Render Frankfurt cluster, and DNS then failed because CoreDNS ran on the rebooted control plane nodes and could not start without the API serverRender2024- Symptoms
In January 2022 an etcd memory spike overloaded the Kubernetes control plane of one of Render's clusters in Frankfurt. At first only operations that need the control plane failed: new deploys and cron job runs.
- Trigger
A memory spike in etcd overloaded the cluster's control plane.
- Root cause
- Component
- Contributing factor
- Action items
- Run CoreDNS on data plane nodes instead of control plane nodes
- Run etcd on dedicated nodes
- Lessons
CoreDNS can keep answering from its in-memory cache while the API server is down, but it cannot initialise without it. With CoreDNS on the control plane nodes, a reboot or restart during a control plane outage turned a failure of deploys and cron jobs into a failure of requests to services that were already running. The core problem was that the data plane was not isolated enough from the control plane: even without the reboot, the etcd memory spike alone could have forced CoreDNS to restart.
IL-0194After a kube-apiserver restart, pod LIST requests from every pod of a Vector DaemonSet nearly tripled etcd memory and restarted all master nodesPalark2023- Symptoms
One evening, right after an ordinary restart of kube-apiserver in a customer's production cluster, etcd memory consumption rose almost threefold. The sudden growth led to a cascading restart of all the master nodes.
- Trigger
An ordinary restart of kube-apiserver, after which every pod of the log collector DaemonSet sent its list requests at the same time.
- Root cause
- Component
- Contributing factor
- Detection
Memory graphs showed etcd memory on the master nodes almost tripling after a kube-apiserver restart; the audit logs then pointed to one DaemonSet's list requests.
- Remediation
- created a PriorityLevelConfiguration named limit-list-custom that queues requests (assuredConcurrencyShares 5, 16 queues, handSize 4, queueLengthLimit 50)
- created a FlowSchema that routes list and get requests on pods from the log collector's service account to that priority level
- Action items
- Submit a pull request adding resource version support to the Kubernetes Rust library
- Open a pull request to the Vector log collector to address the startup list requests
- Apply the same flow-control approach to a similar problem found with the Cilium CNI
- Lessons
A field selector reduces what kube-apiserver returns, not what it reads from etcd: listing the pods of one node still reads every pod in the cluster. A DaemonSet whose pods all list at startup multiplies that by the node count each time kube-apiserver restarts. Where exact freshness is not needed, resourceVersion=0 lets kube-apiserver answer from its cache; where the client cannot set it, API Priority and Fairness can queue the requests so they reach etcd gradually.
IL-0076Kubernetes masters went down after Dex filled etcd with AuthRequest objects and deleting its namespace started an endless list-and-timeout loopFullstaq2019- Symptoms
Dex, the OIDC proxy that handled Kubernetes authentication, stored its data in the Kubernetes API (storage type kubernetes, inCluster: true) and had built up a huge number of AuthRequest objects. Listing all AuthRequests timed out, and without the list they could not be deleted.
- Trigger
The dex namespace was deleted so that Kubernetes would clean up the accumulated AuthRequest objects itself.
- Root cause
- Component
- Contributing factor
- Detection
The speaker says he had got hints of the problem earlier. While the masters were down, plenty of alerts arrived in Slack, but monitoring could not be reached because authentication and port-forwarding no longer worked.
- Remediation
- removed the kubernetes finalizer from the dex namespace by calling the API directly (kill-kube-ns)
- deployed Dex to a new namespace with sane defaults
- Lessons
Dex with Kubernetes as its storage keeps every AuthRequest as an API object, and with a long TTL they pile up until the API cannot list them. Deleting a namespace that holds that many objects makes Kubernetes list them in a loop and can overload the masters. Monitoring that is reached through cluster authentication is lost when authentication is what broke.
IL-0075Kubernetes API servers pegged on CPU when the cluster grew to about 290 nodes, traced to Datadog agents polling the APICivis Analytics2019- Symptoms
After Civis released its new script infrastructure on Kubernetes internally in September 2018, developers reported that kubectl commands were slow, and users intermittently could not start notebooks and services.
- Trigger
Migrating clients' Python, R and container scripts from the in-house Bocce system to Kubernetes (the project called Croquet) pushed the cluster to about 290 EC2 instances under a large script load.
- Root cause
- Component
- Contributing factor
- Detection
Developer reports of slow kubectl commands and user reports of notebooks and services failing to start, then high CPU on the master nodes.
- Remediation
- moved internal users back to the old Bocce infrastructure
- resized the three master nodes from m4.large to m4.4xlarge
- changed the Datadog setup so per-node agents no longer polled the API server for service metadata
- raised max-requests-inflight for non-mutating requests from 400 to 1200
- grew the etcd EBS volumes from 20 to 100 GB (100 to 300 IOPS)
- switched client scripts from the ClusterFirst DNS policy to Default
- Action items
- Upgrade etcd from 2.2.1 to 3.x once Kops supports a safe migration
- Solve the in-cluster DNS timeouts so client scripts can talk to other workloads in the cluster
- Lessons
Kubernetes can reach thousands of nodes only after tuning, and third-party DaemonSets are a common cause of control plane load: an agent on every node that polls or watches the API server multiplies with the cluster size. Datadog, kube2iam and the fluentd metadata filter all showed this. A small configuration change often fixes it, but finding it took load testing and the API server access logs.
These 4 cases involve etcd and Kubernetes API server. 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 cause1
Capacity exhaustion4 cases
- Contributing factor
- Organisation
IL-0204An etcd memory spike overloaded the control plane of a Render Frankfurt cluster, and DNS then failed because CoreDNS ran on the rebooted control plane nodes and could not start without the API serverRender2024IL-0194After a kube-apiserver restart, pod LIST requests from every pod of a Vector DaemonSet nearly tripled etcd memory and restarted all master nodesPalark2023IL-0076Kubernetes masters went down after Dex filled etcd with AuthRequest objects and deleting its namespace started an endless list-and-timeout loopFullstaq2019IL-0075Kubernetes API servers pegged on CPU when the cluster grew to about 290 nodes, traced to Datadog agents polling the APICivis Analytics2019