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

Cases18 cases

13 to 17 of 18

  1. Symptoms

    At 08:52 PM IST a report came in from WER that many students could not access the JupyterHub and that it was frozen; pages were stuck and nothing was usable. A rise in activity was visible by 09:02 PM, but the usual fixes, such as opening an incognito window and restarting servers, did not help.

    Trigger

    WER students' pods used a good chunk of their memory limit (tests had shown they almost always use just under 1G of their 2G limit, against a 512M guarantee) on nodes shared with the hub's core pods.

    Root cause
    Component
    Contributing factor
    Detection

    WER reported stuck pages and students unable to reach the hub in a GitHub issue (2i2c-org/docs#27).

    Remediation
    • removed memory overcommit for the WER students
    • raised resource guarantees for all core pods, which restarted them and moved some to a new node
    Action items
    • Put user pods in a separate pool so they do not create pressure on the core pods (infrastructure#89)
    • Set limits on the support infrastructure (Prometheus, Grafana, ingress) as well (infrastructure#90)
    • Document and think about overcommit ratios for memory usage (infrastructure#91)
    • Set up better Grafana dashboards to monitor resource usage (infrastructure#92)
    • Document how people can get kubectl access to the cluster so others can look into issues too (infrastructure#87)
    Lessons

    Core pods without resource guarantees get whatever is left on a node, so when user pods on the same nodes fill the CPU and memory, the hub that serves everyone freezes. The memory overcommit ratio has to come from measured use: WER students used just under 1G against a 512M guarantee, which a 4x overcommit could not hold.

  2. Symptoms

    At 08:18 UTC on 13 July 2020, production Kubernetes pods began to be marked unavailable. The loss of pods spread through the clusters and reduced capacity until GitHub.com services went down.

    Trigger

    A container in the production pods exceeded its memory limit and was terminated; a routine DNS maintenance operation completed earlier had left the clusters unable to reach the image registry.

    Root cause
    Component
    Contributing factor
    Remediation
    • restarted the process with the cached DNS records so the clusters could reach the registry
    • fetched the container images, redeployed and recovered the services
    Action items
    • Improve monitoring so pod restarts cannot fail again in the same pattern
    • Minimise the dependency on the image registry
    • Expand validation during DNS changes
    • Re-evaluate all existing Kubernetes deployment policies
    • Improve progressive deployments so the impact of a deployment can be evaluated incrementally
    Lessons

    A container that production traffic does not need can still take pods out of service, because a pod is available only when all of its containers are healthy. ImagePullPolicy Always turns every container restart into a registry dependency, so an unrelated DNS change that breaks registry access turns a one-minute self-healing event into a long outage, and a mass redeploy spreads it.

  3. Symptoms

    Right after an updated RedisFailover resource was rolled out, the large Redis database lost all its data and the service went down; the data had to be restored from a backup taken just before the change.

    Trigger

    A RedisFailover change that raised the number of Redis replicas from one to two and, in the same rollout, lowered the containers' memory requests and limits from 22 GB to 19 GB.

    Root cause
    Component
    Contributing factor
    Remediation
    • restored the Redis data from the backup prepared before the rollout
    Action items
    • Report the readiness probe flaw to the Redis Operator project and test the developers' fix
    • Reconsider the use of the Spotahome Redis Operator
    • Clean up the Redis databases and fix the application code that created the excess keys
    • Consider Redis built-in clustering and sharding
    Lessons

    Changing the replica count and the pod resources in one rollout turned a seemingly harmless change into a rolling restart of the only pod with data while the new replica was still empty. A readiness probe that only checks that Redis answers a ping does not tell whether a replica has finished syncing. Operators for critical stateful components need to be evaluated for maturity before production use, and the dump.rdb file should be backed up before any change to the Redis cluster.

  4. Symptoms

    On a Saturday at 5:12 pm, Blue Matador's own monitoring raised a SystemOOM event for one node in the production Kubernetes cluster. Four minutes later a second warning reported a low EBS Burst Balance on that node's root volume. CloudWatch data showed the burst balance had actually bottomed out at 5:02 pm, before the memory event; the warning arrived late because EBS metrics lag 10 to 15 minutes.

    Trigger

    Memory use of the fluentd-sumologic log shipper pods grew until the node ran out of memory; log volume in Sumo Logic had been steady, so a burst of logs was not the cause.

    Root cause
    Component
    Contributing factor
    Detection

    Blue Matador's own monitoring product alerted on the SystemOOM event, followed minutes later by a low EBS Burst Balance warning for the same node.

    Remediation
    • restarted all fluentd-sumologic pods so they started with low memory
    • set RUBY_GC_HEAP_OLDOBJECT_LIMIT_FACTOR to 0.9 on the fluentd-sumologic pods
    • added memory requests of 128Mi and limits of 1024Mi, and CPU requests of 100m and limits of 250m, to the fluentd-sumologic pods
    Action items
    • Apply default resource limits and resource quotas so that every pod runs with requests and limits
    Lessons

    When checking for restarted pods, look in every namespace, not only the application one. Set resource requests and limits on every pod, third-party ones in particular, so that one workload cannot exhaust a node. Investigate side signals such as the disk I/O spike while the logs still exist.

  5. Symptoms

    The NU.nl development team got reports that several services on one of its Kubernetes clusters behaved erratically: occasional error pages, slow responses and timeouts. The affected services were mostly internal tools and dashboards.

    Trigger

    A new ElastAlert rule, deployed shortly before from the command line, that fired if the Cloudfront-* Elasticsearch indexes stopped receiving documents; those indexes take a few million requests per hour, and the rule made ElastAlert's memory grow without bound.

    Root cause
    Component
    Contributing factor
    Detection

    Users reported error pages, slow responses and timeouts from several services; no alert fired.

    Remediation
    • terminated the NotReady nodes one by one so the auto-scaling group replaced them (the new nodes also went NotReady, but Prometheus and Grafana landed on a stable node)
    • found the ElastAlert pods' memory growth on the Grafana pod memory dashboard
    • fixed the ElastAlert problem that caused the memory growth
    Action items
    • Define alerts on resource usage such as CPU, memory and disk space
    • Keep researching an alerting strategy that combines Elasticsearch, Prometheus Alertmanager and New Relic
    • Consider exporting metrics out of the cluster and running Grafana outside it, on EC2 or a separate Kubernetes cluster
    • Either visualise the important metrics in the ELK stack or make Prometheus and Grafana more available, and improve the metrics strategy
    • Set resource limits for ElastAlert through the Helm values
    • Configure namespaces with default memory requests and limits
    • Isolate customer-facing workloads from build, logging and monitoring workloads (a dedicated node group, or later a separate tools cluster)
    • Deploy everything through automation such as Jenkins pipelines, and consider a GitOps approach
    • Deploy through a pipeline that includes a smoke test step
    • Make Kubernetes and cloud infrastructure work part of the team's sprints, picked up by all team members while pairing with more experienced members, and hold workshops that go deep into specific topics
    Lessons

    Fixing the root cause covers only a small part of what an incident can teach; the chain of smaller failures around it is where most of the learning is. A pod without a memory limit can take whole nodes down, so limits need defaults at the namespace level. Monitoring that runs inside the cluster it watches goes blind with it. Changes installed by hand from the command line leave the rest of the team without a record of what changed.

Check your cluster for this

These 18 cases involve Container memory limit and Node pool. 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 exhaustion12 cases

  1. IL-0102 CoreDNS pods on a production EKS cluster ran out of memory under a burst of new pods, endpoints and nodes, taking down the Buildkite web UI, APIs and job dispatch
  2. 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
  3. IL-0027 All CoreDNS pods landed on one node, the node ran out of memory, and DNS for the whole service went down
  4. IL-0044 Prometheus OOMKilled in a loop while replaying its write-ahead log after a kube-prometheus-stack upgrade
  5. IL-0110 A Grafana Agent pod's high memory use and crash-looping Hangfire pods drove a Kubernetes node into system OOM and NotReady, twice in one day
    DFDS2024
  6. IL-0169 The Scaleway Kubernetes API in FR-PAR ran out of memory under simultaneous deployments, and because it also handled node authentication, Kapsule and Kosmos nodes went NotReady
  7. IL-0016 Prometheus on the live cluster ran out of memory and was OOMKilled, and the monitoring node it ran on went NotReady
  8. IL-0165 Some LKE users in Frankfurt could not reach their kube-apiservers with kubectl after backend services failed under memory constraints
    Linode2023
  9. IL-0206 Consul agents in GitLab.com's GKE pods were repeatedly OOM-killed, so the Rails pods lost database replica discovery and sent every query to the primary
    GitLab2022
  10. IL-0094 Student pods filled the shared nodes of a JupyterHub cluster and starved the hub's core pods, freezing the hub
    2i2c2020
  11. IL-0026 Kubernetes nodes hit SystemOOM because fluentd-sumologic log shipper pods had no memory limits
  12. IL-0001 Cluster-wide DNS outage after CoreDNS pods were OOM-killed again and again under a burst of DNS queries

Configuration change3 cases

  1. IL-0063 VPN outage after recreating a Redis StatefulSet restarted the whole Redis cluster without readiness checks
  2. IL-0191 A label selector accidentally added to the Loki distributor Service matched only the new pods of a rollout, which took all write traffic, were OOM-killed and stalled the rollout
  3. IL-0035 Worker nodes went NotReady after a new ElastAlert rule without memory limits used up node memory
    NU.nl2019

Software defect2 cases

Organisation
  1. IL-0123 A response buffer allocated anew in a loop made OpenAI's routing layer nodes hit their memory limits and fail readiness checks on a morning with more completions than any day before, causing 502 and 503 errors across all models
    OpenAI2023
  2. IL-0196 Adding a second Redis replica and lowering memory limits in one RedisFailover change restarted the only Redis pod that held data, and Sentinel promoted the empty new replica, erasing the data
    Palark2020

DNS or network fault1 case

Organisation
  1. IL-0199 A non-essential container exceeding its memory limit made GitHub's production pods unavailable, and their restarts failed because a DNS maintenance change had left the clusters unable to reach the image registry
    GitHub2020