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

Cases6 cases

1 to 5 of 6

  1. Symptoms

    At 13:42 the RootVolUtilisation-Critical alert fired in the high-priority alerts channel. At 14:03 a user reported image pull errors with the message "no space left on device".

    Trigger

    Upgrading the EKS Terraform module to version 18, which changed the node launch template, and draining workloads onto the new nodes it created.

    Root cause
    Component
    Contributing factor
    Detection

    The RootVolUtilisation-Critical alert fired in the high-priority alerts channel at 13:42, and a user reported "no space left on device" image pull errors at 14:03.

    Remediation
    • Uncordoned the old default node group and drained the new nodes to move workloads back
    • Identified the launch template change that cut the root volume to 20 GB and applied a fix on the manager and live clusters
    • Drained the old node group onto the fixed nodes
    Action items
    • Update the runbook to compare launch template changes during an EKS module upgrade
    • Create a test setup that pulls images of different sizes, like live
    • Update the RootVolUtilisation alert runbook to check the disk space configuration
    • Scale CoreDNS dynamically based on the number of nodes
    • Investigate whether IPv6 can solve the IP prefix starvation problem
    • Add drift testing to identify when a terraform plan shows a change to the launch template
    • Set up logging for the CNI and ipamd logs and alerts on errors related to IP prefix starvation
    Lessons

    The write-up lists review actions rather than lessons. They aim at two gaps: the launch template changes brought by a module upgrade were not compared or drift-tested before rollout, and there were no CNI or ipamd logs or alerts to show the IP prefix starvation the team suspected during the drain.

  2. Symptoms

    Right after a pull request to the infrastructure-as-code repository was merged, every API endpoint of one InfluxDB Cloud production cluster began returning 404 errors. Writes and reads failed alike: no one could collect data, scheduled tasks failed to run and external queries did not work.

    Trigger

    A merged pull request whose rendered YAML added a new Argo CD Application and AppProject that an automation error had named app01-cluster01, the name of the existing production Application, instead of app02-cluster01; reviewers did not notice the app01 and app02 difference.

    Root cause
    Component
    Contributing factor
    Detection

    Monitoring and alerting did not detect the issue right away, so the team's first response was to try to roll the change back rather than plan a recovery. The write-up does not say how the team found out.

    Remediation
    • stopped the revert of the merged pull request
    • restored the etcd metadata cluster
    • recreated the missing Kubernetes objects so the retained PersistentVolumes became available, then recreated the StatefulSets
    • restored the Zookeeper volumes from an hourly Velero backup
    • rebuilt the Kafka StatefulSet one pod at a time with health and readiness checks disabled
    • accepted writes into the Kafka write-ahead log and scaled up the write path with more replicas and higher memory requests and limits
    • recreated the storage pods, which downloaded data from object storage, reindexed it and replayed the write-ahead log
    • re-enabled Argo CD, queries, dashboards and scheduled tasks, restored replica counts and ran final QA checks
    Action items
    • Write runbooks for restoring state when Kubernetes objects such as PersistentVolumeClaims are deleted but the data on the underlying volumes is preserved
    • Set every volume in every environment to retain data when its PersistentVolumeClaim is deleted
    • Improve the process for handling public-facing incidents
    • Store generated YAML as one object per file, so an overwrite of an existing object shows up as such in review
    • Detect duplicate objects when generating YAML and warn before review, treating objects with the same group, namespace and name as the same even when the apiVersion string differs
    • Add the Argo CD Prune=false annotation to all stateful resources and to Namespace objects managed by Argo CD
    • Set FailOnSharedResource=true on Argo CD Applications so Argo CD fails before changing an object another Application manages or managed
    Lessons

    The biggest gap was that monitoring did not notice the deletion quickly, which pushed the team toward a reflex rollback; in a stateful system a revert can create a new, empty instance instead of bringing the old one back. Retained volumes and clients that retry writes are what kept data loss at zero. Rendering many objects into one file let an overwrite of an existing object look like an addition, so generated configuration needs one object per file and duplicate detection that compares objects the way Kubernetes does. Stateful resources need protection from pruning, and that protection must cover their Namespace too, or deleting the namespace removes everything inside it.

  3. Symptoms

    After the switch to Traefik v2, functional tests indicated that everything was fine, and this was reported on Slack at 08:44 UTC. The first sign of trouble came at 09:26 UTC, when a developer reported a high count of HTTP 307 redirects, especially on the Okta service. At 09:32 UTC the team learned that the online booking system was down.

    Trigger

    At 08:22 UTC the AWS load balancers were updated to send requests to the new Traefik v2 reverse proxy as part of the migration away from Traefik v1.

    Root cause
    Component
    Contributing factor
    Detection

    A developer reported a high count of HTTP 307 redirects, in particular on the Okta service, at 09:26 UTC, 64 minutes after the change; six minutes later the team was told the online booking system was down. The functional tests run after the switch had not caught it.

    Remediation
    • Rolled back the switch to Traefik v2, putting rollback ahead of investigation because of how critical the booking system is
    Action items
    • Consider how critical announcements can be made more visible
    • Consider whether the ALBs used for testing should have been shared with the teams so they could test their own scenarios
    Lessons

    Cloud Engineering cannot test every application scenario on its own, even after testing its own applications for weeks. A header that changes value behind a new ingress controller, here x-forwarded-proto going from https to http, can break an authentication flow while basic functional tests still pass. DFDS asks whether diffing request headers before and after the migration would have shown the problem in advance.

  4. Symptoms

    On 25 August 2021, skyscanner.net was unavailable and the Skyscanner mobile apps could not work, for travellers and business partners everywhere at the same time. The full global outage lasted four and a half hours.

    Trigger

    A peer-reviewed change to a rarely changed root-level file of the cells templating configuration, intended as a no-op, that left out the {{ }} delimiters; it was submitted around 15:30 GMT, merged to master and rolled out automatically to every region at once.

    Root cause
    Component
    Contributing factor
    Remediation
    • restored the correct configuration for each cluster and let Argo CD reconcile the cluster back to it
    • restored services through the backup and restoration process
    • brought one region back first with the critical services and served all traffic from it from around 20:30 GMT
    • restored and verified the remaining regions and non-critical services over Thursday and Friday
    Action items
    • Avoid global configuration deploys, including rare change paths like this one
    • Treat templated configuration as code and add testing and linting
    • Plan and wargame more drastic failure scenarios in runbooks
    • Verify backup and restore processes, including access to the backups and the loss of a region
    • Refactor runbooks so they are clear and, where appropriate, idempotent for a stressed engineer in the early morning
    • Reconsider how much configuration is templated across regions, weighing configuration drift against automated global rollout
    Lessons

    Global configuration changes had been prevented in many cases, but not in this rarely used path. Configuration that gains templating and logic has become code and needs tests and at least linting. The failure scenarios and runbooks were not pessimistic enough, a backup only counts once it has been restored, and runbooks need care so they work for a stressed engineer at night. Automation that templates configuration across regions trades drift for the risk of rolling one mistake out everywhere. An experienced incident commander who kept the response calm and blameless made a large difference.

  5. Symptoms

    On Friday 19 July 2019 the Grafana Cloud Hosted Prometheus service, which is built on the Cortex project, was down for 26 minutes. New error-budget-based Prometheus alerts paged the on-call engineer within 4 minutes of the start.

    Trigger

    An engineer created a new dedicated Cortex cluster for a large customer. Its configuration did not include the new pod priorities, so all its pods got the default medium priority, and the Kubernetes cluster did not have enough free resources to fit it.

    Root cause
    Component
    Contributing factor
    Detection

    New error-budget-based Prometheus alerts paged the on-call engineer within 4 minutes of the start of the outage.

    Remediation
    • Scaled up the underlying Kubernetes cluster to fit both the new and the production Cortex clusters
    • Diagnosed and fixed the out-of-memory errors in the authenticating reverse proxies in front of Cortex
    Action items
    • Give the production ingesters the high priority class, which should have been done before medium became the default
    • Have more people review changes to configuration that is global to the cluster
    • Require a design document for every configuration change outside a namespace
    • Automate the sizing of the frontend authenticating reverse proxy so it does not run out of memory under overload
    • Investigate the default backoff and scaling behaviour of Prometheus to prevent a stampeding herd of retries
    Lessons

    Medium should not have become the default priority until the production ingesters had the high priority, and that designation should have reached production sooner. The change was considered too minor for a design document and was only discussed in a GitHub issue; cluster-global configuration needs more scrutiny. On the positive side, once Cortex had enough capacity it recovered by itself, and Grafana Loki helped confirm that the ingesters exited gracefully.

Check your cluster for this

These 6 cases involve Argo CD and Configuration templating. 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

Configuration change6 cases

  1. IL-0019 An EKS Terraform module upgrade shrank node root disks from 100 GB to 20 GB and image pulls failed with no space left on device
  2. IL-0009 A duplicated generated name made Argo CD replace the InfluxDB Cloud production Application and delete the whole production environment
  3. IL-0111 Switching the main Kubernetes ingress controller from Traefik v1 to v2 stopped X-Forwarded headers being passed, which broke the Okta login flow for every service using Okta and stopped DFDS online bookings for over an hour
    DFDS2021
  4. IL-0010 A templating change that dropped its {{ }} delimiters made Argo CD delete all 478 Skyscanner services in every region
  5. IL-0004 A new default pod priority let a new Cortex cluster preempt every production ingester in a cascade, taking Grafana Cloud Hosted Prometheus down
  6. IL-0061 A Terraform pull request merged out of order deleted a production GKE cluster, and recreating it deleted a second one