Incident Library
Applied filters ComponentContainer CPU limitDomainKubernetesClear allEvery case under the filters, with no sentence; newest first.
Suggested filters Search, and the values found in your words appear here.

Graph

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

Cases7 cases

1 to 5 of 7

  1. Symptoms

    An e-commerce platform suddenly became slow to respond, worst on the product lookup page, and users began reporting that the page would not open.

    Trigger

    A post on the external community Ppomppu linked to the platform and brought a large number of users in a short time, who called the product lookup API heavily.

    Root cause
    Component
    Contributing factor
    Detection

    Users reported that the product page would not open. The dashboard showed all pods Running, and the namespace CPU usage near 100% and the CPU usage metrics pointed to throttling.

    Remediation
    • raised the HPA minReplicas from 5 to 10
    • raised the container CPU limit from 1 core to 2 cores
    Action items
    • Keep adjusting the CPU limit to a suitable level through monitoring
    Lessons

    CPU throttling is hard to notice: pods stay Running, nothing restarts and the logs show no clear error, so a pod list does not reveal it and CPU usage metrics do. Settings that had handled expected event traffic became the bottleneck as soon as one external post multiplied the traffic. The author concludes that the team needs more preparation for traffic pattern changes and more thought about resource settings.

  2. Symptoms

    When MonotaRO raised the share of requests for the remaining endpoints of its backend API sent to EKS from 1% to 25%, Sentry filled with errors saying the API could not reach the database and outside services. The errors were about DNS name resolution, and the traffic had to be shifted back to the EC2 version.

    Trigger

    MonotaRO raised the share of requests for the remaining API endpoints routed by the ALB to the EKS version from 1% to 25%.

    Root cause
    Component
    Contributing factor
    Detection

    Sentry showed a large number of errors about connecting to the database and outside services right after the traffic share was raised.

    Remediation
    • Shifted the requests back to the EC2 version to stop the errors
    • Added an HPA to autoscale the CoreDNS pods as a stopgap, which let the migration to EKS finish
    Action items
    • Set ndots to 1 through dnsConfig in the application Deployments
    • Set cache 600 in the Corefile in the coredns ConfigMap to lengthen the CoreDNS cache TTL
    • Add lameduck 30s to the CoreDNS health plugin so CoreDNS keeps serving while it is scaled in
    • Consider reducing the differences between production and staging, weighed against cost
    Lessons

    MonotaRO assumed that a managed service would not cause problems and so skipped researching other companies' migrations, load testing and monitoring. Staging differed from production in its network layout, so ndots differed between them, and staging databases could not take a high-load test. Looking at the CoreDNS logs and resolv.conf instead of guessing found that ndots:5 made lookups of outside names try every search domain first.

  3. Symptoms

    Request latency from the Temporal Server History service, the service that starts workflow executions and records their progress, was higher and less steady than it should be on a self-hosted Kubernetes deployment. The CPU dashboard showed the history pods using less than 60 percent of their CPU, yet the same pods were being throttled.

    Trigger

    Normal load on History pods that had a CPU limit of 2 cores on 8-core nodes, with the Go runtime's GOMAXPROCS left at its default of one per node core.

    Root cause
    Component
    Contributing factor
    Detection

    A Prometheus query for CPU throttling showed the history pods throttled although their CPU usage read under 60 percent.

    Remediation
    • set the GOMAXPROCS environment variable to 2 to match the 2-core CPU limit
    Action items
    • Set GOMAXPROCS automatically from the Kubernetes CPU limit, from Temporal release 1.21.0
    Lessons

    A CPU usage graph averaged over 15 seconds or more can sit far below 100 percent while a container is being throttled, so throttling needs its own metric. A Go program in a container should have GOMAXPROCS matched to its CPU limit, or to its CPU request when it has no limit. The author recommends not using CPU limits at all.

  4. Symptoms

    During a DevOps review of resource usage across microservices, the team lowered resources.requests.cpu from 2 to 1 for notification-preferences, a Spring WebFlux service not yet used in production. A few minutes later an alarm fired because memory usage was above 90%. Neither the memory allocation nor the JVM's GC arguments had been changed.

    Trigger

    The team lowered resources.requests.cpu for the notification-preferences deployment from 2 to 1 as part of resource optimisation, with no CPU limit set.

    Root cause
    Component
    Contributing factor
    Detection

    A memory usage alarm above 90% fired a few minutes after the CPU request was lowered.

    Remediation
    • set -XX:ActiveProcessorCount=1 in JAVA_OPTIONS so the JVM uses one processor regardless of the cgroup values
    Action items
    • Write an internal notice about the issue
    Lessons

    On cgroup v1, a JVM in a pod with a CPU request of exactly one core and no CPU limit sees every CPU of the node, because cpu.shares 1024 is read as unset. Thread pools sized from availableProcessors(), such as Reactor Netty's I/O workers, grow accordingly and use more memory. When lowering requests for JVM services without a CPU limit, set -XX:ActiveProcessorCount or a CPU limit explicitly. Later JDKs ignore CPU requests for this calculation altogether.

  5. Symptoms

    From April 11, 2022 at 13:17 UTC customers and Gitpod staff reported that Gitpod workspaces were intermittently becoming unresponsive. CPU usage of nodes and pods looked normal, with nothing maxed out, and at 13:58 UTC the team found that the workspaces were IO bound rather than CPU bound.

    Trigger

    The ws39 generation of workspace clusters, released to all regional clusters on April 8th at 20:08 UTC and to the XL clusters on April 9th at 17:45 UTC, split the 1TB disk into smaller RAID0 disks, changed CPU limiting and workspace networking, and moved to faster machine types.

    Root cause
    Component
    Contributing factor
    Detection

    Customers and Gitpod staff reported on April 11th at 13:17 UTC that workspaces were intermittently unresponsive, and the team opened an incident in Slack through its incident.io integration. On April 17th the team noticed increased CPU load on the workspace nodes and opened an internal incident.

    Remediation
    • Shifted workspace starts back to the ws38 clusters on April 11th
    • Built ws39a clusters with c2d machines and local SSDs and moved traffic to them
    • Requested a limit increase from Let's Encrypt
    • Routed EU XL traffic to the regional EU cluster and built ws-eu39bxl to replace the crashed ws-eu39xl
    • Cleaned up workspaces stuck in a stopping state so users could start them again
    • Released ws40 with 1TB boot disks to get more IO bandwidth
    • Removed the workspaces that consumed excessive CPU time for crypto-mining
    • Blocked the fraudulent users behind the crypto-mining from using Gitpod
    • Rolled back the ws-daemon change that broke CPU limiting and shipped the fix in the ws34 clusters
    • Blocked ACME HTTP requests to workspace ports so Let's Encrypt rate limits would not be hit again
    • Rolled out IO limiting with the ws41xl and ws41 clusters and moved traffic to them step by step
    Action items
    • Invest in test automation so that test results stop releases like this one
    • Vary the interval between traffic shifts to new clusters, with more time for larger releases
    • Add a risk assessment stage, to be automated, that governs changeset size and rollout speed of workspace cluster rollouts
    • Reduce the impact teams have on each other
    • Add review criteria that find backwards incompatible changes before pull requests are merged, and split such pull requests
    • Recommend rollback as the primary means of mitigation in the incident procedures, and look at automating it
    • Make the status page show the workspace service as down when it is, and update the playbooks
    • Keep incident communication in a single Slack channel and Google Meet
    • Put 10% of the engineering staff on the on-call rotation from May 9th and use that time on observability, alerting and stability
    Lessons

    Gitpod concluded that it should have committed to rolling back on April 11th instead of building and shipping fixes, which kept customers on degraded workspaces longer than necessary. A large release so soon after the previous one needed a risk assessment and slower traffic shifts, and backwards incompatible changes that block a rollback need to be found before pull requests are merged. Failure-free operations require experience with failure.

Check your cluster for this

These 7 cases involve Container CPU limit and Horizontal pod autoscaler. 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 exhaustion3 cases

  1. IL-0181 A traffic spike from an external community post pushed product API pods into CPU throttling under a 1-core limit, and an e-commerce product page slowed down while every pod stayed Running
    Kevin2026
  2. IL-0433 Shifting API traffic from EC2 to EKS on Fargate overloaded two CoreDNS pods and caused mass name-resolution errors
  3. IL-0028 Temporal History service latency rose because its pods were CPU-throttled while CPU usage read below 60 percent

Software defect3 cases

  1. IL-0175 Lowering a JVM pod's CPU request from 2 to 1 pushed memory past the 90% alert because the JVM treats a cgroup v1 cpu.shares value of exactly 1024 as unset and sized Reactor Netty threads from the node's 36 CPUs
  2. IL-0029 Slow user-facing services from CPU throttling on containers that used far less CPU than their limit
    Buffer2020
  3. IL-0012 CPU limits and an unpatched kernel CFS quota bug throttled multi-threaded services into stalls, failed health checks and timeouts
    Omio2020

Faulty deployment1 case

Organisation
  1. IL-0591 Gitpod workspaces in all regions became IO bound and unresponsive for days after the ws39 workspace cluster release
    Gitpod2022