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

Cases6 cases

3 to 6 of 6

  1. Symptoms

    One evening the platform team that runs SCHIP, Adevinta's internal runtime platform on Kubernetes, was paged because some DaemonSets were failing. Checking the pod status showed this error from the network plugin: name="aws-cni" failed (add): add cmd: failed to assign an IP address to container

    Trigger

    Not stated for the first page. It came in June, during the migration from SCHIP's kube-aws-based clusters to EKS-based clusters; the write-up mentions spikes of pods, such as a job that goes rogue or failing jobs that keep their IPs, as ways a cluster can run out.

    Root cause
    Component
    Contributing factor
    Detection

    A pager alert that some DaemonSets were failing. The on-call engineer checked the pod status and found the aws-cni error about failing to assign an IP address.

    Remediation
    • Rolled out VPC CNI custom networking with a secondary CIDR to the smaller clusters from late August
    • Paused the EKS migration in September while available IPs were very low
    • Rolled out custom networking to the rest of the fleet
    • Added the --reserved-enis parameter to the Karpenter deployment
    Action items
    • Use VPC CNI custom networking with a secondary CIDR across the whole fleet
    • Make Karpenter account for custom networking with the --reserved-enis parameter
    Lessons

    For a platform team, the VPC CNI is not ready to scale in production without time spent on capacity planning, and every option has its pros and cons. For large clusters started today, IPv6 is the cheaper and more future-proof option. Do not assume that what works in small clusters will keep working when they grow.

  2. Symptoms

    One Monday morning the author opened the Prometheus dashboard to check a Kubernetes cluster for alerts and could not reach it. The Prometheus pod was in CrashLoopBackOff: kubectl get pods showed it 1/2 ready with 950 restarts over 3d20h on worker3.

    Trigger

    After start, the Prometheus time series count rose to 2,162,256 within five minutes and its memory use filled the 8GB host.

    Root cause
    Component
    Contributing factor
    Detection

    The author found it on a Monday morning when the Prometheus dashboard, opened to check the cluster for alerts, could not be reached.

    Remediation
    • removed most of the unnecessary settings from the Prometheus ConfigMap, after which the container stopped crashing
    Action items
    • Set appropriate resource requests and limits on the Prometheus pod
    • Reduce unneeded metrics by adjusting scrape targets or scrape interval
    • Estimate Prometheus memory needs, provide dedicated hosts with a node label such as deploy-topology: Prometheus, and pin the Prometheus pod to them with a nodeSelector
    Lessons

    Exit code 137 together with an OOM event in the kubelet log means the kernel killed the container, not kubelet. Under node memory pressure the kernel kills the process with the highest score, and kubelet derives each container's oom_score_adj from the pod's QoS class: a container without a memory request in a pod where another container has one ends up Burstable with a score near 1000, so it is killed first. In a large cluster, Prometheus memory needs to be estimated from the expected series count and requested explicitly.

  3. Symptoms

    Shortly after a round of changes, loveholidays saw connectivity problems and raised error rates on its aggregation service. The service is a proxy between two other services of more than 100 instances each, handles over 10,000 requests per second continuously and can spike to four times that.

    Trigger

    Three changes together: a change in service architecture, halving the RAM of the nodes that run the aggregation service, and sharding a downstream service, which doubled the number of connections to track.

    Root cause
    Component
    Contributing factor
    Detection

    Rising error rates and climbing connection reset errors in HAProxy, then node_exporter conntrack metrics compared with their limit.

    Remediation
    • moved the aggregation service to nodes with more RAM
    • limited the number of aggregation service pods per node
    Action items
    • Alert when conntrack table use goes above 75%, with (node_nf_conntrack_entries / on (pod) node_nf_conntrack_entries_limit / on (pod) group_right kube_pod_info) > 0.75
    Lessons

    The conntrack limit is tied to node memory, so resizing a node pool silently resizes the connection table, and on GKE the ratio did not match the commonly cited formula. A high-traffic proxy on small nodes can exhaust it, and the symptoms are connection resets and timeouts, so conntrack use needs its own metric and alert.

  4. Symptoms

    After Civis released its new script infrastructure on Kubernetes internally in September 2018, developers reported that kubectl commands were slow, and users intermittently could not start notebooks and services.

    Trigger

    Migrating clients' Python, R and container scripts from the in-house Bocce system to Kubernetes (the project called Croquet) pushed the cluster to about 290 EC2 instances under a large script load.

    Root cause
    Component
    Contributing factor
    Detection

    Developer reports of slow kubectl commands and user reports of notebooks and services failing to start, then high CPU on the master nodes.

    Remediation
    • moved internal users back to the old Bocce infrastructure
    • resized the three master nodes from m4.large to m4.4xlarge
    • changed the Datadog setup so per-node agents no longer polled the API server for service metadata
    • raised max-requests-inflight for non-mutating requests from 400 to 1200
    • grew the etcd EBS volumes from 20 to 100 GB (100 to 300 IOPS)
    • switched client scripts from the ClusterFirst DNS policy to Default
    Action items
    • Upgrade etcd from 2.2.1 to 3.x once Kops supports a safe migration
    • Solve the in-cluster DNS timeouts so client scripts can talk to other workloads in the cluster
    Lessons

    Kubernetes can reach thousands of nodes only after tuning, and third-party DaemonSets are a common cause of control plane load: an agent on every node that polls or watches the API server multiplies with the cluster size. Datadog, kube2iam and the fluentd metadata filter all showed this. A small configuration change often fixes it, but finding it took load testing and the API server access logs.

Check your cluster for this

These 6 cases involve VPC subnet or pod address range 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 cause1