Incident Library

IL-0462 Shopify · 2021-10-21 (published)kubernetesgcpdatabase

Some MySQL pods on Shopify's GKE clusters took up to 30 minutes to start, slowing instance replacement

KateSQL runs MySQL as Kubernetes pods on GKE across several Google Cloud regions. Earlier in 2021 some MySQL pods began taking far longer than others to start and stop, slowing the instance replacement procedure. As a first mitigation the team cordoned older nodes, replaced MySQL instances so their pods moved to new nodes added by the GKE autoscaler, and drained the old nodes, which improved performance on the new pods.

A deeper analysis traced the slowness to memory allocation during InnoDB buffer pool initialisation, which spent its time in the kernel's mem_cgroup_commit_charge. Affected nodes had about 50K memory cgroups, which pointed to a cgroup leak: charging each page may have to traverse many cgroups. Bug reports, an lwn.net article and a Linux kernel mailing list thread matched the problem, and Google's kernel engineers confirmed it was another side effect of reparenting slab memory on cgroup removal in the Linux kernel memory cgroup controller. Writing 1 to /sys/fs/cgroup/memory/kubepods/memory.force_empty on an affected node brought memory cgroups down to about 1800, and a restarted MySQL pod then initialised an 80G InnoDB buffer pool in five seconds.

Shopify and Google weighed several workarounds: rebooting or cordoning nodes found by monitoring /proc/cgroups, a cron job that drops slab and page caches, moving short-lived pods to a dedicated node pool, a memory.force_empty call in the preStop hook of short-lived pods, and upgrading to COS 85, which has the upstream fixes, with the move from GKE 1.16 to 1.18 expected to bring Linux kernel 5.4 with the relevant fixes. Since a GKE upgrade was due, the team created new GKE 1.18 clusters and started creating MySQL pods there, and after several weeks buffer pool initialisation and query performance stayed consistent.

Severity
–
Scope
KateSQL instance replacement slowed: MySQL pod creation took 10 to 30 minutes, and affected pods also served slower queries
Users affected
–
Region
–
Time to detect
–
Time to resolve
–

Symptoms

In 2021 Shopify's KateSQL, a database-as-a-service platform that runs several hundred production MySQL instances on GKE, found that some MySQL pods started and shut down much more slowly than similar pods with the same data set. Instance replacement, the procedure that creates a new MySQL replica pod and stops the old one, showed pod creation times ranging from 10 to 30 minutes, which held up maintenance such as configuration changes and upgrades.

Two pods with the same CPU, memory, storage and data set differed widely: katesql-n4sx0 took 2120 seconds to initialise and 1104 seconds to start, while katesql-jxijq took 74 and 17 seconds. The slow pods also became gradually slower at queries, with more slow queries among those that used temporary memory tables.

Nodes that had been running for a few months performed worse than newly provisioned ones, although kubelet, kernel and Container-Optimized OS versions were the same. Storage was ruled out. During InnoDB buffer pool initialisation mysqld used about 100% of one CPU, strace showed each mmap() call taking around 100 ms to allocate chunks of about 128MB, and a perf flame graph showed the jemalloc allocator spending most of its time in the kernel function mem_cgroup_commit_charge.

slabtop showed a dentry cache of around 20GB on a node with about 64 pods, and dropping it with echo 2 > /proc/sys/vm/drop_caches brought an immediate improvement like a node restart, although the team confirmed that its case was not the one described in a sysdig post it had followed. An affected node had approximately 50K memory cgroups, far more than a good node.

Symptom Slow pod startup or shutdownHigh latency

Root cause

Trigger
–

Detection

KateSQL's instance replacement operations showed inconsistent MySQL pod creation times, and the team then measured the mysql-init container and MySQL startup times across pods.

Remediation

Action items

–

Lessons

The investigation was one of the longest the Database Platform group had carried out, because of the nature of the problem, how hard it was to reproduce and the lack of an established method to follow; once the cause was known, there were several ways to fix it.

Sources

Related cases

Check your cluster for this

kubegap audits a Kubernetes cluster for conditions like the ones in this case, Linux kernel, Node operating system image, Database among them, read-only, from Claude Code or Codex. Its checks cite public reports like this one.

For AI tools and scripts

The API needs no key. The MCP server offers search_incidents, get_incident, list_incidents, get_topic and vocab; both are explained on API and MCP.