vole
Clone
Read only, no credentials:
https://rodent.software/git/vole.git
Write over SSH with a registered key:
git clone ssh://git@0.0.0.0:2222/vole.git
A free and open-source forge that lives in your Git repo.
Run several jobs at once with --jobs
18c559ea0010dc22db13c889afda4fe9af3c15d7 · Keenan Nemetz · 2d ago · parent 91b47a22
Run several jobs at once with --jobs A runner process leased one job and blocked on it, so the only way to get a second job onto a machine was a second process: another host, another key, another allowlist entry, and another --dir that learns the repositories cold. The server was never the limit — a lease is taken per session and claimed by a conditional update — so this is the runner catching up. `--jobs N` is N slots in one process. Each slot owns a session and runs at most one job, and everything that belongs to the process happens once, before the slots start: the directories, the cache bounds, the leftover sweep, and the connections. A slot that refuses a job stops every slot, because reconnecting would ask the same instance the same question. A slot that loses its connection reconnects with a doubling delay instead, so one flaky link does not take the other slots' jobs with it; the job it was running is requeued when its lease expires. The log stream moves from the session to the job, which is what makes two jobs on one session impossible to confuse: a slot has one, and it is the stream for the job in front of it. Deployment: `RUNNER_JOBS` in the first-boot renderer, the packaged argument file, and the docs. The container limits are per job, so the machine has to carry --jobs times what they allow; max_jobs_per_repo is what stops one repository claiming every slot. Refs: 01M6SCWCSX39QXS38QAHQSMVGX (#216)
docs/runner.md +40−2
| @@ -30,9 +30,47 @@ vole runner --remote ssh://git@host:2222 --repos demo --repos docs | |||
| 30 | 30 | - `--repos` narrows what the account is already allowed to run. It cannot grant | |
| 31 | 31 | access to a repository. | |
| 32 | 32 | - `--dir` chooses where checkouts and caches are kept. | |
| 33 | - `--jobs` is how many jobs this machine runs at once. Each gets its own container; | ||
| 34 | see [Running several jobs at once](#running-several-jobs-at-once). | ||
| 33 | 35 | - `--once` leases one job and exits, which is useful for a runner that is | |
| 34 | 36 | scheduled per job. | |
| 35 | 37 | ||
| 38 | ## Running several jobs at once | ||
| 39 | |||
| 40 | A build is usually one step waiting on one thing at a time, so most of a big machine | ||
| 41 | sits idle behind it. `--jobs` puts more jobs on the one machine: | ||
| 42 | |||
| 43 | ```sh | ||
| 44 | vole runner --remote ssh://git@host:2222 --container-runtime podman --jobs 4 | ||
| 45 | ``` | ||
| 46 | |||
| 47 | Each job slot is a session of its own, so the instance hands work to each one | ||
| 48 | independently and the runners page shows four rows rather than one. The slots share | ||
| 49 | the machine: one cache, one set of saved checkouts, one set of images. What they do | ||
| 50 | not share is a container. | ||
| 51 | |||
| 52 | Two things need sizing for it: | ||
| 53 | |||
| 54 | - **The container limits are per job.** `--container-memory`, `--container-cpus` and | ||
| 55 | `--container-pids` apply to each container, so a machine running four jobs needs | ||
| 56 | four times what they allow. On the instance, `max_jobs_per_repo` is what stops one | ||
| 57 | repository's burst from claiming every slot (see | ||
| 58 | [Configuration](configuration.md)). | ||
| 59 | - **A job's cache is shared with the same repository's other jobs.** Two jobs of the | ||
| 60 | same repository, trust and image get the same `/cache`, which is what lets them | ||
| 61 | reuse each other's downloads. The tools in the image are what make that safe: `go`, | ||
| 62 | `cargo` and `npm` all lock their own caches. A job that empties `/cache` or keeps | ||
| 63 | state there between runs is competing with its own siblings, so give it a path of | ||
| 64 | its own or its own runner. | ||
| 65 | |||
| 66 | An idle slot holds one open connection while it waits for work, so a machine with | ||
| 67 | `--jobs 8` uses eight of the instance's SSH connections (`ssh_max_connections`). | ||
| 68 | Losing a connection costs that slot its job — the job is requeued when its lease | ||
| 69 | expires — and the slot reconnects rather than stopping the rest. | ||
| 70 | |||
| 71 | With `--once`, `--jobs 4` starts up to four jobs, finishes them, and exits, which is | ||
| 72 | the shape a scheduler that starts a container per job wants. | ||
| 73 | |||
| 36 | 74 | ## The runner's account | |
| 37 | 75 | ||
| 38 | 76 | A runner connects as an account, and that account is the runner's identity: it is | |
| @@ -140,8 +178,8 @@ instance or kept on the runner, so each of those channels has a bound: | |||
| 140 | 178 | checkouts jobs clone from are bounded separately; see | |
| 141 | 179 | [Saved checkouts](#saved-checkouts). | |
| 142 | 180 | - **Container.** `--container-memory`, `--container-cpus` and `--container-pids` | |
| 143 | pass the runtime's own limits. `--container-network` is what this machine can | ||
| 144 | offer — `none` (the default) or `bridge` — and a job's own `network:` decides what | ||
| 181 | pass the runtime's own limits, per container, so `--jobs` multiplies them. | ||
| 182 | `--container-network` is what this machine can offer — `none` (the default) or `bridge` — and a job's own `network:` decides what | ||
| 145 | 183 | it gets, so a bridge runner can still run a job that asks for none. See | |
| 146 | 184 | [Network](#network). The runtime's storage driver, not Vole, is what bounds the | |
| 147 | 185 | container's writable layer, so size it on the host. | |