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

Cases7 cases

4 to 7 of 7

  1. Symptoms

    At 13:42 the RootVolUtilisation-Critical alert fired in the high-priority alerts channel. At 14:03 a user reported image pull errors with the message "no space left on device".

    Trigger

    Upgrading the EKS Terraform module to version 18, which changed the node launch template, and draining workloads onto the new nodes it created.

    Root cause
    Component
    Contributing factor
    Detection

    The RootVolUtilisation-Critical alert fired in the high-priority alerts channel at 13:42, and a user reported "no space left on device" image pull errors at 14:03.

    Remediation
    • Uncordoned the old default node group and drained the new nodes to move workloads back
    • Identified the launch template change that cut the root volume to 20 GB and applied a fix on the manager and live clusters
    • Drained the old node group onto the fixed nodes
    Action items
    • Update the runbook to compare launch template changes during an EKS module upgrade
    • Create a test setup that pulls images of different sizes, like live
    • Update the RootVolUtilisation alert runbook to check the disk space configuration
    • Scale CoreDNS dynamically based on the number of nodes
    • Investigate whether IPv6 can solve the IP prefix starvation problem
    • Add drift testing to identify when a terraform plan shows a change to the launch template
    • Set up logging for the CNI and ipamd logs and alerts on errors related to IP prefix starvation
    Lessons

    The write-up lists review actions rather than lessons. They aim at two gaps: the launch template changes brought by a module upgrade were not compared or drift-tested before rollout, and there were no CNI or ipamd logs or alerts to show the IP prefix starvation the team suspected during the drain.

  2. Symptoms

    The hub pod of the prod JupyterHub on the leap cluster (leap.2i2c.org) restarted unexpectedly during a large node scale-up, and a user opened a support ticket. The ingress-nginx and proxy pods kept running.

    Trigger

    A user's dask-gateway workload added about 100 dask-worker nodes within a minute, and Prometheus started scraping the metrics exporters on about 200 nodes.

    Root cause
    Component
    Contributing factor
    Detection

    A user support ticket (2i2c Freshdesk ticket 414) about the leap hub; the engineer then looked at Grafana and the cluster's nodes and events.

    Action items
    • Configure CPU and memory requests for the hub and proxy pods (#2127; at least 100m CPU was proposed)
    • Make the Grafana OOMKiller dashboard work (#2213)
    • Move LEAP cloud infrastructure to shared nodes (#2209)
    • Update resource requests and limits, mainly for ingress-nginx and Prometheus (#2324)
    • Decide whether Prometheus should scrape dask worker pods (#2366)
    Lessons

    Prometheus load grows with the number of nodes, so a burst of autoscaled nodes can push a nearly full core node over the edge and evict the pods that matter most. Core pods that request 10m of CPU get a tenth of the CPU share of busy neighbours that request 100m. Kubernetes events expire after an hour, so evidence of OOM kills needs a dashboard that keeps it.

  3. Symptoms

    On Friday 19 July 2019 the Grafana Cloud Hosted Prometheus service, which is built on the Cortex project, was down for 26 minutes. New error-budget-based Prometheus alerts paged the on-call engineer within 4 minutes of the start.

    Trigger

    An engineer created a new dedicated Cortex cluster for a large customer. Its configuration did not include the new pod priorities, so all its pods got the default medium priority, and the Kubernetes cluster did not have enough free resources to fit it.

    Root cause
    Component
    Contributing factor
    Detection

    New error-budget-based Prometheus alerts paged the on-call engineer within 4 minutes of the start of the outage.

    Remediation
    • Scaled up the underlying Kubernetes cluster to fit both the new and the production Cortex clusters
    • Diagnosed and fixed the out-of-memory errors in the authenticating reverse proxies in front of Cortex
    Action items
    • Give the production ingesters the high priority class, which should have been done before medium became the default
    • Have more people review changes to configuration that is global to the cluster
    • Require a design document for every configuration change outside a namespace
    • Automate the sizing of the frontend authenticating reverse proxy so it does not run out of memory under overload
    • Investigate the default backoff and scaling behaviour of Prometheus to prevent a stampeding herd of retries
    Lessons

    Medium should not have become the default priority until the production ingesters had the high priority, and that designation should have reached production sooner. The change was considered too minor for a design document and was only discussed in a GitHub issue; cluster-global configuration needs more scrutiny. On the positive side, once Cortex had enough capacity it recovered by itself, and Grafana Loki helped confirm that the ingesters exited gracefully.

  4. Symptoms

    During a rolling update of a kubelet change in one of Oath's on-premises production clusters, nodes started going NotReady, and soon all nodes in the cluster were NotReady.

    Trigger

    A change to kubelet was rolled out across the nodes of one cluster; on restart, kubelet cleans up transient cgroup files, and a Kubernetes bug in that step left kubelet stuck instead of starting.

    Root cause
    Component
    Contributing factor
    Detection

    Nodes reported NotReady and the eviction graphs climbed while the kubelet rollout was in progress.

    Remediation
    • failed the affected data center over so users were routed to the next available data center
    Action items
    • Run a functional test of kubelet after each upgrade batch and certify it before the next 30% of nodes are updated
    Lessons

    Check kubelet after upgrading it before moving to the next batch; a simple curl against the kubelet API would have caught this. The node controller's eviction throttling and full disruption mode, which the speakers note is not well documented, kept a cluster-wide kubelet failure from evicting every pod.

Check your cluster for this

These 7 cases involve Node pool and AWS VPC CNI. 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 exhaustion2 cases

Organisation
  1. IL-0099 User servers on 2i2c's Earthscope hub took over 15 minutes to start and kernels were killed during a workshop, because a profile option guaranteed 8 GB of memory with no limit on 32 GB nodes
    2i2c2025
  2. IL-0070 Critical pods on core nodes evicted when Prometheus began scraping about 200 nodes after a dask-gateway scale-up
    2i2c2023

Faulty deployment1 case

  1. IL-0020 During an EKS 1.30 upgrade the descheduler tried to reschedule every pod on the cordoned nodes at once and production workloads went down

Configuration change3 cases

  1. IL-0114 An unpinned AWS VPC CNI plugin was updated automatically during a capacity expansion, leaving new pods Pending without IP addresses and stopping CoW Protocol settlements for about 3.5 hours
  2. IL-0019 An EKS Terraform module upgrade shrank node root disks from 100 GB to 20 GB and image pulls failed with no space left on device
  3. IL-0004 A new default pod priority let a new Cortex cluster preempt every production ingester in a cascade, taking Grafana Cloud Hosted Prometheus down

Software defect1 case

Organisation
  1. IL-0038 kubelet rollout hit a Kubernetes bug and left every node in a cluster NotReady, triggering mass pod eviction
    Oath2018