doc: Format README.md
This commit is contained in:
262
README.md
262
README.md
@@ -1,79 +1,84 @@
|
||||
# Podmand-In-Podman Gitlab Runner
|
||||
|
||||
This project provides a Gitlab Runner which runs inside a container launched
|
||||
with `podman`. The Gitlab Runner itself uses an independent `podman` instance
|
||||
inside to launch jobs.
|
||||
|
||||
## Overview
|
||||
|
||||
This container image is built daily from this `Containerfile`, and
|
||||
made available as:
|
||||
This container image is built daily from this `Containerfile`, and made
|
||||
available as:
|
||||
|
||||
* `registry.gitlab.com/qontainers/pipglr:latest`
|
||||
- `registry.gitlab.com/qontainers/pipglr:latest`
|
||||
|
||||
-or-
|
||||
|
||||
* `registry.gitlab.com/qontainers/pipglr:<version>`
|
||||
- `registry.gitlab.com/qontainers/pipglr:<version>`
|
||||
|
||||
It's purpose is to provide an easy method to execute a GitLab runner,
|
||||
to service CI/CD jobs for groups and/or repositories on
|
||||
[gitlab.com](https://gitlab.com). It comes pre-configured to utilize
|
||||
the gitlab-runner app to execute within a rootless podman container,
|
||||
nested inside a rootless podman container.
|
||||
It's purpose is to provide an easy method to execute a GitLab runner, to service
|
||||
CI/CD jobs for groups and/or repositories on [gitlab.com](https://gitlab.com).
|
||||
It comes pre-configured to utilize the gitlab-runner app to execute within a
|
||||
rootless podman container, nested inside a rootless podman container.
|
||||
|
||||
This is intended to provide additional layers of security for the host,
|
||||
when running potentially arbitrary CI/CD code. Though, the ultimate
|
||||
responsibility still rests with the end-user to review the setup and
|
||||
configuration relative to their own security situation/environment.
|
||||
This is intended to provide additional layers of security for the host, when
|
||||
running potentially arbitrary CI/CD code. Though, the ultimate responsibility
|
||||
still rests with the end-user to review the setup and configuration relative to
|
||||
their own security situation/environment.
|
||||
|
||||
**Note**: While this can run entirely under a regular user, it will require
|
||||
root access for the first two setup steps (below).
|
||||
**Note**: While this can run entirely under a regular user, it will require root
|
||||
access for the first two setup steps (below).
|
||||
|
||||
### Operation
|
||||
|
||||
This image leverages the podman `runlabel` feature heavily. Several
|
||||
labels are set on the image to support easy registration and execution
|
||||
of the runner container. While it's possible to use the container
|
||||
with your own command-line, it's highly recommended to base them
|
||||
off of one of the labels. See the examples below for more information.
|
||||
This image leverages the podman `runlabel` feature heavily. Several labels are
|
||||
set on the image to support easy registration and execution of the runner
|
||||
container. While it's possible to use the container with your own command-line,
|
||||
it's highly recommended to base them off of one of the labels. See the examples
|
||||
below for more information.
|
||||
|
||||
***Note:*** Some older versions of podman don't support the
|
||||
`container runlabel` sub-command. If this is the case, you may simulate
|
||||
it with the following, substituting `<label>` with one of the predefined
|
||||
values (i.e. `register`, `setupconfig`, etc.):
|
||||
**_Note:_** Some older versions of podman don't support the `container runlabel`
|
||||
sub-command. If this is the case, you may simulate it with the following,
|
||||
substituting `<label>` with one of the predefined values (i.e. `register`,
|
||||
`setupconfig`, etc.):
|
||||
|
||||
```bash
|
||||
$ IMAGE="registry.gitlab.com/qontainers/pipglr:latest"
|
||||
$ eval $(podman inspect --format=json $IMAGE | jq -r .[].Labels.<label>)
|
||||
```
|
||||
|
||||
#### Persistent containers (step 1)
|
||||
#### Persistent Containers (step 1)
|
||||
|
||||
By default on many distributions, regular users aren't permitted to leave
|
||||
background processes running after they log out. Since this is likely
|
||||
desired for running the pipglr container long-term, `systemd` needs to be
|
||||
configured to override this policy. For this, you (`$USER`) will need
|
||||
root access on the system.
|
||||
background processes running after they log out. Since this is likely desired
|
||||
for running the pipglr container long-term, `systemd` needs to be configured to
|
||||
override this policy. For this, you (`$USER`) will need root access on the
|
||||
system.
|
||||
|
||||
```bash
|
||||
$ sudo loginctl enable-linger $USER
|
||||
```
|
||||
|
||||
Side-effect: This will allow your user to persist other user-level systemd
|
||||
services as well. For example `podman.socket` is handy to enable for
|
||||
`podman remote` access. You could also [setup
|
||||
quadlet](https://www.redhat.com/sysadmin/quadlet-podman) or a systemd unit
|
||||
so pipglr starts up on system boot.
|
||||
services as well. For example `podman.socket` is handy to enable for
|
||||
`podman remote` access. You could also
|
||||
[setup quadlet](https://www.redhat.com/sysadmin/quadlet-podman) or a systemd
|
||||
unit so pipglr starts up on system boot.
|
||||
|
||||
#### Expanded user-namespace (step 2) ***This is probably important***
|
||||
#### Expanded User-Namespace (step 2) **_This is probably important_**
|
||||
|
||||
As an added protection/safety measure, pipglr excludes three UID/GIDs
|
||||
from being used by job-level containers. One for `root`, another for
|
||||
`runner` and a third for `podman`. However, some container images
|
||||
you may want to use for jobs (mainly Debian/Ubuntu), assign one/more
|
||||
essential users a high UID/GID value (like `65535`).
|
||||
As an added protection/safety measure, pipglr excludes three UID/GIDs from being
|
||||
used by job-level containers. One for `root`, another for `runner` and a third
|
||||
for `podman`. However, some container images you may want to use for jobs
|
||||
(mainly Debian/Ubuntu), assign one/more essential users a high UID/GID value
|
||||
(like `65535`).
|
||||
|
||||
At the same time, most distributions also set `65536` as the default maximum
|
||||
number (including ID `0`) of IDs to allocate for user-namespaces (via `/etc/login.defs`). This
|
||||
creates a problem you won't realize until the runner actually picks up a job
|
||||
😞 The main symptom of this issue will be messages in the pipglr containers log,
|
||||
similar to (abbreviated):
|
||||
number (including ID `0`) of IDs to allocate for user-namespaces (via
|
||||
`/etc/login.defs`). This creates a problem you won't realize until the runner
|
||||
actually picks up a job 😞 The main symptom of this issue will be messages in
|
||||
the pipglr containers log, similar to (abbreviated):
|
||||
|
||||
```
|
||||
```text
|
||||
...cut...
|
||||
running `/usr/bin/newuidmap ...cut...`: newuidmap: write to uid_map failed: Operation not permitted
|
||||
Error: cannot set up namespace using "/usr/bin/newuidmap": exit status 1
|
||||
@@ -82,71 +87,71 @@ Error: cannot set up namespace using "/usr/bin/newuidmap": exit status 1
|
||||
|
||||
or
|
||||
|
||||
```
|
||||
```text
|
||||
E: setgroups 65534 failed - setgroups (22: Invalid argument)
|
||||
```
|
||||
|
||||
***The good news is, working around this is relatively simple:***
|
||||
**_The good news is, working around this is relatively simple:_**
|
||||
|
||||
As root, edit the two files `/etc/subuid` and `/etc/subgid` to expand the
|
||||
by 3 IDs. For example assuming a user running the pipglr container is
|
||||
called `johndoe`, the contents of these files should be edited to allocate
|
||||
`65539` IDs like:
|
||||
As root, edit the two files `/etc/subuid` and `/etc/subgid` to expand the by 3
|
||||
IDs. For example assuming a user running the pipglr container is called
|
||||
`johndoe`, the contents of these files should be edited to allocate `65539` IDs
|
||||
like:
|
||||
|
||||
`jogndoe:<some number>:65539`
|
||||
`johndoe:<some number>:65539`
|
||||
|
||||
Where `<some number>` was set by your OS when the `johndoe` user was created
|
||||
(you can ignore this). Only the last number needs to be increased. This
|
||||
change will be effective on next login, or immediately by running:
|
||||
(you can ignore this). Only the last number needs to be increased. This change
|
||||
will be effective on next login, or immediately by running:
|
||||
|
||||
`podman system migrate`
|
||||
|
||||
*Note:* This will stop any currently running containers.
|
||||
_Note:_ This will stop any currently running containers.
|
||||
|
||||
#### Runner registration (step 3)
|
||||
#### Runner Registration (step 3)
|
||||
|
||||
All runners must be connected to a project or group runner configuration
|
||||
on your gitlab instance (or `gitlab.com`). This is done using a special
|
||||
registration *runlabel*. The command can (and probably should) be run
|
||||
more than once (using the same `config.toml`) to configure and register
|
||||
multiple runners. This is necessary for the *pipglr* container to execute
|
||||
multiple jobs in parallel. For example, if you want to support running
|
||||
four jobs at the same time, you would use the `register` *runlabel*
|
||||
four times.
|
||||
All runners must be connected to a project or group runner configuration on your
|
||||
gitlab instance (or `gitlab.com`). This is done using a special registration
|
||||
_runlabel_. The command can (and probably should) be run more than once (using
|
||||
the same `config.toml`) to configure and register multiple runners. This is
|
||||
necessary for the _pipglr_ container to execute multiple jobs in parallel. For
|
||||
example, if you want to support running four jobs at the same time, you would
|
||||
use the `register` _runlabel_ four times.
|
||||
|
||||
Before using the `register` *runlabel*, you must set your unique
|
||||
*registration* (a.k.a. *activation*) token as a podman *secret*. This
|
||||
secret may be removed once the registration step is complete. The
|
||||
**<actual registration token>** value (below) should be replaced with
|
||||
the value obtained from the "runners" settings page of a gitlab
|
||||
group or project's *CI/CD Settings*. Gitlab version 16 and later
|
||||
refers to this value as an *activation* token, but the usage is the same.
|
||||
Before using the `register` _runlabel_, you must set your unique _registration_
|
||||
(a.k.a. _activation_) token as a podman _secret_. This secret may be removed
|
||||
once the registration step is complete. The **`<actual registration token>`**
|
||||
value (below) should be replaced with the value obtained from the `runners`
|
||||
settings page of a gitlab group or project's _CI/CD Settings_. Gitlab version 16
|
||||
and later refers to this value as an _activation_ token, but the usage is the
|
||||
same.
|
||||
|
||||
```bash
|
||||
$ IMAGE="registry.gitlab.com/qontainers/pipglr:latest"
|
||||
$ echo '<actual registration token>' | podman secret create REGISTRATION_TOKEN -
|
||||
```
|
||||
|
||||
Next, ***a blank `config.toml` file*** needs to be created. Without this, the
|
||||
`reigster` *runlabel* will return a permission-denied error. Once the empty
|
||||
Next, **_a blank `config.toml` file_** needs to be created. Without this, the
|
||||
`reigster` _runlabel_ will return a permission-denied error. Once the empty
|
||||
`config.toml` file is created, you may register one or more runners by repeating
|
||||
the registration *runlabel* as follows:
|
||||
the registration _runlabel_ as follows:
|
||||
|
||||
```bash
|
||||
$ IMAGE="registry.gitlab.com/qontainers/pipglr:latest"
|
||||
$ touch ./config.toml # important: file must exist, even if empty.
|
||||
$ podman container runlabel register $IMAGE
|
||||
...repeat as desired...
|
||||
# ...repeat as desired...
|
||||
$ podman secret rm REGISTRATION_TOKEN # if desired
|
||||
```
|
||||
|
||||
#### Runner Configuration (step 4)
|
||||
|
||||
During the registration process (above), a boiler-plate (default) `config.toml` file
|
||||
will be created/updated for you. At this point you may edit the configuration
|
||||
if desired before committing it as a *podman secret*. Please refer to the
|
||||
[gitlab runner documentation](https://docs.gitlab.com/runner/configuration/)
|
||||
for details.
|
||||
During the registration process (above), a boiler-plate (default) `config.toml`
|
||||
file will be created/updated for you. At this point you may edit the
|
||||
configuration if desired before committing it as a _podman secret_. Please refer
|
||||
to the
|
||||
[gitlab runner documentation](https://docs.gitlab.com/runner/configuration/) for
|
||||
details.
|
||||
|
||||
```bash
|
||||
$ $EDITOR ./config.toml # if desired
|
||||
@@ -155,15 +160,15 @@ $ rm ./config.toml # if desired
|
||||
```
|
||||
|
||||
This may be necessary, for example, to increase the default `concurrency` value
|
||||
to reflect the number of registered runners. If you need to edit this file
|
||||
after committing it as a secret, there's
|
||||
[ a `dumpconfig` *runlabel* for that](README.md#configuration-editing).
|
||||
to reflect the number of registered runners. If you need to edit this file after
|
||||
committing it as a secret, there's
|
||||
[a `dumpconfig` _runlabel_ for that](README.md#configuration-editing).
|
||||
|
||||
#### Volume setup (step 5)
|
||||
#### Volume Setup (step 5)
|
||||
|
||||
Since several users are utilized inside the container volumes must be
|
||||
specifically configured to permit access. This is done using several
|
||||
*runlabels* as follows:
|
||||
specifically configured to permit access. This is done using several _runlabels_
|
||||
as follows:
|
||||
|
||||
```bash
|
||||
$ IMAGE="registry.gitlab.com/qontainers/pipglr:latest"
|
||||
@@ -171,16 +176,17 @@ $ podman container runlabel setupstorage $IMAGE
|
||||
$ podman container runlabel setupcache $IMAGE
|
||||
```
|
||||
|
||||
Note: These volumes generally do not contain any critical operational data,
|
||||
they may be re-created anytime to quickly free up host disk-space if
|
||||
it's running low. Simply remove them with the command
|
||||
`podman volume rm pipglr-storage pipglr-cache`. Then reuse the `setupstorage`
|
||||
and `setupcache` *runlabels* as in the above example.
|
||||
Note: These volumes generally do not contain any critical operational data, they
|
||||
may be re-created anytime to quickly free up host disk-space if it's running
|
||||
low. Simply remove them with the command
|
||||
`podman volume rm pipglr-storage pipglr-cache`. Then reuse the `setupstorage`
|
||||
and `setupcache` _runlabels_ as in the above example.
|
||||
|
||||
#### Runner Startup (step 6)
|
||||
|
||||
With the runner configuration saved as a Podman secret, and the runner volumes
|
||||
created, the GitLab runner container may be launched with the following commands:
|
||||
created, the GitLab runner container may be launched with the following
|
||||
commands:
|
||||
|
||||
```bash
|
||||
$ IMAGE="registry.gitlab.com/qontainers/pipglr:latest"
|
||||
@@ -189,11 +195,10 @@ $ podman container runlabel run $IMAGE
|
||||
|
||||
### Configuration Editing
|
||||
|
||||
The gitlab-runner configuration contains some sensitive values which
|
||||
should be protected. The pipglr container assumes the entire configuration
|
||||
will be passed in as a Podman secret. This makes editing it slightly
|
||||
convoluted, so a handy *runlabel* `dumpconfig` is available.
|
||||
It's intended use is as follows:
|
||||
The gitlab-runner configuration contains some sensitive values which should be
|
||||
protected. The pipglr container assumes the entire configuration will be passed
|
||||
in as a Podman secret. This makes editing it slightly convoluted, so a handy
|
||||
_runlabel_ `dumpconfig` is available. It's intended use is as follows:
|
||||
|
||||
```bash
|
||||
$ IMAGE="registry.gitlab.com/qontainers/pipglr:latest"
|
||||
@@ -206,17 +211,17 @@ $ rm ./config.toml # if desired
|
||||
|
||||
### Debugging
|
||||
|
||||
The first thing to check is the container output. This shows three things:
|
||||
Systemd, Podman, and GitLab-Runner output. For example:
|
||||
The first thing to check is the container output. This shows three things:
|
||||
Systemd, Podman, and GitLab-Runner output. For example:
|
||||
|
||||
```bash
|
||||
$ podman logs --since 0 pipglr
|
||||
```
|
||||
|
||||
Next, try running a pipglr image built with more verbose logging. Both
|
||||
the `runner.service` and `podman.service` files have a `log-level` option.
|
||||
Simply increase one or both to the "info", or "debug" level. Start the
|
||||
debug container, and reproduce the problem.
|
||||
Next, try running a pipglr image built with more verbose logging. Both the
|
||||
`runner.service` and `podman.service` files have a `log-level` option. Simply
|
||||
increase one or both to the `info`, or `debug` level. Start the debug container,
|
||||
and reproduce the problem.
|
||||
|
||||
## Building
|
||||
|
||||
@@ -226,39 +231,36 @@ This image may be built simply with:
|
||||
$ podman build -t registry.gitlab.com/qontainers/pipglr:latest .
|
||||
```
|
||||
|
||||
This will utilize the latest stable version of podman and the latest
|
||||
stable version of the gitlab runner.
|
||||
This will utilize the latest stable version of podman and the latest stable
|
||||
version of the gitlab runner.
|
||||
|
||||
### Build-args
|
||||
### Build-Arguments
|
||||
|
||||
Several build arguments are available to control the output image:
|
||||
|
||||
* `PRUNE_INTERVAL` - A systemd.timer compatible `OnCalendar` value that
|
||||
- `PRUNE_INTERVAL`: A systemd.timer compatible `OnCalendar` value that
|
||||
determines how often to prune Podman's storage of disused containers and
|
||||
images. Defaults to "daily", but should be adjusted based on desired
|
||||
caching-effect balanced against available storage space and job
|
||||
execution rate.
|
||||
* `RUNNER_VERSION` - Allows specifying an exact gitlab runner version.
|
||||
By default the `latest` is used, assuming the user is building a tagged
|
||||
image anyway. Valid versions may be found on the [runner
|
||||
release page](https://gitlab.com/gitlab-org/gitlab-runner/-/releases).
|
||||
* `TARGETARCH` - Supports inclusion of non-x86_64 gitlab runners. This
|
||||
value is assumed to match the image's architecture. If using the
|
||||
`--platform` build argument, it will be set automatically. Note:
|
||||
as of this writing, only `amd64` and `arm64` builds of the gitlab-runner
|
||||
are available.
|
||||
* `GITLAB_URL` - Defaults to 'https://gitlab.com/' but can be set to point
|
||||
to a self hosted instance of Gitlab.
|
||||
* `NESTED_PRIVILEGED` - Defaults to 'true', may be set 'false' to prevent
|
||||
nested containers running in `--privileged` mode. This will affect
|
||||
the ability to build container images in CI jobs using tools like
|
||||
podman or buildah.
|
||||
images. Defaults to `daily`, but should be adjusted based on desired
|
||||
caching-effect balanced against available storage space and job execution
|
||||
rate.
|
||||
- `RUNNER_VERSION`: Allows specifying an exact gitlab runner version. By default
|
||||
the `latest` is used, assuming the user is building a tagged image anyway.
|
||||
Valid versions may be found on the
|
||||
[runner release page](https://gitlab.com/gitlab-org/gitlab-runner/-/releases).
|
||||
- `TARGETARCH`: Supports inclusion of non-x86_64 gitlab runners. This value is
|
||||
assumed to match the image's architecture. If using the `--platform` build
|
||||
argument, it will be set automatically. Note: as of this writing, only `amd64`
|
||||
and `arm64` builds of the gitlab-runner are available.
|
||||
- `GITLAB_URL`: Defaults to `https://gitlab.com/` but can be set to point to a
|
||||
self hosted instance of Gitlab.
|
||||
- `NESTED_PRIVILEGED`: Defaults to `true`, may be set `false` to prevent nested
|
||||
containers running in `--privileged` mode. This will affect the ability to
|
||||
build container images in CI jobs using tools like podman or buildah.
|
||||
|
||||
### Environment variables
|
||||
### Environment Variables
|
||||
|
||||
Nearly every option to every gitlab-runner sub-command may be specified via
|
||||
environment variable. Some of these are set in the `Containerfile` for
|
||||
the `register` *runlabel*. If you need to set additional runtime
|
||||
env. vars., please do so via additional `Environment` optionns in the
|
||||
`runner.service` file. See the *systemd.nspawn* man page for important
|
||||
value-format details.
|
||||
environment variable. Some of these are set in the `Containerfile` for the
|
||||
`register` _runlabel_. If you need to set additional runtime env. vars., please
|
||||
do so via additional `Environment` optionns in the `runner.service` file. See
|
||||
the _systemd.nspawn_ man page for important value-format details.
|
||||
|
||||
Reference in New Issue
Block a user