Cases2 cases
1 to 2 of 2
IL-0251Most of Slack's HAProxy load balancers routed to a stale, shrinking set of webapp backends and served HTTP 503 errorsSlack2020- Symptoms
At 4:45pm Pacific on 12 May 2020, Slack was alerted that it was serving more HTTP 503 errors than normal. A subset of the webapp fleet was under heavy load while the rest of the webapp instances were not.
- Trigger
At the end of the US business day the webapp tier began its usual scale-down, and autoscaling terminated the oldest instances first, which were the only backends left in most HAProxy instances' state.
- Root cause
- Component
- Contributing factor
- Detection
An alert for more HTTP 503 errors than normal. The alerting meant to catch stale HAProxy state was not working.
- Remediation
- Did a rolling restart of the HAProxy fleet
- Action items
- Move all ingress load balancing from HAProxy to Envoy Proxy, with endpoint discovery through an xDS control plane
- Lessons
The alerting for this exact failure had stopped working, and nobody noticed because the HAProxy stack had run for a long time without needing changes, so few engineers worked with its monitoring and alerting. A slot limit that had been ample a few months earlier was reached after pandemic-driven growth and one large autoscaling event.
- 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.
These 2 cases involve Service discovery and Coordination and key-value store. 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
Software defect2 cases
- Contributing factor