Providers
Rungar does not run machines itself. It asks a provider for them: one backend that can create, list and delete machines – a Dicer host, a Proxmox VE cluster, a cloud project or account. Everything about the backend – how it is reached, what a runner’s machine is made of, how the machine is told which runner to become – is the provider’s, and the rest of Rungar works the same whichever one it is.
Where on the backend a machine goes is the backend’s business too. A cloud schedules its servers, a cluster its nodes; a Dicer host is one machine, and so is its own answer. Rungar chooses only which provider a runner goes to – the same way for every type – and never which machine inside it. See Placement.
Which backends Rungar can use are its provider types, each with a page in Providers. Everything on this page holds for every type.
Providers
providers lists them. Each has a name, which scale sets, logs and
metrics call it by, and a type. It may have a weight, a
max_runners, a disabled and a runner
block. Those are Rungar’s, and mean the same on every
type. Everything else in the entry is its type’s to read – here, where a
Dicer daemon is and how it is reached – and is checked when the
configuration loads, so a misspelt key is refused before anything starts:
providers:
- &dicer
name: compute1
type: dicer
address: 10.10.0.101:7443
tls:
ca_file: /etc/rungar/ca.pem
cert_file: /etc/rungar/client.pem
key_file: /etc/rungar/client-key.pem
runner:
image: ghcr.io/actions/actions-runner:latest
kernel: linux-6.18
- <<: *dicer
name: compute2
address: 10.10.0.102:7443
weight: 2A fleet of machines that each make their own decisions, like Dicer hosts, is
a provider per machine. What they share is written once, with a YAML anchor
(&dicer), and brought into the others with a merge key (<<: *dicer); each
then says only what differs. Rungar reads a provider’s entry with its anchors
resolved, so the type sees it as if it had been written out.
A provider is listed once. Two naming the same backend – the same address, written differently – are refused, since both would place runners on it and count them apart.
Three keys every provider has shape how placement uses it:
weight and max_runners, see Placement;
and disabled, which takes it out of placement while leaving its
runners to finish their jobs, see
Draining a provider.
Room
What a provider has room for is its backend’s to say, and it says it the one way every backend can: by creating a runner’s machine, or refusing to because it is full. Rungar tries a provider and, when it is full, the next; see Placement. It never assumes a provider empty because Rungar put nothing there, and never keeps a count of its own of what a backend holds. Whether vCPUs may be overcommitted is the backend’s setting, not Rungar’s.
A provider that cannot be reached is shown as such, and left out of placement; its runners are written off only after five minutes. See State and adoption.
The runner block
What a runner’s machine is made of is written in the provider type’s terms – an
image and a size, a machine type and a network – in a runner block. It is
written in two places, the second over the first:
- the provider’s own, which every scale set on it starts from: what the scale sets share, such as the image;
- the scale set’s for that provider, which says what makes its runners different there – usually their size.
scale_sets:
- name: rungar-c2-m4
max_runners: 8
providers:
- name: compute1
runner: &c2-m4 {vcpus: 2, memory: 4GiB}
- name: compute2
runner: *c2-m4
- name: rungar-c8-m16
max_runners: 2
providers:
- name: compute1
runner: &c8-m16 {vcpus: 8, memory: 16GiB}
- name: compute2
runner: {<<: *c8-m16, disk: 100GiB}Each block is its provider’s alone, so a scale set says its size once for each provider; providers alike share it with a YAML anchor, as above. The keys are the type’s, but how the two blocks combine is Rungar’s, the same on every type:
- a key given later replaces the one before;
- a mapping, such as an environment, is merged key by key;
- a list, such as mounts, is replaced whole;
- a key set to
nullis cleared, as if it had never been given.
What results is handed to each provider’s type, which checks it as the runner it will actually be when the configuration loads – so a scale set that inherits no image is refused before anything starts, and names the provider it would have been refused on.
A scale set can span providers of different types, each block in its own provider’s terms:
scale_sets:
- name: rungar-c4-m8
max_runners: 10
providers:
- name: compute1
runner: {vcpus: 4, memory: 8GiB}
- name: gcp
runner: {machine_type: e2-custom-4-8192}Moving things around
Because runners are found by their labels rather than remembered, changing the configuration is safe, but a few changes leave something behind:
- Removing a provider, or taking it out of a scale set’s list, leaves its
runners where they are, no longer looked at or counted. Busy ones finish
their job and go; idle ones take the next job that comes, and go. Mark it
disabledfirst, and remove it once it is empty. - Renaming a provider changes only what logs, metrics and
rungar statuscall it: its runners are found by their labels, on whatever backend it names.