Cases5 cases
1 to 5 of 5
IL-0063VPN outage after recreating a Redis StatefulSet restarted the whole Redis cluster without readiness checksAdGuard VPN2025- Symptoms
The day began with an alert that several instances of the Redis cluster were running out of disk space. That part was fixed quickly. The outage came an hour later: right after the Redis StatefulSet was deleted and recreated at 8:10 UTC, Kubernetes restarted every Redis pod within about five minutes, and problems started to appear.
- Trigger
To make Git match the volumes that had been resized by hand, the Redis StatefulSet was deleted with orphan (non-cascading) deletion and recreated with the new storage template; Kubernetes reconciled the new spec by restarting the entire Redis cluster.
- Root cause
- Component
- Contributing factor
- Detection
An alert about Redis instances running out of disk space started the work; the outage itself showed up as backend errors about Redis connections right after the StatefulSet was recreated.
- Remediation
- made the Redis masters forget obsolete node identities, reset the affected replicas and rejoined them, then waited for replication to catch up
- identified the component that was actually running out of memory, scaled the backend service and raised memory limits for that component
- temporarily relaxed probes so backend instances took traffic immediately instead of flapping between ready and not ready
- reverted the temporary workarounds at 10:00 UTC
- Action items
- Add startup probes so a Redis pod is not marked ready until its dataset is loaded
- Build an own control plane for Redis that handles restarted pods stuck to an old master address
- Reduce dependence on the single Redis cluster: move some important data to other stores, such as a separate Redis cluster per server, and use Kafka for some backend components
- Lessons
The disk resize was not the problem; the cleanup afterwards was. An immutable field pushes operators toward deleting and recreating the controller, and that can set off a full reconcile. Startup and readiness probes are what slow a rolling restart down to a safe pace; without them a distributed store restarts in the most fragile way. Recovery plans must expect a cluster to heal slowly, and dependent services need to degrade gracefully while it does.
IL-0197Moving a three-node Elasticsearch StatefulSet to new persistent volumes split the cluster in two, because the Helm chart hardcoded cluster.initial_master_nodes to elasticsearch-0Palark2021- Symptoms
After the last old Elasticsearch pod, elasticsearch-0, was deleted and came back on a new, empty persistent volume, `_cat/nodes` run inside that pod listed a single node: elasticsearch-0 itself, marked as master. The same command run inside elasticsearch-1 listed the other five nodes, elasticsearch-1 to elasticsearch-5, with elasticsearch-2 as master.
- Trigger
Deleting the elasticsearch-0 pod and its PVC so that it restarted on an empty volume of the new StorageClass.
- Root cause
- Component
- Contributing factor
- Detection
The engineer running the migration checked `_cat/nodes` after elasticsearch-0 restarted and saw it alone in a cluster of its own.
- Remediation
- scaled the three deployments of workers writing to Elasticsearch down to zero
- listed elasticsearch-0, elasticsearch-1 and elasticsearch-2 under initial_master_nodes in the elasticsearch ConfigMap and removed the cluster.initial_master_nodes environment variable from the StatefulSet
- saved and deleted the elasticsearch discovery Service and deleted the PVC of elasticsearch-0 while the rolling update ran
- set initial_master_nodes to elasticsearch-3, elasticsearch-4 and elasticsearch-5, created an empty PVC for elasticsearch-0 and deleted all six pods
- recreated the discovery Service from the saved manifest, after which the six nodes formed one cluster with every index green
- Action items
- Restore the original initial_master_nodes values in the ConfigMap and restart all pods again
- Move all shards to nodes 0, 1 and 2 and scale the cluster down from six nodes to three
- Commit all the manual changes to the repository
- Lessons
A setting that only matters when a cluster first starts, such as Elasticsearch's cluster.initial_master_nodes, can sit in a Helm chart template rather than in the ConfigMap that was reviewed. When a pod named in it starts with an empty data directory, it can bootstrap a new cluster beside the existing one. The author's conclusion is that a migration plan like this one breaks on any surprise and needs a plan B ready. Before running it in a more important environment, rehearse it in a test environment configured like production, and either schedule downtime or move the load to another cluster: stop the writers, take a fresh backup, then move the data.
IL-0196Adding a second Redis replica and lowering memory limits in one RedisFailover change restarted the only Redis pod that held data, and Sentinel promoted the empty new replica, erasing the dataPalark2020- Symptoms
Right after an updated RedisFailover resource was rolled out, the large Redis database lost all its data and the service went down; the data had to be restored from a backup taken just before the change.
- Trigger
A RedisFailover change that raised the number of Redis replicas from one to two and, in the same rollout, lowered the containers' memory requests and limits from 22 GB to 19 GB.
- Root cause
- Component
- Contributing factor
- Remediation
- restored the Redis data from the backup prepared before the rollout
- Action items
- Report the readiness probe flaw to the Redis Operator project and test the developers' fix
- Reconsider the use of the Spotahome Redis Operator
- Clean up the Redis databases and fix the application code that created the excess keys
- Consider Redis built-in clustering and sharding
- Lessons
Changing the replica count and the pod resources in one rollout turned a seemingly harmless change into a rolling restart of the only pod with data while the new replica was still empty. A readiness probe that only checks that Redis answers a ping does not tell whether a replica has finished syncing. Operators for critical stateful components need to be evaluated for maturity before production use, and the dump.rdb file should be backed up before any change to the Redis cluster.
IL-0193A GCP persistent disk degradation took down a Cassandra StatefulSet whose OrderedReady policy blocked recovery, and Metrictank could not reconnect to the recreated pods, causing a 23-hour Graphite query outageGrafana Labs2019- Symptoms
An alert fired because some Metrictank instances could not drain their write queue, which meant they could not write to Cassandra. Google had not yet published an incident, but a team member's Discord server, also hosted on GCP, was down, which pointed at GCP; Google confirmed an SSD persistent disk incident about 90 minutes after it began.
- Trigger
A Google Cloud incident in which SSD persistent disks performed so poorly that many I/O operations failed for an extended period.
- Root cause
- Component
- Contributing factor
- Detection
An alert that Metrictank write instances could not flush their write queue to Cassandra. Error rates alone rose too slowly to notice quickly, because most queries were served from memory.
- Remediation
- Added compute nodes hoping new nodes could attach the disks, which did not work
- Deleted and recreated the Cassandra StatefulSet with an updated pod management policy, so all pods but one started
- Raised Kafka topic retention to avoid data loss during the long downtime
- Temporarily added nodes so Metrictank restarts were not slowed by CPU starvation
- Restarted all Metrictank instances, which took more than 20 hours, so they connected to the new Cassandra IPs
- Action items
- Re-instantiate the gocql connection in Metrictank when it is detected dead, so it reconnects even when all Cassandra IPs change
- Fix the Metrictank write-queue deadlock by updating an internal data structure with atomics instead of a lock
- Lessons
An OrderedReady StatefulSet cannot recover past a single pod whose volume will not attach; when every pod is down, the ordering that protects normal start-up blocks the whole cluster. A client that learns peer addresses only from live peers needs a way to go back to the service name when all peers are replaced at once. A long-tolerated bug with a config workaround can surface at the worst time; this one turned out to have a simple fix. Writing incoming data to a Kafka write-ahead log first meant all data could still be ingested after recovery, and Kafka on non-SSD disks escaped the disk incident. With both Metrictank bugs fixed, the team expects a similar event to take less than 3 hours to recover from instead of 23.
IL-0518gitlab.freedesktop.org on GKE ran short of volume space and a planned 30-minute storage upgrade became a 4-hour outagefreedesktop.org2018- Symptoms
Shortly after 9am UTC on 17 July 2018, the disk space of the GitLab cluster behind gitlab.freedesktop.org was critical, and some API requests were failing because of the shortage. The administrator first learned of the failure when people mentioned it on IRC.
- Trigger
Many recently created forks of Mesa, each about 2.1GB, filled the disk space of the GitLab cluster.
- Root cause
- Component
- Contributing factor
- Detection
People mentioned the failure on IRC. Monitoring and alerting on disk usage and API error rate had not been set up yet.
- Remediation
- Dropped all inbound traffic to GitLab at the firewall except from the administrator's IP
- Took a manual backup by streaming tar over SSH to an encrypted partition on a local machine
- Snapshotted all GCE disks behind the PersistentVolumes
- Copied the data from the old disk snapshots to new enlarged volumes through a temporary GCE VM
- Re-did the copy into new empty volumes with the correct directory structure and checked repositories, users and workflows
- Restored public access to GitLab
- Action items
- Set up monitoring, logging and alerts
- Find ways to communicate outages much better; this one was announced only on IRC, and the lists were not told when it dragged on
- Use the Cloud console clients instead of the slow Cloud Console web UI
- Add more GitLab administrators, ideally someone familiar with Kubernetes deployments
- Move from the single Omnibus container to GitLab's cloud native deployment with one container per service
- Move storage to resizeable volumes or to Google Cloud Storage
- Lessons
The backup step alone used up the outage window; backups had grown along with the disk problem, and a test run before announcing the window could have measured it. The changes had been tested on a scratch cluster, but not exactly as run, and tests of steps such as disk snapshots could have been more realistic. A single GitLab administrator who was new to Kubernetes was a single point of failure. Keeping at least three copies of the data from the first destructive step meant no data was lost.
These 5 cases involve Persistent volumes and stateful sets and Database. 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 cause5
Configuration change1 case
- Contributing factor
- Organisation
Operator error1 case
- Contributing factor
- Organisation
Software defect1 case
- Contributing factor
- Organisation
Cloud provider outage1 case
- Contributing factor
- Organisation
Capacity exhaustion1 case
- Contributing factor
- Organisation