Cases3 cases
1 to 3 of 3
- Symptoms
Nodes that already existed kept running, but every new node, spot or standard, on either v1.32 or v1.33, failed to initialise and could not join the cluster. Spot nodes that were preempted and recreated never came back, so services degraded progressively: background workers on spot instances, reporting services and order allocation stopped completely, and the APIs on existing nodes kept answering but could not scale for load spikes.
- Trigger
Google upgraded the GKE control plane from v1.32.x to v1.33.2 at the version deprecation deadline, although auto-upgrade was disabled on the node pools.
- Root cause
- Component
- Contributing factor
- Remediation
- Created a new GKE cluster at v1.33, the version of the forced upgrade
- Upgraded Istio to 1.27.1 for Kubernetes 1.33 compatibility
- Updated the cert-manager configuration for Kubernetes 1.33
- Migrated all production workloads to the new cluster and verified pod scheduling, DNS resolution, PVC mounting and external integrations
- Decommissioned the broken cluster
- Action items
- Configure all clusters to use the GKE stable release channel
- Implement a separate management cluster for Argo CD, monitoring and other control components (Q4 2025)
- Review spot instance usage for critical workloads and add on-demand fallback pools
- Document the SRE upgrade procedure: management cluster first, production after a monitoring period of several days
- Document a Kubernetes, Istio and cert-manager compatibility matrix
- Create an automated upgrade testing pipeline
- Reserve static IPs for quick migrations
- Pin versions of Istio, cert-manager, CSI and DNS addons
- Stay current with stable releases and regularly check GKE alerts and announcements to avoid deprecation deadlines
- Lessons
GKE upgrades the control plane at a version's deprecation deadline even when auto-upgrade is disabled, so staying inside the supported version window is how to avoid a forced upgrade. A control plane upgrade can leave existing nodes healthy while every new node fails, and spot nodes that cannot rejoin after preemption turn this into cascading failures. Relying heavily on spot instances for critical workers turned a node join failure into a progressive outage. Kubernetes upgrades have to be planned together with dependent components such as Istio and cert-manager, and without a standby cluster on the same provider there was no immediate failover; the only recovery left was building a new cluster.
IL-0230kube-proxy sync failures during a Kubernetes upgrade corrupted node iptables, and CircleCI jobs stopped startingCircleCI2023- Symptoms
On 14 March 2023 at about 18:00 UTC, communication errors rose on one CircleCI service, and pipelines for all customers began to start late until jobs did not run at all. Within an hour the errors had spread to many services and to every function of the application, including the CircleCI UI and API.
- Trigger
At about 17:40 UTC on 14 March the infrastructure team resumed the upgrade of the main production Kubernetes cluster with a changed approach for some components, after a first attempt on 13 March had been rolled back. The ongoing upgrade left kubelet and kube-proxy at mismatched versions.
- Root cause
- Component
- Contributing factor
- Detection
At 18:00 UTC engineers saw communication errors rise on one service, then job processing delays climbing and job queues backing up across several services. The kube-proxy "Sync failed" errors were found only in the analysis after the incident.
- Remediation
- Restarted every node in the cluster so each node built a fresh iptables ruleset
- Restarted a separate pool of dependencies so jobs using contexts or the machine executor ran again
- Added capacity to work through the backlog of jobs
- Restarted the RabbitMQ nodes to fix a few corrupted queues
- Action items
- Improve the Kubernetes upgrade process to limit the risk of future upgrades
- Add metrics and alerts for kube-proxy sync errors
- Evaluate ways to make the RabbitMQ infrastructure more resilient
- Lessons
No single trigger caused the incident. Because networking underlies everything in the cluster, Kubernetes upgrades carry inherent risk, and CircleCI's risk mitigation did not hold up when several events interacted.
IL-0003linkerd lost Kubernetes service discovery after an etcd reconfiguration, and restarting every linkerd instance turned failed payments into a full platform outageMonzo2017- Symptoms
At 14:10 an engineer deployed a change to a service that Monzo's current account needs to process payments, and every request to that service started to fail. Current account customers saw payment failures; the prepaid card was not affected at first because it does not use that service. The change was rolled back at 14:12, but the errors continued.
- Trigger
At 14:10 an engineer deployed a change to a service needed to process current account payments. Two weeks earlier the etcd cluster had been upgraded and grown from three to nine nodes, and one day earlier another team had scaled a new service down to zero replicas while leaving its Kubernetes service in place.
- Root cause
- Component
- Contributing factor
- Detection
Payment failures began right after the 14:10 deploy. The team rolled back at 14:12 and declared an outage internally at 14:16. At 15:13, when no service could serve requests, practically all automated alerts fired.
- Remediation
- Rolled back the payments service change (the errors continued)
- Activated internal backup processes so most customers could still use their card
- Restarted all linkerd instances (this made the outage worse)
- Restarted the three Kubernetes API server processes so replacement linkerd instances could start
- Began deploying a newer linkerd version with the fix for empty services
- Deleted the Kubernetes service that had no endpoints, which let linkerd load service discovery again
- Action items
- Fix the bug in Kubernetes that can trigger timeouts after a cluster reconfiguration
- Roll out a new version of linkerd that fixes the parsing error
- Create better health checks, dashboards and alerts for the affected components so they give clearer signals about what is wrong and prevent human error
- Improve procedures to communicate outages internally and externally as clearly and quickly as possible
- Lessons
A large failure in a distributed system can be very hard to understand, and well-meant human action can compound it, as restarting every linkerd instance did here by exposing a second incompatibility. Because Monzo deploys often and its network changes constantly, the deployment and request-routing systems have to be trustworthy. Monzo committed to publishing a similar post-mortem for any incident of this severity.
These 3 cases involve Client-side DNS resolver and cache and kubelet. 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
Breaking change in an upgrade2 cases
- Component
- Contributing factor
IL-0101After Google forced a GKE control plane upgrade to 1.33.2 at a deprecation deadline, no new node could initialise, so autoscaling and spot node replacement stopped for 15 hoursWealthy2025IL-0230kube-proxy sync failures during a Kubernetes upgrade corrupted node iptables, and CircleCI jobs stopped startingCircleCI2023
Software defect1 case
- Contributing factor
- Organisation