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

Cases6 cases

1 to 5 of 6

  1. Symptoms

    On 16 May 2025, in Neon's Kubernetes cluster in AWS us-east-1, new compute pods were scheduled but could not start and failed with IP allocation errors. Each Neon compute is a Postgres database running in a lightweight virtual machine in its own pod, so without new pods, idle customer databases could not be woken up.

    Trigger

    On 16 May the Neon control plane's periodic job that terminates idle computes started failing. Compute creations continued, and the number of active computes rose from about 5k to about 8.1k within minutes. On 19 May, a follow-up change that set WARM_IP_TARGET back to 1 started the second round of failures.

    Root cause
    Component
    Contributing factor
    Detection

    As cluster-autoscaler added nodes, the team saw IP allocation errors on new pods that were scheduled but could not start. The rate of successful pod starts and VPC subnet metrics were then used to follow the problem.

    Remediation
    • Set WARM_IP_TARGET=1 to release IPs held by nodes without free CPU or memory
    • Fixed the control plane's periodic job so idle computes were terminated again
    • Restarted the aws-node DaemonSet several times, each with a temporary improvement
    • Set WARM_IP_TARGET=0, MINIMUM_IP_TARGET=0 and WARM_ENI_TARGET=0, which let nodes allocate enough IPs and stabilised the cluster
    • On 19 May, set WARM_IP_TARGET back to 0 after setting it to 1 failed again
    • Enlarged the pool of pre-created warm compute pods to absorb failed pod starts
    Action items
    • Open a pull request to AWS CNI to improve how ipamd releases IPs in this situation
    • Follow up with AWS Support about the roughly 100 subnet IPs that were never allocated, for reasons Neon could not explain
    • Change the architecture to support horizontal scaling
    Lessons

    With default settings AWS CNI can keep many IPs on nodes that cannot use them, so the share of subnet IPs assigned to pods does not tell how close the subnet is to running out. WARM_IP_TARGET and WARM_ENI_TARGET follow different logic, a warm IP target of zero switches to the ENI logic, and IPs in cooldown count toward the target, which behaves badly under high pod churn. Changing these settings during an incident without knowing that logic prolonged the outage, and reverting a setting did not bring back the earlier healthy state.

  2. Symptoms

    At 09:36 on 18 March 2025, during the upgrade of the live cluster to EKS 1.30, users reported that their pods were being terminated and were not restarting automatically, in both production and non-production environments. Automated infrastructure alerts fired as well, and production services had outages.

    Trigger

    Upgrading the live EKS cluster from 1.29 to 1.30, during which the descheduler attempted to reschedule all pods on the cordoned nodes simultaneously.

    Root cause
    Component
    Contributing factor
    Detection

    Users reported at 09:36 that pods were being terminated and not restarting, and automated infrastructure alerts fired.

    Remediation
    • Removed the cordon annotation so pods could be rescheduled
    • Deleted stuck 1.30 nodes to force their recreation
    • Added a new node group of 20 nodes running 1.30 by hand
    • Cordoned and drained all old 1.29 nodes onto the new 1.30 nodes
    Action items
    • Raise an AWS Production System Down support case (Case ID: 174229643100496)
    • Get guidance from AWS support on querying control-plane logs to find the root cause of similar issues
    • Document a runbook for emergency scaling of a new node group in case of unexpected capacity shortages
    • Alert on an imbalance between the autoscaling group and the Kubernetes nodes
    • Review the descheduler configuration to understand why it throws pods off cordoned nodes, and fix it where possible
    • Alert on spikes in the pending pod count
    Lessons

    The write-up lists review actions rather than lessons. They show the team had no documented way to add an emergency node group, no alert on a mismatch between the autoscaling group and the nodes Kubernetes sees, no alert on a spike in pending pods, and no clear understanding of how the descheduler treats cordoned nodes.

  3. Symptoms

    A user of the LIS JupyterHub reported a "backoff after failed scale-up" error, and user servers would not start. An engineer opened incident #36, "LIS hub cannot scale", at 5:40 AM Pacific on 14 November 2022.

    Trigger

    At 10 AM UK time on 14 November 2022, the B zone of Google Cloud's europe-west2 region (London) ran out of resources to allocate. The LIS cluster's nodes were restricted to that zone.

    Root cause
    Component
    Contributing factor
    Detection

    A user reported the "backoff after failed scale-up" error; an engineer opened the incident at 5:40 AM Pacific, about three hours and forty minutes after the zone ran out of resources.

    Remediation
    • edited the node pool in the GCP console to allow node creation in the A and C zones of europe-west2, which were not exhausted
    Action items
    • Either restrict the node pool back to the B zone after the Black Friday event, or move the cluster and the NFS Filestore to the A zone (infrastructure issue #1944)
    • Investigate an enterprise plan that allows a regional NFS, at higher cost (infrastructure issue #1945)
    • Make sure PagerDuty notifications always get through to engineers (team-compass issue #574)
    Lessons

    A node pool pinned to one zone for storage performance cannot scale when the cloud provider runs out of capacity in that zone. The autoscaler's "backoff after failed scale-up" message usually points to quotas, and raising quotas does nothing here; the ZONE_RESOURCE_POOL_EXHAUSTED error in the logs is what identifies a zone without capacity. The review found that one engineer wearing many hats (incident commander, comms and debugging), with pages not reaching the other responders, made the response harder; a team response would have given more support.

  4. Symptoms

    At 08:05 UTC on 2021-06-21 the API service's Apdex (the share of requests that finish within a target time) and Rails request queuing began trending the wrong way. At 09:01 the team found the API deployment unhealthy: it needed more pods for the day's growing traffic, but no new nodes could be added to give it pod capacity. Users saw slow responses; the review found no sign that error rates rose.

    Trigger

    Google Cloud ran out of SSD persistent disk stock in us-east1, the region GitLab.com runs in, while the API service needed more nodes for rising user traffic.

    Root cause
    Component
    Contributing factor
    Detection

    There was no alert on resource availability. Apdex and Rails queuing began trending the wrong way at 08:05 UTC and an engineer declared the incident in Slack at 08:43; finding the cause took a lot of log digging: cluster autoscaler errors about node pools in backoff, then ZONE_RESOURCE_POOL_EXHAUSTED at the instance-group level, and finally Google Cloud support naming SSD as the exhausted resource.

    Remediation
    • added a node pool that uses pd-standard disks
    • scaled the new node pool by hand across all three zones to relieve the API
    • brought more pd-standard node pools online for the other blocked workloads
    • stopped production deployments and opened a Google Cloud support case about the cluster autoscaler not working with the new node pools
    • changed node pools and nodeSelectors so the remaining workloads ran on pd-standard nodes
    • removed the SSD-backed node pools after a day without problems
    Action items
    • Move Kubernetes services to pd-standard disks (delivery#1837)
    • Capture resource exhaustion errors as a metric
    Lessons

    A cloud region can run out of one specific resource, here SSD persistent disks, and the only error may be a generic ZONE_RESOURCE_POOL_EXHAUSTED that does not name it. GitLab could neither monitor nor reserve resource availability, so detection took 22 hours and the cause came from Google Cloud support. The workloads ran fine on pd-standard disks. A second problem found on the way, a cluster autoscaler that does not fall back to another matching node pool when one cannot scale, slowed the move to the new node pools.

  5. Symptoms

    A colleague wrote in Slack that his application was taking a long time to deploy. A deployment that normally finishes in minutes had been running for about an hour: about half of the new pods were running and serving traffic, and the other half were Pending.

    Trigger

    The cluster reaching 256 nodes, the most its /16 pod secondary range could hold at 256 addresses per node; every further node creation failed.

    Root cause
    Component
    Contributing factor
    Detection

    A colleague reported in Slack that a deployment was slow; the pending pods' events and the cluster autoscaler status ConfigMap showed the exhausted IP space.

    Remediation
    • lowered the maximum pods per node on selected node pools, cutting IP consumption by about 30%
    • moved some node pools to larger instance types
    Action items
    • Lower the maximum pods per node on node pools that do not run many pods
    • Use larger instance types in some node pools
    Lessons

    In a VPC-native GKE cluster the number of nodes, not the number of pods, uses up the pod range: by default each node reserves 256 addresses, so even a /16 is full at 256 nodes. Maximum pods per node and node size are the practical levers; larger nodes pack better but take more pods down when they fail.

Check your cluster for this

These 6 cases involve Cluster autoscaler 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 cause3

Capacity exhaustion2 cases

Organisation
  1. IL-0006 VPC subnets ran out of IP addresses because the AWS VPC CNI kept IPs on full nodes, and WARM_IP_TARGET changes then blocked pod starts after every pod deletion
    Neon2025
  2. IL-0015 A GKE cluster's /16 pod address range ran out at 256 nodes, leaving new pods Pending and node scale-ups failing

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

Cloud provider outage3 cases

  1. IL-0096 A GKE node pool pinned to the europe-west2-b zone could not scale for 6.5 hours because Google ran out of resources in that zone (ZONE_RESOURCE_POOL_EXHAUSTED)
    2i2c2022
  2. IL-0205 The GKE cluster autoscaler could not add nodes to GitLab.com's production cluster because Google Cloud ran out of SSD persistent disks in us-east1
    GitLab2021
  3. IL-0014 A GKE upgrade to a withdrawn version stalled on slow drains and a stuck node pool, then broke an ingress and confused the HPA