Root cause confirmed: each scrape fetches time series for every metric
descriptor of every configured project concurrently, with no limit — one
goroutine + HTTP request + JSON decode per descriptor, per project. When
google.projects.filter (or a long google.project-ids list) resolves to
many projects, this spawns far more concurrent Monitoring API requests than
a memory-constrained pod can service at once, leading to OOM kills. This is
worse in containers specifically, since GOMAXPROCS reports the host's
vCPUs rather than the container's cgroup CPU limit — far more goroutines get
scheduled than the pod's actual quota, and CPU throttling stalls many of
them mid-decode with their buffers unfreed.
Root cause confirmed: each scrape fetches time series for every metric
descriptor of every configured project concurrently, with no limit — one
goroutine + HTTP request + JSON decode per descriptor, per project. When
google.projects.filter(or a longgoogle.project-idslist) resolves tomany projects, this spawns far more concurrent Monitoring API requests than
a memory-constrained pod can service at once, leading to OOM kills. This is
worse in containers specifically, since
GOMAXPROCSreports the host'svCPUs rather than the container's cgroup CPU limit — far more goroutines get
scheduled than the pod's actual quota, and CPU throttling stalls many of
them mid-decode with their buffers unfreed.