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

Cases2 cases

1 to 2 of 2

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

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

Check your cluster for this

These 2 cases involve Container CPU limit and CoreDNS. 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 cause2