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

Cases9 cases

2 to 6 of 9

  1. Symptoms

    From 16:30 UTC on 5 August 2024, DigitalOcean's internal services could not discover the other services they depended on. Creates, event processing and the management of DigitalOcean products failed in all regions through the Cloud Control Panel and the API, while existing customer resources such as Droplets stayed online.

    Trigger

    During the rollout of a new datastore cluster in a new datacenter, a replication configuration was deployed against the datastore behind internal service discovery that gave the new datacenter, which held zero keys, 100% ownership of all keys.

    Root cause
    Component
    Contributing factor
    Detection

    Service discovery unavailability was first reported internally at 16:35 UTC, five minutes after the rollout of the new datastore cluster began.

    Remediation
    • Reverted the replication configuration and ran it against the region that had become the datastore owner
    • Applied the configuration by hand on the nodes of lagging regions and ran local data repairs
    • Cleaned up failed events and processed pending events that had not timed out
    Action items
    • Perform this kind of datastore extension inside a declared maintenance window, announced on the status page
    • Update the process documentation for this type of deployment, stage by stage
    • Automate the manual steps used in this deployment to reduce human error
    • Evaluate the internal datastore topology and whether to regionalise or layer it
  2. Symptoms

    At 18:23 UTC on 28 July 2022, PSF Infrastructure got an alert that at least one Vault container in PyPI's Kubernetes cluster was down and needed unsealing. At 18:46 UTC PyPI's backends became unresponsive, and they stayed down until 18:53 UTC.

    Trigger

    From 17:24 UTC the cloud provider automatically replaced several instances of PyPI's Kubernetes cluster because of an unknown failure. All replacements were healthy by 18:20 UTC, but the event reshuffled many pods and restarted Consul and Vault on new nodes.

    Root cause
    Component
    Contributing factor
    Detection

    An alert at 18:23 UTC told PSF Infrastructure that at least one Vault container was down and needed unsealing.

    Remediation
    • Forcefully removed the Consul pod stuck in Terminating so it was recreated and Consul could elect a leader
    • Unsealed the new Vault containers
  3. Symptoms

    On the afternoon of 28 October 2021 (13:37 PST), Vault performance at Roblox degraded and a single Consul server showed high CPU load. Consul cluster metrics showed that writes to its key-value (KV) store had a 50th percentile latency of 2 seconds instead of the usual under 300 ms. Players were not yet affected.

    Trigger

    On 27 October at 14:00, one day before the outage, Roblox enabled the Consul streaming feature on the backend service responsible for traffic routing and, to prepare for end-of-year traffic, added 50% more nodes to traffic routing.

    Root cause
    Component
    Contributing factor
    Detection

    Roblox engineers began investigating when Vault performance degraded and a single Consul server had high CPU load, before players were affected. Consul cluster metrics then showed elevated KV write latency.

    Remediation
    • Replaced one Consul cluster node on the suspicion of degraded hardware
    • Replaced all Consul nodes with 128-core machines with faster NVMe SSDs
    • Shut down the Consul cluster and reset its state from a snapshot taken at the start of the outage, with access blocked by iptables
    • Blocked external traffic, disabled all non-essential Consul use, scaled services down and lowered health check frequency from 60 seconds to 10 minutes
    • Moved the Consul cluster back to 64-core servers
    • Disabled the streaming feature for all Consul systems, which brought KV write latency back to 300ms
    • Kept the slow Consul servers from staying elected as leader
    • Redeployed the caching system and fixed its wrong scheduling data and failed deployments
    • Restarted the stopped services at the right capacity levels
    • Let players back in with DNS steering in roughly 10% steps while checking database load, cache performance and stability
    Action items
    • HashiCorp builds laboratory benchmarks and scale tests that reproduce the streaming contention
    • HashiCorp improves the design of streaming so it does not contend under extreme load
    • Compact the BoltDB database with existing BoltDB tooling
    • Remove the circular dependency between the telemetry systems and Consul
    • Extend telemetry with targeted alerts on Consul and BoltDB performance and with visibility into traffic between services and Consul
    • Run the backend in an additional, geographically distinct data center and in multiple availability zones
    • Split critical services into their own dedicated Consul clusters
    • Move data that core services keep directly in the Consul KV store to a more suitable storage system
    • Delete obsolete KV data from Consul
    • Upgrade to a Consul version that replaces BoltDB with bbolt, in Q1
    • Redesign cache deployment so the cache system can be brought up quickly from a standing start
    • Deploy Nomad enhancements that make it easier to turn up large jobs after a long period of unavailability
    • Use mechanisms for faster machine configuration changes
    • Reintroduce streaming only after a new implementation has been tested at Roblox's scale and workload
    Lessons

    Two mostly unrelated problems deep inside Consul, contention in streaming under very high read and write load and BoltDB freelist growth, were hard to diagnose, and that difficulty was the main reason the outage lasted so long. A single Consul cluster serving every workload made the impact larger, and monitoring that depended on Consul hid the cause when it was needed most. Faster hardware did not help and may have hurt, because the contention was worse on NUMA machines. HashiCorp had benchmarked streaming at a similar scale, but the problem needed both a large number of streams and a high churn rate. Restarting a platform from a fully stopped state, including warming caches, took a long time and needed tools built for bootstrapping rather than incremental change.

  4. Symptoms

    On 16 March 2020 at 14:19 PDT most of Discord's Elixir services, which handle real-time connections and chat message processing, crashed at once. Discord lost much of its real-time capacity, the failure cascaded into dependent systems, and most users could not connect for about an hour.

    Trigger

    At 14:18 the Google Cloud managed instance group autoscaler added a node to Discord's API cluster, and the TCP connection of its first announce request to etcd was reset after the request headers were sent but before the body.

    Root cause
    Component
    Contributing factor
    Detection

    At 14:21 several internal alarms fired on a drop in key metrics, along with anomaly alerts for cluster utilization, and a SEV1 incident was declared.

    Remediation
    • Restarted the lost real-time capacity and repaired the failed nodes
    • Throttled connections to Discord to help services recover
    • Stopped anti-entropy repairs on two ScyllaDB clusters so reconnecting users would not starve them of resources
    • Raised the connection throttle step by step to let more users reconnect
    Action items
    • Make the etcd clients send each announce request in a single TCP packet, so headers and body arrive together or not at all
    • Add error handling that ignores services whose key value is corrupt instead of crash-looping
    • File an upstream bug report with the Go project about net/http not checking the body against Content-Length
    Lessons

    Discord's service discovery code handled many etcd failure modes but did not expect a client to write a key without a value because of a transient network error. Go's net/http accepts a request whose body is shorter than its Content-Length header, which breaks the HTTP 1.1 specification and added a failure case nobody had anticipated.

  5. Symptoms

    On 4 February 2019 at about 02:50 UTC, Elastic Cloud customers with deployments in AWS us-east-1 lost stable access to their Elasticsearch clusters, and an increase in HTTP 5xx errors showed on the load balancer. Deployments were partially or completely unavailable until 09:28 UTC, Kibana access was disrupted for most customers in the region, and the Elastic Cloud User Console timed out when customers tried to view their deployments.

    Trigger

    A routine patching procedure in AWS us-east-1 replaced the first and second members of the three-node ZooKeeper ensemble with patched hosts between 02:25 and 02:45 UTC, following the same documented process used in the other 12 regions.

    Root cause
    Component
    Contributing factor
    Detection

    An increase in HTTP 5xx errors on the load balancer was identified at 02:50 UTC, the time the ZooKeeper ensemble lost its leader.

    Remediation
    • Restarted internal services in sweeping restarts at 03:22 and 06:00 to reduce client connection problems
    • Isolated the ZooKeeper ensemble by cutting off client connections
    • Rolled back the remaining ensemble member after its host became unstable
    • Rolled back the second ensemble member after its host became unstable
    • Rebooted the ZooKeeper hosts made unresponsive by the runc CPU softlocks
    • Re-established ZooKeeper quorum by removing client load and operator debugging, then reintroduced client load gradually
    • Increased the initLimit setting of the ZooKeeper observer layer used by the proxies
    • Scaled the proxy fleet up and out to handle the increased traffic
    • Applied a runbook that restarted the internal proxying containers and Kibana instances and set sysctl limits
    Action items
    • Reduce the dataset size carried by the ZooKeeper ensembles by over 60%
    • Reduce the number of health checks and intervals needed before a healthy proxy node joins the load balancing layer
    • Stop counting ZooKeeper connectivity in the proxy health checks once a proxy has its configuration and routes
    • Canary the rewritten proxy v2 architecture, which decouples the proxy service from ZooKeeper state, in production regions
    • Improve visibility into ZooKeeper with better logging and metrics for the ZooKeeper processes, the JVM and the container and host systems
    • Make Kibana route discovery more resilient
    • Fix the Kibana issues that amplify internal HTTP requests during availability events
    • Fix the Kibana issues that leak connections
    • Make internal monitoring agents use backoff with jitter
    • Formalize a maintenance matrix with set timeframes per region, so failures of critical services fall in non-critical times
    • Give runbooks for coordination layer maintenance a better decision criteria matrix
    • Set up a feedback loop with support leadership for incident communications through support and the status page
    Lessons

    Service metrics that reported the ZooKeeper hosts healthy were not enough to show the state of individual hosts or of the ensemble, so they gave a false signal that maintenance could continue. Because the platform depended on the coordination layer, losing its quorum caused a major service disruption in which every Elasticsearch cluster in the region saw some failures, and fixes that worked one by one fell short at the scale of the failure.

Check your cluster for this

These 9 cases involve Coordination and key-value store and Service discovery. 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 cause4

Configuration change2 cases

  1. IL-0499 Discord voice and video calls hung at Awaiting Endpoint for three hours after 17% of sessions stopped at once
  2. IL-0374 DigitalOcean creates and management actions failed globally when its service discovery datastore lost quorum

Cloud provider outage1 case

Contributing factor
  1. IL-0514 PyPI's backends stopped responding for 7 minutes as rescheduled pods could not start while Consul and Vault were down

Software defect5 cases

  1. IL-0213 Roblox was down for 73 hours because key-value writes on its single Consul cluster slowed from under 300 ms to 2 seconds
    Roblox2021
  2. IL-0271 An empty etcd service entry crashed Discord's Elixir chat nodes, and Discord was down for most users for an hour
  3. IL-0277 Patching Elastic Cloud's ZooKeeper ensemble in us-east-1 lost quorum, and hosted clusters and Kibana went unreachable
  4. IL-0587 Elastic Cloud proxies in AWS eu-west-1 flooded an overloaded ZooKeeper and ran out of memory, cutting cluster access
  5. IL-0536 Amazon SimpleDB in US East returned HTTP 500 to nearly all API calls for two hours after its nodes left the cluster

Faulty deployment1 case

Organisation
  1. IL-0276 Chef restarted two of three ZooKeeper nodes at once, and Parse.ly's real-time data stopped for about 3 hours