Skip to content

ARC capacity: 14 repos moved onto the shared node and saturated it #586

Description

@izzywdev

@claude — infra request. Raised from the consuming side; I have not touched anything in this repo's cluster config.

What happened

14 private repos were moved off ubuntu-latest onto their own ARC scale sets today, because the account's Actions budget refuses private-repo GitHub-hosted jobs outright (runner_id: 0, empty runner_name, no log — the job never starts). That migration is correct and working: jobs that had never run at all now run.

But it put 299 jobs across 14 repos onto the shared node at once, and it is saturated.

Evidence, from this repo's own tooling

cluster-query (runs-on: staging) is the cleanest measurement, because it's small, constant, and unrelated to the migrated repos:

dispatched outcome
18:49 UTC ran on staging-25mld-runner-z88sp, completed in 12s
19:29 UTC queued 8+ minutes, runner_id: 0, still not started

Same workflow, same runner, same commit. The only variable is load.

This is not the queue-forever hazard from governance/ci-runners.md — the staging set exists and its listener is up. It's genuine contention.

Why it happened

runners/arc/ puts all 22 scale sets on one 4-vCPU / 8GB node (fuzeinfra-ci-runner-1) at maxRunners: 3 each. That's a ceiling of ~66 concurrent runner pods, plus unbounded dind sidecars, on 4 vCPUs. ci-runners.md says this plainly — "Capacity is shared, and it is small… the sum across sets is what matters, not the per-set number" — and notes the node has OOMed once before.

I read that and rolled all 14 anyway. That's on me; the fix on my side was to stop pushing, and the backlog does drain.

What would help, in rough order of value

  1. More capacity — a second runner node, or a larger one. The fleet has roughly doubled its self-hosted footprint today and is not going back.
  2. Bound the sum, not the per-set number. maxRunners: 3 × 22 sets is a ceiling nothing enforces against actual CPU. Lowering per-set maxRunners would trade latency for stability, which is the better failure mode than an OOM.
  3. Cap the dind sidecars. They're currently unbounded, and they're the part most likely to take the node down rather than just slow it.

Not asking for

No change to scale-set names — the per-repo naming is what the consuming repos now declare in ci.runner, and the fuze-runner consolidation is a separate coordinated flip (see governance/ci-runners.md).

Related, and cheap

A concurrency group on the stamped workflows would cut a lot of this waste: a re-push currently stacks a whole new set of ~20 jobs instead of cancelling the superseded run. That's a FuzeSDLC change, not an infra one — I'll take it there once the current queue clears, since landing it means pushing to 14 repos again.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions