Skip to content

Commit b0fc771

Browse files
authored
Create, start and delete microVMs in runner.sh (#13)
* Add number validation functions * Lessen size of random strings * Migrate VM creation to runner Change the logic to adapt to the semantics of the microVMs lifecycle. MicroVMs are created, started and deleted by the runner loops instead. The orchestrator is only responsible for creating the loops. As a result, many ORCHESTRATOR_ variables (and their options) have been moved to the runner.sh loop script, and renamed to RUNNER_. The orchestrator now accepts much fewer options. Instead, options should be passed after a -- at the command-line, and these are blindly passed to each runner loop. This means that the number of loops to create is not an argument anymore, but rather an option to the orchestrator (defaults to 1). This is a breaking change. Also the tgz binary distribution is now removed during installation, and, instead the runner-specific installation is (recursively) copied to the target directory. This is to avoid the need to have the tgz distribution in the runner's directory, but also because copying is actually quicker than moving files (hierarchies).
1 parent 72e9218 commit b0fc771

File tree

7 files changed

+284
-252
lines changed

7 files changed

+284
-252
lines changed

CONTRIBUTING.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@
22

33
This document contains notes about the internals of the implementation.
44

5+
> [!TIP]
6+
> The [orchestrator](./orchestrator.sh) takes few options. Run it with a `--`,
7+
> all options after that separator will be blindly passed to the
8+
> [runner](./runner.sh), which is the script with most user-facing options.
9+
510
## Signalling Between Processes
611

712
When environment isolation is turned on, i.e. when the variable
@@ -33,3 +38,21 @@ automatically removed as soon as the microVM has booted is running the
3338
`runner.sh` script, workflows are not able to break the external loop: they are
3439
able to create files in the `/_environment` directory, but they cannot know the
3540
value of the secret to put into the file to force the exiting handshake.
41+
42+
## Changes to the Installation Scripts
43+
44+
The installation of both images is handled by the [`base.sh`](./base/base.sh)
45+
and [`install.sh`](./runner/install.sh). When making changes to these scripts,
46+
or to the [`docker.sh`](./base/docker.sh) docker CLI wrapper, you will need to
47+
wait for the results of the [`dev.yml`](./.github/workflows/dev.yml) workflow to
48+
finish and for the resulting image to be published at the GHCR before being able
49+
to test. The images will be published for amd64 only and with a tag named after
50+
the name of the branch. Check out the "Inspect image" step of the `merge` job to
51+
collect the fully-qualified name of the image. Once done, provide that name to
52+
the `-i` option of the [`runner.sh`](./runner.sh) script.
53+
54+
Note that when changing the logic of the "entrypoints", i.e. the scripts run at
55+
microVM initialisation, you do not need to wait for the image to be created.
56+
Instead, pass `-D /local` to the [`runner.sh`](./runner.sh) script. This will
57+
mount the [`runner`](./runner/) directory into the microVM at `/local` and run
58+
the scripts that it contains from there instead.

README.md

Lines changed: 32 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -17,36 +17,35 @@ multi-platform OCI [images][image] created for this project.
1717
## Example
1818

1919
Provided you are at the root directory of this project, the following would
20-
create two runner loops that are bound to *this* repository (the
21-
`efrecon/gh-runner-krunvm` principal). Runners can also be registered at the
22-
`organization` or `enterprise` scope using the `-s` option. In the example
20+
create two runner loops (the `-n` option) that are bound to *this* repository
21+
(the `efrecon/gh-runner-krunvm` principal). Runners can also be registered at
22+
the `organization` or `enterprise` scope using the `-s` option. In the example
2323
below, the value of the `-T` option should be a [PAT]. In each loop, as soon as
2424
one job has been picked up and executed, a new pristine runner will be created
2525
and registered.
2626

27-
2827
```bash
29-
./orchestrator.sh -v -T ghp_XXXX -p efrecon/gh-runner-krunvm -- 2
28+
./orchestrator.sh -v -n 2 -- -T ghp_XXXX -p efrecon/gh-runner-krunvm
3029
```
3130

32-
The project tries to have good default options and behaviour -- run with `-h`
33-
for a list of options. For example, nor the value of the token, nor the value of
34-
the runner registration token will be visible to the workflows using your
35-
runners. The default is however to create far-less capable runners than the
36-
GitHub [runners], i.e. 1G or memory and 2 vCPUs. By default, runners have random
37-
names and carry labels with the name of the base repository, e.g. `fedora` and
38-
`krunvm`. The GitHub runner implementation will automatically add other labels
39-
in addition to those.
31+
The project tries to have good default options and behaviour. For example, nor
32+
the value of the token, nor the value of the runner registration token will be
33+
visible to the workflows using your runners. The default is however to create
34+
far-less capable runners than the GitHub [runners], i.e. 1G or memory and 2
35+
vCPUs. By default, runners have random names and carry labels with the name of
36+
the base repository, e.g. `fedora` and `krunvm`. The GitHub runner
37+
implementation will automatically add other labels in addition to those.
4038

4139
All scripts within the project accepts short options only and can either be
4240
controlled through options or environment variables. Running with the `-h`
43-
option will provide help and a list of those variables. Variables starting with
44-
`ORCHESTRATOR_` will affect the behaviour of the
41+
option will provide help and a list of those variables. From the command-line,
42+
you will only be running one script: the [orchestrator](./orchestrator.sh).
43+
However, runner loops are created using the [runner](./runner.sh) script, by the
44+
orchestrator. At the orchestrator CLI, options that appear after the `--` will
45+
be blindly passed to the runner loop and script. Environment variables starting
46+
with `ORCHESTRATOR_` will affect the behaviour of the
4547
[orchestrator](./orchestrator.sh), while variables starting with `RUNNER_` will
46-
affect the behaviour of each runner. Usually, the only script that you will have
47-
to use is the [orchestrator](./orchestrator.sh). However, it is possible to
48-
create the microVM with the orchestrator and manually run loops using the
49-
[runner](./runner.sh) script.
48+
affect the behaviour of each runner (loop).
5049

5150
[PAT]: https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens
5251

@@ -75,7 +74,7 @@ create the microVM with the orchestrator and manually run loops using the
7574
## Requirements
7675

7776
This project is coded in pure POSIX shell and has only been tested on Linux. The
78-
images are automatically [built] both for x86_64 and AArch64. However, [krunvm]
77+
images are automatically [built] both for amd64 and arm64. However, [krunvm]
7978
also runs on MacOS. No "esoteric" options have been used when using the standard
8079
UNIX binary utilities. PRs are welcome to make the project work on MacOS, if it
8180
does not already.
@@ -106,12 +105,13 @@ installed on the host. Installation is easiest on Fedora
106105

107106
## Architecture and Design
108107

109-
The [orchestrator](./orchestrator.sh) focuses on creating (but not starting) a
110-
microVM based on the default OCI image (see below). It then creates as many
111-
loops of ephemeral runners as requested. These loops are implemented as part of
112-
the [runner.sh](./runner.sh) script: the script will start a microVM that will
113-
start an (ephemeral) [runner][self]. As soon as a job has been executed on that
114-
runner, the microVM will end and a new will be created.
108+
The [orchestrator](./orchestrator.sh) creates as many loops of ephemeral runners
109+
as requested. These loops are implemented as part of the
110+
[runner.sh](./runner.sh) script: the script will create a microVM based on the
111+
default image (see below), memory and vCPU requirement. It will then start that
112+
microVM using `krunvm` and that will start an (ephemeral) [runner][self]. As
113+
soon as a job has been executed on that runner, the microVM will end and a new
114+
will be created.
115115

116116
The OCI image is built in two parts:
117117

@@ -143,6 +143,12 @@ user. The `runner` user shares the same id as the one at GitHub and is also a
143143
member of the `docker` group. Similarily to GitHub runners, the user is capable
144144
of `sudo` without a password.
145145

146+
Runner tokens are written to the directory that is shared with the host. This is
147+
used during initial synchronisation, to avoid starting up several runners at the
148+
same time from the main orchestrator loop. The tokens are automatically removed
149+
as soon as the runner is up, they are also protected so that the `runner` user
150+
cannot read their content.
151+
146152
## History
147153

148154
This project was written to combat my anxeity combatting my daughter's newly

lib/common.sh

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ is_true() {
3333

3434
# shellcheck disable=SC2120 # Function has good default.
3535
random_string() {
36-
LC_ALL=C tr -dc 'a-zA-Z0-9' < /dev/urandom | head -c "${1:-12}"
36+
LC_ALL=C tr -dc 'a-zA-Z0-9' < /dev/urandom | head -c "${1:-7}"
3737
}
3838

3939
usage() {
@@ -104,6 +104,27 @@ wait_path() {
104104
done
105105
}
106106

107+
check_number() {
108+
if ! printf %d\\n "$1" >/dev/null 2>&1; then
109+
if [ -n "${2:-}" ]; then
110+
error "$2 is an invalid number: $1"
111+
else
112+
error "Invalid number: $1"
113+
fi
114+
fi
115+
}
116+
117+
check_positive_number() {
118+
check_number "$1" "$2"
119+
if [ "$1" -le 0 ]; then
120+
if [ -n "${2:-}" ]; then
121+
error "$2 must be a positive number: $1"
122+
else
123+
error "Invalid positive number: $1"
124+
fi
125+
fi
126+
}
127+
107128

108129
# PML: Poor Man's Logging
109130
_log() {

0 commit comments

Comments
 (0)