mirror of
https://tangled.org/evan.jarrett.net/at-container-registry
synced 2026-09-23 10:44:16 +00:00
The scanner shares a 1 GiB host with the hold, and nothing stopped it taking the whole box down with it. max_image_size was absent from the template, so production ran the 2 GiB default. Peak RSS tracks image size and a 389 MiB compressed image already reaches 561 MiB, so 512 MiB is the ceiling that fits. Sizing matters in this order: max_image_size rejects before a byte is downloaded, while MemoryMax kills mid-scan, and the hold then returns the row to pending and the restarted scanner is handed the same job again, which is a permanent crash loop on one image. If the cgroup cap is ever seen firing, lower max_image_size rather than raising it. GOMEMLIMIT is soft: the runtime collects harder to respect it and never fails an allocation to honour it. With no cgroup cap the kernel picks its own OOM victim, and the other large process on that host is the hold, so the scanner's overshoot could kill the service it reports to. CPUWeight and IOWeight, because no unit here set any scheduling directive: a scan finishing a minute later costs nothing, a hold that cannot answer a pull costs a user. Weights apply only under contention, so the scanner still uses the whole box when nothing else wants it. workers drops to 1. Proactive dispatch was depth-one hold-wide until this release so the second worker never received anything, and now that it can, two concurrent scans of a node:22-class image need 687 MiB against a host this size. Raise it with MemoryMax and the host together. Note the cgroup ceiling still wants rechecking: it was sized from measurements taken with Grype disabled, and the vulnerability database's resident pages count against MemoryMax even though GOMEMLIMIT cannot see them. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01U1Km3N3uUmeGaj7VbaM8PF