Incident Library
  • Root cause
  • Component
  • Symptom
  • Contributing factor
  • Case

Cases8 cases

1 to 5 of 8

  1. Symptoms

    A Kubernetes worker node paged with NodeFilesystemFilesFillingUp, the node_exporter mixin alert that predicts a filesystem will run out of inodes. The engineer checked disk space first: df -h showed the root filesystem 83% used, 103G used and 22G available. df -i showed inodes 67% used, 11M used and 5.3M free.

    Trigger

    Several versions of a single-stage Node.js image, each shipping more than 40,000 files, were held on the node; containerd unpacked every layer with a distinct digest into its own snapshot, each with a full copy of node_modules.

    Root cause
    Component
    Contributing factor
    Detection

    The NodeFilesystemFilesFillingUp alert from the node_exporter mixin fired on the predicted inode trend while inode use was at 67%.

    Action items
    • Build the image in multiple stages so the final image contains only the compiled assets
    • Add a flat alert on root filesystem inode use above 80% for 30 minutes alongside the predictive alert
    • Put a Prometheus query on a dashboard that shows, per node, inode usage minus disk usage, sorted from the highest
    • Remove unused images from nodes with crictl rmi --prune to free old snapshots
    Lessons

    kubelet's background cleanup works on bytes only. A workload heavy in small files gets no early intervention for inodes, and the first thing kubelet does at 5% free inodes is evict pods. Watch inode use on nodes separately from disk use, and keep dependency trees out of runtime images.

  2. Symptoms

    The cluster could not be reached from outside. On the control plane node, sudo systemctl status kubelet showed TLS handshake errors such as "http: TLS handshake error from 101.198.0.183:19517: tls: client requested unsupported application protocols" and "http: TLS handshake error from 101.198.0.172:36328: tls: client offered only unsupported versions: [302 301]".

    Trigger

    The leaf certificates that kubeadm had generated for the cluster, valid for one year by default, expired at 2026-02-20 16:16 UTC.

    Root cause
    Component
    Contributing factor
    Detection

    The author could not connect to the cluster from outside and went to the control plane node to read the kubelet logs.

    Remediation
    • renewed all expired certificates with sudo kubeadm certs renew all
    • restarted containerd and the kubelet so the static control plane pods restarted with the new certificates
    • copied the renewed /etc/kubernetes/admin.conf to $HOME/.kube/config
    Lessons

    A kubeadm cluster stops working one year after its leaf certificates were issued unless they are renewed. The first errors seen may be TLS handshake failures or a flag error that does not mention certificates; the decisive message is the x509 expiry in the kube-apiserver log for its connection to etcd. The author recommends checking expiry with kubeadm certs check-expiration and renewing from 30 days before. kubeadm upgrade apply renews the certificates too, so a cluster upgraded at least once a year avoids the problem; a cluster run for a long time without upgrades can renew from cron, for example with 0 3 1 1 * root kubeadm certs renew all && systemctl restart kubelet in /etc/cron.d/kubeadm-cert-renew.

  3. 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.

  4. Symptoms

    Customers of DigitalOcean Managed Kubernetes (DOKS) saw worker nodes go NotReady between 06:00 and 07:00 UTC and stay unavailable, taking down the services on them, until the nodes were replaced or rebooted; some nodes needed several replacements or reboots. The first sporadic reports on October 8 said replacing the node fixed it. The same thing happened again around 06:00 UTC on October 9, more widely and across many regions, and again on October 10. Only clusters on versions 1.27.6-do.0 and 1.28.2-do.0 were affected.

    Trigger

    A systemd timer in the DigitalOcean Debian image started apt upgrade daily at 06:00 UTC, with a random delay of up to 60 minutes.

    Root cause
    Component
    Contributing factor
    Detection

    Sporadic customer reports of failed worker nodes arrived at 07:43 UTC on October 8; internal incident response started at 07:10 UTC on October 9 after broader impact across regions.

    Remediation
    • Advised customers to replace or reboot affected worker nodes
    • Arranged SSH and console access to worker nodes while they were healthy, and live-debugged an affected node on October 10
    • Released a DaemonSet to all affected clusters that disables the apt upgrade systemd timer on every worker node
    • Released new node images without the auto-update process
    Action items
    • Disable the timer during node provisioning, then remove the DaemonSet from all clusters
    • Add a check to the internal conformance test suite for new cluster versions that the auto-upgrade process and other unwanted timers stay disabled
    • Support logging into worker nodes even when normal access paths are broken
    Lessons

    An operating system auto-update timer left enabled in a node image can change the kernel and systemd underneath Kubernetes, and a timeout that kills the upgrade half-way can leave a node without networking. Failures that start at the same time every day point to a scheduled job on the nodes, and systemd timers belong on that list next to cron jobs. When the failure takes out a node's network, an investigation that depends on logging into the node stalls; access paths that work while the node is broken shorten diagnosis.

  5. Symptoms

    Builds on Zalando's in-house Continuous Delivery Platform (CDP), which runs CI/CD on Kubernetes, timed out and failed for almost an hour on 11 June 2019. The Kubernetes builder pods could not get AWS IAM credentials.

    Trigger

    An unlucky rescaling of the CDP Kubernetes cluster left only one node available for builder pods. Builder pods were created and deleted on that node so quickly that kubelet fell behind.

    Root cause
    Component
    Contributing factor
    Remediation
    • Scaled the CDP cluster up by hand so builder pods spread over more than one node
    Action items
    • Raise the kubelet QPS limit from the default 5 to 50 in the global cluster configuration
Check your cluster for this

These 8 cases involve kubelet 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 cause4

Capacity exhaustion4 cases

  1. IL-0071 Worker node running out of inodes while disk space looked fine, because containerd kept a full node_modules tree in each of several image layer snapshots
  2. IL-0027 All CoreDNS pods landed on one node, the node ran out of memory, and DNS for the whole service went down
  3. IL-0002 CI builder pods could not get AWS IAM credentials because kubelet fell minutes behind its API rate limit
  4. IL-0040 Parallel Helm installs saturated small gp2 root volumes on a kops cluster and left all three workers NotReady with the kubelet or Docker down

Certificate or credential expiry1 case

Contributing factor
Organisation
  1. IL-0183 kubeadm's one-year leaf certificates expired, so kube-apiserver could not reach etcd, restarted in a loop and left the cluster unreachable

Configuration change2 cases

  1. IL-0153 DOKS worker nodes went NotReady at 06:00 UTC on three days because a systemd timer in the Debian image ran apt upgrade and killed it mid kernel upgrade, breaking node networking
  2. IL-0035 Worker nodes went NotReady after a new ElastAlert rule without memory limits used up node memory
    NU.nl2019

unknown1 case

Organisation
  1. IL-0059 Single-master Kubernetes control plane kept dying because the kubelet restarted a healthy etcd on a failing kubeadm liveness probe