Cases4 cases
1 to 4 of 4
IL-0206Consul 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 primaryGitLab2022- Symptoms
On 2022-04-25 the Sidekiq Apdex (the share of background jobs that finish within a target time) dropped, and an engineer declared an incident in Slack at 15:13 UTC. Users saw intermittent slowness across GitLab.com, and asynchronous work such as pipeline creation and import and export took unusually long.
- Trigger
The Consul agent in GitLab.com's GKE pods had memory demand spikes that did not fit in the pods' 500MB memory limit, and the agent was killed again and again.
- Root cause
- Component
- Contributing factor
- –
- Detection
An engineer declared the incident in Slack at 15:13 UTC after the Sidekiq Apdex dropped; the second event was found when monitoring detected an elevated error rate at 01:21 UTC on 2022-04-26.
- Remediation
- planned at 16:13 to raise the per-user connection limit for the gitlab database user and the pgbouncer backend pools for the main database; changes were applied at 17:26 and confirmed at 17:47
- raised the pod memory limits from 500MB to 1GB so the Consul agents survive memory spikes
- Action items
- Monitor the Consul agents on GKE pods to see whether the 1GB memory limit keeps them healthy
- Investigate the Consul memory demand spikes and what can be done beyond raising the hard memory limit
- Lessons
When the local Consul agent that Rails uses for database service discovery keeps dying, Rails does not fail; it sends every query to the last known primary. What engineers saw was database saturation and slow background jobs, which pointed the investigation first at a recent pgbouncer pool change. The memory limit of the Consul agent in every pod therefore decided the load on the primary database.
IL-0035Worker nodes went NotReady after a new ElastAlert rule without memory limits used up node memoryNU.nl2019- 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.
IL-0001Cluster-wide DNS outage after CoreDNS pods were OOM-killed again and again under a burst of DNS queriesZalando2019- Symptoms
Customers of the Zalando Fashion Store got a high rate of errors on all web product pages and outfit pages for more than an hour. The errors came from the main data aggregation layer service, which runs in one of Zalando's Kubernetes clusters.
- Trigger
Calls from the aggregation layer to a single, not very important downstream service started timing out. The aggregation layer returned 404s for them, clients retried, and the resulting spike in requests became a spike in DNS queries to CoreDNS.
- Root cause
- Component
- Contributing factor
- Detection
The on-call engineer for the aggregation layer phoned the on-call Kubernetes engineer. Automatic paging did not happen because the cluster's monitoring and alerting ran inside the cluster and failed along with DNS. The Kubernetes engineer then saw that the CoreDNS pods were being OOM-killed.
- Remediation
- Raised the CoreDNS memory requests and limits by hand from 100Mi to 2000Mi
- Action items
- Introduce a more resilient DNS setup: CoreDNS fronted by dnsmasq on every node
- Improve high-level alerting from outside the clusters, so that a cluster problem is known before or at the same time as applications are affected
- Improve incident response processes and tooling so that any on-call engineer can escalate directly to other teams when automatic paging fails, for example through a chat bot
- Lessons
The Kubernetes DNS setup was far from resilient enough: a single application could take down DNS for everything in the cluster. The blast radius of one application sending more DNS queries should be limited to one node at most, ideally to single pods. Known Kubernetes DNS problems, such as Linux kernel races in conntrack handling and the ndots 5 problem, were familiar to the team and partly mitigated, but their combined effect on the DNS infrastructure was worse than the team had understood. Monitoring that runs inside the cluster was not robust enough: when the cluster's DNS broke, it could not page anyone, and recovery took longer than it should have.
IL-0468New JupyterHub student pods stuck Pending on MaxVolumeCount after a memory limit cut with node size unchangedUC Berkeley2017- Symptoms
On 20 March 2017, from some time early in the day until about 13:00, some new student servers on UC Berkeley's JupyterHub stayed in Pending forever and the students got 500 errors that kept them from logging in.
- Trigger
On 18 March at 16:30 the RAM per student was reduced from 2G to 1G to save resources while the nodes kept the same size of 26G RAM, and as a result the nodes hit the Google Cloud the limit on the number of disks per node.
- Root cause
- Component
- Contributing factor
- Detection
New student servers reported a 500 error that kept students from logging in. At 12:44 this was judged widespread, and at 12:53 `kubectl describe pod` showed the pods Pending on MaxVolumeCount.
- Remediation
- Copied the Google Container Engine instance template and changed it to spawn smaller n1-highmem-2 nodes
- Switched the managed instance group to the new template
- Grew the instance group by 30 new nodes
- Ran populate.bash so student pods would start on time on the new nodes
- Stopped the simple autoscaler
- Stopped and started affected user pods from the control panel
- Restarted the hub and proxy pods
- Action items
- Follow the status of kubernetes/kubernetes issue 24317
- Find and fix the cause of the 'too many redirects' error in JupyterHub
- Delete the older, larger nodes that are no longer in use
- Alert when any pods stay Pending for a non-negligible time
These 4 cases involve Container memory limit and Cloud block storage. 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
Capacity exhaustion3 cases
- Component
- Contributing factor
- Organisation
IL-0206Consul 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 primaryGitLab2022IL-0001Cluster-wide DNS outage after CoreDNS pods were OOM-killed again and again under a burst of DNS queriesZalando2019IL-0468New JupyterHub student pods stuck Pending on MaxVolumeCount after a memory limit cut with node size unchangedUC Berkeley2017
Configuration change1 case
- Contributing factor
- Organisation