Build1 distinct publisher2 min readPublished
A prebuilt binary carries the ABI floor of the machine that built it, and the loader enforces that floor before it reads a line of your configuration. On one two-node cluster that was the first of three unrelated outages.
The Engineer · Build desk

Compiled by The EngineerSomething wrong?How this is made
A versioned symbol reference is resolved when the program loads, before any of its own code runs. That is why the crash loop happened before the orchestrator read a single line of configuration [1]. Correct config was never reachable.
So "official release binary" is a claim about the machine that built it, and it transfers only if the receiving host's glibc is at least as new as the build host's. The controller node was newer and took the release without complaint [3]. The second node runs Ubuntu 20.04, ships glibc 2.31, and could not load the same file [2]. One host set the floor for every prebuilt artifact in the cluster [6].
The fix required a rebuild on a matching host, not a configuration flag. The `rust:1-bullseye` image is Debian 11 with glibc 2.31, so a binary compiled there loads on the 2.31 node, with `protobuf-compiler` installed in the same container invocation [4][5]. Cheap once, permanent after: upgrades of that orchestrator on that host are now a compile rather than a copy [7].
The cgroup failure was arithmetic. On this Virtuozzo container `cgroup.subgroups_limit` reads 100, and a directory count under `/sys/fs/cgroup/systemd` returned 101 [9][10]. At the cap, no new unit starts regardless of the binary. Of those 101 directories, 96 held no processes at all [12]. Remove them and the live count is 5, leaving 95 slots free [20]. The author's own repeated logins to debug the box had been spending the budget he needed to start the service [12].
The third failure is the one worth copying into review notes. The release added a startup path that registered each service, and it treated services pinned to the controller's own hostname as remote placeholders, so the controller waited indefinitely for a node that was itself, without adopting the already-running containers or registering their routes [15]. According to the author, this is the same blind spot as a redeploy bug he fixed in the previous instalment: the controller's self-registration matching a placement lookup that should exclude it, now in a later code path his fix did not cover [16]. Pulling the pins out of config did not undo it, because the placeholder registration had persisted a stop-mark that the reconciler still honoured [17], and the release had also dropped the CLI `start` verb [18].
Each of the three failures traced to a different root cause [19]. What they do share is sequence: the loader runs before systemd and systemd runs before the reconciler, so each layer failed with an error naming itself rather than the upgrade that triggered it.
Ranked by verification strength, evidence, and original report placement.
After the author copied the official release binary to the second node, the service went into a crash loop with the error: /usr/local/bin/orca: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.32' not found (required by orca).
That node runs Ubuntu 20.04, which ships glibc 2.31, while the official builds are linked against something newer, so the binary simply cannot load there.
The controller node is newer and took the release fine; the old node could not.
The fix was to stop using the official binary on that node and build one linked against its glibc, by running cargo build --release inside a container after installing protobuf-compiler.
The image used was rust:1-bullseye, which is Debian 11 with glibc 2.31, so the resulting binary runs on the 2.31 node.
The author's stated lesson: your oldest host sets your glibc floor for every prebuilt binary, so either build for that floor or retire the host.
Distinct publishers with included, body-backed reporting in this cluster.
dev.to
1 article · August 28, 2026
Follow any of these and your For You feed starts watching them — no settings page required.
product
AI writes the Dockerfile, and the pipeline is still checking the app code1 distinct publisher
build
A 28-host Debian 12 cutover, and the 02:13 failure Ansible could not have prevented1 distinct publisher
build
Ubuntu's Rust migration lands in the plumbing, and sudo-rs is where fleets will feel it1 distinct publisher
build
Debian 13 cleans /tmp, and Plex's EAC3 transcoding dies ten days later1 distinct publisher
Evidence-backed comparisons of source perspectives and observed adoption signals. Read the methodology
Which Builder, Operator, and Investor concerns the observed source mix emphasized—not a truth score.
Evidence, demonstrated adoption, hype gap, incentives, and confidence are assessed independently, each on its own current evidence. How these are measured.
Checkable, but nobody has checked it
Each failure arrives with the artifact that proves it: the loader's own GLIBC_2.32 line, status=219/CGROUP, a subgroups_limit of 100 against a directory count of 101, docker ps disagreeing with the orchestrator's own status output. That is unusually falsifiable for a war story. What it is not is verified — dev.to is the sole account, the orchestrator appears only as "orca" with no release version, and no maintainer, distribution or hosting vendor has confirmed a line of it.
One operator, two nodes
The blast radius is two personal nodes and one end-of-life Ubuntu box. Nothing suggests the placeholder regression bit anyone else, and the only mark left outside this operator's shell history is the issue he filed himself. The underlying mechanisms — a glibc floor inherited from the build host, a Virtuozzo subgroup ceiling — apply to a great many machines, but broad applicability is not evidence of broad incidence.
Sold as one bad afternoon
If anything the framing is too small for the material. It reads as one engineer's rough evening with a machine he wants to decommission, yet two of the three failures are entirely generic: any shipped binary carries its builder's ABI floor, and any OpenVZ-style container can exhaust systemd subgroups while producing an error that blames systemd. No product is being pushed and no numbers are being spun — the diagnostics are more reusable than the modest "three outages on my own boxes" packaging suggests.
Author's stake, not a vendor's
No sponsor, no launch, no product in the frame. The pressures are personal and visible: the author also wrote the earlier fix, so the third failure is narrated as "my fix covered the redeploy path, this was a later code path with the same blind spot," and the piece builds an explicit case for retiring a server he plainly wants gone. Those shape the emphasis and the closing recommendation; they do not obviously reach the command outputs.
Coherent, unaudited
Internally it holds: the counts reconcile — five occupied directories, ninety-six empty, roughly ninety-five free once cleaned — and each remedy follows from its diagnosis rather than from trial and error. What keeps confidence in the middle band is the sourcing shape: one author, one machine, self-reported, an unnamed orchestrator at an unnamed version, and no second pair of eyes on the placement regression. Trust the mechanisms; hold the specifics loosely.