Cases3 cases
1 to 3 of 3
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-0184JupyterHub's KubeSpawner could not create containers and kubectl was refused because the API server and other internal certificates of a kubeadm cluster had expireddbhang2021- Symptoms
KubeSpawner, which starts JupyterHub user containers on Kubernetes, failed to create containers with an error the author had never seen, saying an SSL certificate had expired.
- Root cause
- Component
- Contributing factor
- Detection
KubeSpawner failed to create a container and logged an SSL certificate verification error.
- Remediation
- checked certificate expiry with kubeadm alpha certs check-expiration
- moved the old certificates and /etc/kubernetes/*.conf files to a backup directory
- regenerated all certificates with kubeadm init phase certs all
- regenerated the kubeconfig files with kubeadm init phase kubeconfig all
- copied /etc/kubernetes/admin.conf to ~/.kube/config and restarted kubelet
- restarted the kube-system containers with docker restart so they picked up the new credentials
- Lessons
kubeadm clusters run on certificates that expire, and when the API server certificate expires kubectl cannot be used to fix it, so renewal has to happen on the control plane node with kubeadm. After renewal, the kubeconfig files and the running control plane containers must also pick up the new certificates, or kubectl returns Unauthorized.
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 3 cases involve Kubernetes API server 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 cause2
Capacity exhaustion2 cases
- Contributing factor
- Organisation
IL-0194After a kube-apiserver restart, pod LIST requests from every pod of a Vector DaemonSet nearly tripled etcd memory and restarted all master nodesPalark2023IL-0075Kubernetes API servers pegged on CPU when the cluster grew to about 290 nodes, traced to Datadog agents polling the APICivis Analytics2019
Certificate or credential expiry1 case
- Component
- Contributing factor
- Organisation