Merge branch 'reimplement_systemd' into 'main'
Fix podman leaking conmon processes See merge request qontainers/pipglr!18
This commit is contained in:
222
Containerfile
222
Containerfile
@@ -1,157 +1,81 @@
|
|||||||
# pipglr/Containerfile
|
FROM quay.io/centos/centos:stream9
|
||||||
#
|
|
||||||
# Builds a Podman-in-Podman Gitlab-Runner image for
|
|
||||||
# executing Gitlab CI/CD jobs. Requires configuration
|
|
||||||
# steps specific to Gitlab projects. For more info. see
|
|
||||||
# https://docs.gitlab.com/runner/executors/docker.html#use-podman-to-run-docker-commands
|
|
||||||
#
|
|
||||||
|
|
||||||
FROM quay.io/podman/stable:v4.3.1
|
ADD /setup.sh /xpackages.txt /root/
|
||||||
|
ADD /containers.conf /home/podman/.config/containers/containers.conf
|
||||||
|
ADD /podman.service /podman.socket /prune.service /prune.timer /home/podman/.config/systemd/user/
|
||||||
|
ADD /runner.service /home/runner/.config/systemd/user/
|
||||||
|
ADD kmsglog.conf /etc/systemd/system.conf.d/
|
||||||
|
|
||||||
# This is a list of packages to remove and/or exclude from the image.
|
# Allow image-builders to choose another version becides "latest" should
|
||||||
# Primarily this is done for security reasons, should a runner process
|
# an incompatible change be introduced.
|
||||||
# escape confinement. Having fewer things to poke, lowers the attack
|
ARG RUNNER_VERSION=latest
|
||||||
# surface-area.
|
|
||||||
#
|
|
||||||
# This list was formed manually by running these commands in the base image:
|
|
||||||
# for package in $(rpm -qa); do \
|
|
||||||
# if dnf erase $package; then echo "$package" >> exclude; fi; \
|
|
||||||
# done; \
|
|
||||||
# cat exclude
|
|
||||||
#
|
|
||||||
# After adding those packages to this file, the container build was run
|
|
||||||
# and package list adjusted, untill no dependency errors were raised.
|
|
||||||
ARG EXCLUDE_PACKAGES="\
|
|
||||||
fedora-repos-modular \
|
|
||||||
findutils \
|
|
||||||
libxcrypt-compat \
|
|
||||||
openldap-compat \
|
|
||||||
podman-gvproxy \
|
|
||||||
rootfiles \
|
|
||||||
sudo \
|
|
||||||
vim-minimal \
|
|
||||||
yum"
|
|
||||||
|
|
||||||
# Base-image runs as user 'podman', temporarily switch to root
|
# Permit building containers for alternate architectures. At the time
|
||||||
# for installation/setup.
|
# of this commit, only 'arm64' is available.
|
||||||
USER root
|
ARG TARGETARCH=amd64
|
||||||
# Helper for comparison in future RUN operations (DO NOT USE)
|
|
||||||
ARG _DNFCMD="dnf --setopt=tsflags=nodocs -y"
|
|
||||||
# Set this instead, if (for example) you want to volume-mount in /var/cache/dnf
|
|
||||||
ARG DNFCMD="${_DNFCMD}"
|
|
||||||
# Avoid installing any documentation to keep image small
|
|
||||||
# During install, excluding packages is meaningless if already installed
|
|
||||||
RUN set -x && \
|
|
||||||
rm -f /etc/dnf/protected.d/sudo.conf && \
|
|
||||||
rm -f /etc/dnf/protected.d/yum.conf && \
|
|
||||||
$DNFCMD remove ${EXCLUDE_PACKAGES}
|
|
||||||
|
|
||||||
# Enable callers to customize the runner version as needed, otherwise
|
# Allow image-builders to choose an alternate nested-container pruning cycle.
|
||||||
# assume this image will be version-tagged, so it's fine to grab the latest.
|
# For most people the default is probably fine. This setting is dependent
|
||||||
ARG RUNNER_VERSION="latest"
|
# on the number and frequency of jobs run, along with the amount of disk-space
|
||||||
# When building a multi-arch manifest-list, this buid-arg is set automatically.
|
# available for both /cache and /home/podman/.local/share/containers volumes.
|
||||||
ARG TARGETARCH="amd64"
|
ARG PRUNE_INTERVAL=daily # see systemd.timer for allowable values
|
||||||
ENV RUNNER_RPM_URL=https://gitlab-runner-downloads.s3.amazonaws.com/${RUNNER_VERSION}/rpm/gitlab-runner_${TARGETARCH}.rpm
|
|
||||||
RUN for rpm in ${EXCLUDE_PACKAGES}; do x+="--exclude=$rpm "; done && \
|
|
||||||
set -x && \
|
|
||||||
$DNFCMD update && \
|
|
||||||
$DNFCMD install $x $RUNNER_RPM_URL && \
|
|
||||||
$DNFCMD upgrade && \
|
|
||||||
$DNFCMD reinstall shadow-utils && \
|
|
||||||
if [[ "${DNFCMD}" == "${_DNFCMD}" ]]; then \
|
|
||||||
dnf clean all && \
|
|
||||||
rm -rf /var/cache/dnf; \
|
|
||||||
fi
|
|
||||||
|
|
||||||
# In case of a runner escape, prevent easy installation of packages.
|
# All-in-one packaging/image-setup script to keep things simple.
|
||||||
RUN rm -f /etc/dnf/protected.d/* && \
|
RUN PRUNE_INTERVAL=${PRUNE_INTERVAL} \
|
||||||
rpm -e dnf && \
|
RUNNER_VERSION=${RUNNER_VERSION} \
|
||||||
rm -f $(type -P rpm)
|
bash /root/setup.sh
|
||||||
|
|
||||||
ADD /config.toml /home/podman/.gitlab-runner/config.toml
|
VOLUME /cache /home/podman/.local/share/containers
|
||||||
# The global "listen_address" option is used for metrics and
|
ENTRYPOINT /lib/systemd/systemd
|
||||||
# debugging. Disable it by default since use requires special/
|
|
||||||
# additional host configuration.
|
|
||||||
# Ref: https://docs.gitlab.com/runner/configuration/advanced-configuration.html#the-global-section
|
|
||||||
ARG RUNNER_LISTEN_ADDRESS="disabled"
|
|
||||||
ENV RUNNER_LISTEN_ADDRESS=$RUNNER_LISTEN_ADDRESS
|
|
||||||
RUN if [[ "$RUNNER_LISTEN_ADDRESS" == "disabled" ]]; then \
|
|
||||||
sed -i -r \
|
|
||||||
-e "s/.*@@RUNNER_LISTEN_ADDRESS@@.*//g" \
|
|
||||||
/home/podman/.gitlab-runner/config.toml; \
|
|
||||||
else \
|
|
||||||
sed -i -r \
|
|
||||||
-e "s/@@RUNNER_LISTEN_ADDRESS@@/$RUNNER_LISTEN_ADDRESS/g" \
|
|
||||||
/home/podman/.gitlab-runner/config.toml; \
|
|
||||||
fi
|
|
||||||
|
|
||||||
# A small wrapper is needed to launch a background podman system service
|
# Gitlab-runner configuration options, may be freely overridden at
|
||||||
# process for the gitlab-runner to connect to.
|
# container image build time.
|
||||||
ADD /gitlab-runner-wrapper /podman-in-podman-maintenance /usr/local/bin/
|
ARG DEFAULT_JOB_IMAGE=registry.fedoraproject.org/fedora-minimal:latest
|
||||||
# Base image UTS NS configuration causes runner to break when launching
|
# Run nested containers in --privileged mode - required to allow building
|
||||||
# nested rootless containers.
|
# container images using podman or buildah. Otherwise may be set 'false'.
|
||||||
RUN sed -i -r \
|
ARG NESTED_PRIVILEGED=true
|
||||||
-e 's/^utsns.+host.*/utsns="private"/' \
|
|
||||||
/etc/containers/containers.conf && \
|
|
||||||
chmod +x /usr/local/bin/gitlab-runner-wrapper && \
|
|
||||||
chmod +x /usr/local/bin/podman-in-podman-maintenance && \
|
|
||||||
chown -R podman:podman /home/podman && \
|
|
||||||
chmod u+s /usr/bin/new{uid,gid}map && \
|
|
||||||
rm -f /home/podman/.bash* && \
|
|
||||||
echo DOCKER_HOST="unix:///tmp/podman-run-1000/podman/podman.sock" > /etc/profile.d/podman.sh && \
|
|
||||||
echo "podman:10000:10000" | tee /etc/subuid > /etc/subgid && \
|
|
||||||
setcap -n 10000 cap_setuid+ep /usr/bin/newuidmap && \
|
|
||||||
setcap -n 10000 cap_setuid+ep /usr/bin/newgidmap
|
|
||||||
|
|
||||||
# Runtime rootless-mode configuration
|
# The registration runlabel may be called multiple times to register more than
|
||||||
USER podman
|
# one runner. Each expects a REGISTRATION_TOKEN secret to be pre-defined and
|
||||||
# N/B: Volumes are cumulative with the base image
|
# the file './config.toml' to exist (may be empty). A local-cache volume
|
||||||
VOLUME ["/home/podman/.gitlab-runner/", "/cache"]
|
# '/cache' is configured for bind-mounting into all interrior-containers
|
||||||
WORKDIR /home/podman
|
# for container-runtime use, as recommended by the docs. Other settings
|
||||||
ENTRYPOINT ["/usr/local/bin/gitlab-runner-wrapper"]
|
# may be changed if you know what you're doing.
|
||||||
|
LABEL register="podman run -it --rm \
|
||||||
# Ensure root storage directory exists with correct permissions
|
--secret=REGISTRATION_TOKEN,type=env \
|
||||||
RUN mkdir -p .local/share/containers/storage
|
-v ./config.toml:/home/runner/.gitlab-runner//config.toml:Z \
|
||||||
|
-e REGISTER_NON_INTERACTIVE=true \
|
||||||
# Gitlab-runner configuration options. Default to unprivileged (nested)
|
-e CI_SERVER_URL=https://gitlab.com/ \
|
||||||
# runner. Privileged is required to permit nested container image building.
|
-e RUNNER_NAME=pipglr \
|
||||||
ARG RUNNER_NAME="qontainers-pipglr"
|
-e RUNNER_EXECUTOR=docker \
|
||||||
# Running inner-podman privileged is necessary at the time of this commit.
|
-e RUNNER_SHELL=bash \
|
||||||
ARG PRIVILEGED_RUNNER="true"
|
-e REGISTER_MAINTENANCE_NOTE=Podman-In-Podman-GitLab-Runner \
|
||||||
# Tags allow pinning jobs to specific runners, comma-separated list of
|
-e DOCKER_HOST=unix:///home/runner/podman.sock \
|
||||||
# tags to add to runner (no spaces!)
|
-e DOCKER_IMAGE=${DEFAULT_JOB_IMAGE} \
|
||||||
ARG RUNNER_TAGS="podman-in-podman"
|
-e DOCKER_CACHE_DIR=/cache \
|
||||||
# Permit running jobs without any tag at all
|
-e DOCKER_VOLUMES=/cache \
|
||||||
ARG RUNNER_UNTAGGED="true"
|
-e DOCKER_NETWORK_MODE=host \
|
||||||
# Adjust based on usage and storage size to prevent ENOSPACE problems
|
-e DOCKER_PRIVILEGED=${NESTED_PRIVILEGED} \
|
||||||
ARG CLEAN_INTERVAL="24h"
|
--user runner \
|
||||||
ENV CLEAN_INTERVAL="$CLEAN_INTERVAL" \
|
--entrypoint=/usr/bin/gitlab-runner \$IMAGE register"
|
||||||
REGISTER_NON_INTERACTIVE="true" \
|
# Additionally, the nested-podman storage volumes must be pre-created with
|
||||||
RUNNER_TAG_LIST="$RUNNER_TAGS" \
|
# 'podman' UID/GID values to allow nested containers access.
|
||||||
REGISTER_RUN_UNTAGGED="$RUNNER_UNTAGGED" \
|
LABEL setupstorage="podman volume create --opt o=uid=1000,gid=1000 pipglr-storage"
|
||||||
REGISTER_ACCESS_LEVEL="ref_protected" \
|
# Lastly, the gitlab-runner will manage container-cache in this directory,
|
||||||
REGISTER_MAXIMUM_TIMEOUT="3600" \
|
# which will also be bind-mounted into every container. So it must be
|
||||||
CI_SERVER_URL="https://gitlab.com/" \
|
# writable by both 'podman' user and 'runner' group.
|
||||||
RUNNER_NAME="${RUNNER_NAME}" \
|
LABEL setupcache="podman volume create --opt o=uid=1000,gid=1001 pipglr-cache"
|
||||||
RUNNER_EXECUTOR="docker" \
|
# Helper to extract the current configuration secret to allow editing.
|
||||||
RUNNER_SHELL="bash" \
|
LABEL dumpconfig="podman run -it --rm \
|
||||||
REGISTER_MAINTENANCE_NOTE="Podman-in-Podman containerized runner" \
|
--secret config.toml --entrypoint=/bin/cat \
|
||||||
DOCKER_HOST="unix:///tmp/podman-run-1000/podman/podman.sock" \
|
\$IMAGE /var/run/secrets/config.toml"
|
||||||
DOCKER_DEVICES="/dev/fuse" \
|
# Executing the runner container depends on the config.toml secret being
|
||||||
DOCKER_IMAGE="registry.fedoraproject.org/fedora-minimal:latest" \
|
# set (see above) and two volumes existing with correct permissions set.
|
||||||
DOCKER_CACHE_DIR="/cache" \
|
# Note: The contents of the volumes are not critical, they may be removed
|
||||||
DOCKER_VOLUMES="/cache" \
|
# and re-created (see above) to quickly free-up disk space.
|
||||||
DOCKER_NETWORK_MODE="host" \
|
LABEL run="podman run -dt --name pipglr \
|
||||||
DOCKER_PRIVILEGED="$PRIVILEGED_RUNNER"
|
--secret config.toml,uid=1001,gid=1001 \
|
||||||
|
-v pipglr-storage:/home/podman/.local/share/containers \
|
||||||
# Not a real build-arg. Simply here to save lots of typing.
|
-v pipglr-cache:/cache \
|
||||||
ARG _pm="--systemd=true --device=/dev/fuse --security-opt label=disable --user podman --volume pipglr-podman-root:/home/podman/.local/share/containers --volume pipglr-config:/home/podman/.gitlab-runner -v pipglr-podman-cache:/cache --tmpfs /var/lib/containers,ro,size=1k -e PODMAN_RUNNER_DEBUG -e LOG_LEVEL"
|
--systemd true --privileged \
|
||||||
|
--device /dev/fuse \$IMAGE"
|
||||||
# These labels simply make it easier to register and execute the runner.
|
|
||||||
# Define them last so they are absent should a image-build failure occur.
|
|
||||||
LABEL register="podman run -it --rm $_pm --secret REGISTRATION_TOKEN,type=env \$IMAGE register"
|
|
||||||
# Note: Privileged mode is required to permit building container images with inner-podman
|
|
||||||
LABEL run="podman run -d --privileged --name pipglr $_pm \$IMAGE run"
|
|
||||||
|
|
||||||
# In case it's helpful, include the documentation
|
|
||||||
ADD /README.md /home/podman/
|
|
||||||
|
|||||||
213
README.md
213
README.md
@@ -22,112 +22,122 @@ configuration relative to their own security situation/environment.
|
|||||||
|
|
||||||
### Operation
|
### Operation
|
||||||
|
|
||||||
This image supports `podman container runlabel`, or if your version
|
This image leverages the podman `runlabel` feature heavily. Several
|
||||||
lacks this feature, Several labels are set on the image to support
|
labels are set on the image to support easy registration and execution
|
||||||
easy registration and execution of a runner container using a special
|
of the runner container. While it's possible to use the container
|
||||||
bash command. See the examples below for more information.
|
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.
|
||||||
|
|
||||||
#### [Volume setup]
|
***Note:*** Some older versions of podman don't support the
|
||||||
|
`container runlabel` sub-command. If this is the case, you may simulate
|
||||||
Since podman inside the container runs as user `podman`, the volumes
|
it with the following, substituting `<label>` with one of the predefined
|
||||||
used by it need to be pre-created with ownership information. While,
|
values (i.e. `register`, `setupconfig`, etc.):
|
||||||
we're at it, might as well add the performance-improving `noatime`,
|
|
||||||
option as well.
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
$ VOLOPTS="o=uid=1000,gid=1000,noatime"; \
|
$ IMAGE="registry.gitlab.com/qontainers/pipglr:latest"
|
||||||
for VOLUME in pipglr-podman-root pipglr-config pipglr-podman-cache; do \
|
$ eval $(podman inspect --format=json $IMAGE | jq -r .[].Labels.<label>)
|
||||||
podman volume create --opt $VOLOPTS $VOLUME || true ; \
|
|
||||||
VOLPTH=$(podman unshare podman volume mount $VOLUME)
|
|
||||||
podman unshare chown -c -R 1000:1000 $VOLPTH && \
|
|
||||||
podman unshare chmod -c 02770 $VOLPTH && \
|
|
||||||
podman unshare podman volume unmount $VOLUME ; \
|
|
||||||
done
|
|
||||||
```
|
```
|
||||||
|
|
||||||
If you get `podman system service` startup permission-denied errors, or
|
#### Runner registration (step 1)
|
||||||
errors from gitlab-runner, unable to connect to the podman socket, this is
|
|
||||||
likely the cause. You can fix it after-the-fact using the same commands
|
|
||||||
above.
|
|
||||||
|
|
||||||
#### Runner registration
|
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.
|
||||||
|
|
||||||
Each time the registration command is run, a new runner is added into
|
Before using the `register` *runlabel*, you must set your unique
|
||||||
the configuration. If however, you simply need to update/modify the
|
*registration* (a.k.a. *activation*) token as a podman *secret*. This
|
||||||
configuration, please edit the `config.toml` file directly after mounting
|
secret may be removed once the registration step is complete. The
|
||||||
(default) `pipglr-runner-config` (`/home/podman/.gitlab-runner/`) volume.
|
**<actual registration token>** value (below) should be replaced with
|
||||||
For modern versions of podman, registration can be performed with the
|
the value obtained from the "runners" settings page of a gitlab
|
||||||
following commands:
|
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
|
```bash
|
||||||
$ IMAGE="registry.gitlab.com/qontainers/pipglr:latest"
|
$ IMAGE="registry.gitlab.com/qontainers/pipglr:latest"
|
||||||
$ echo '<actual registration token>' | podman secret create REGISTRATION_TOKEN -
|
$ echo '<actual registration token>' | podman secret create REGISTRATION_TOKEN -
|
||||||
|
$ touch ./config.toml # important: file must exist, even if empty.
|
||||||
$ podman container runlabel register $IMAGE
|
$ podman container runlabel register $IMAGE
|
||||||
|
...repeat as desired...
|
||||||
|
$ podman secret rm REGISTRATION_TOKEN # if desired
|
||||||
```
|
```
|
||||||
|
|
||||||
Where `<actual registration token>` is the value obtained from the "runners"
|
#### Runner Configuration (step 2)
|
||||||
settings page of a gitlab group or project. When you're finished registering
|
|
||||||
as many runners as you want, the secret is no-longer needed and may be removed:
|
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
|
```bash
|
||||||
$ podman secret rm REGISTRATION_TOKEN
|
$ $EDITOR ./config.toml # if desired
|
||||||
|
$ podman secret create config.toml ./config.toml
|
||||||
|
$ rm ./config.toml # if desired
|
||||||
```
|
```
|
||||||
|
|
||||||
##### Note
|
#### Volume setup (step 3)
|
||||||
|
|
||||||
Some versions of podman don't support the `container runlabel` sub-command.
|
Since several users are utilized inside the container volumes must be
|
||||||
If this is the case, you may simulate it with the following command (in addition
|
specifically configured to permit access. This is done using several
|
||||||
to the other example commands above):
|
*runlabels* as follows:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
$ eval $(podman inspect --format=json $IMAGE | jq -r .[].Labels.register)
|
$ IMAGE="registry.gitlab.com/qontainers/pipglr:latest"
|
||||||
|
$ podman container runlabel setupstorage $IMAGE
|
||||||
|
$ podman container runlabel setupcache $IMAGE
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Runner Startup
|
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`. The reuse the `setupstorage`
|
||||||
|
and `setupcache` *runlabels* as in the above example.
|
||||||
|
|
||||||
With one or more runners successfully registered and configured, the GitLab
|
#### Runner Startup (step 4)
|
||||||
runner container may be launched with the following commands:
|
|
||||||
|
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:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
$ IMAGE="registry.gitlab.com/qontainers/pipglr:latest"
|
||||||
$ podman container runlabel run $IMAGE
|
$ podman container runlabel run $IMAGE
|
||||||
```
|
```
|
||||||
|
|
||||||
##### Note
|
### Configuration Editing
|
||||||
|
|
||||||
As above, if you're missing the `container runlabel` sub-command, the following
|
The gitlab-runner configuration contains some sensitive values which
|
||||||
may be used instead (assuming `$IMAGE` remains set):
|
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
|
```bash
|
||||||
$ eval $(podman inspect --format=json $IMAGE | jq -r .[].Labels.run)
|
$ IMAGE="registry.gitlab.com/qontainers/pipglr:latest"
|
||||||
|
$ podman container runlabel dumpconfig $IMAGE > ./config.toml
|
||||||
|
$ $EDITOR ./config.toml
|
||||||
|
$ podman secret rm config.toml
|
||||||
|
$ podman secret create config.toml ./config.toml
|
||||||
|
$ rm ./config.toml # if desired
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Runner configuration
|
### Debugging
|
||||||
|
|
||||||
You may inspect/modify the gitlab-runner configuration as you see fit, just be
|
The first thing to check is the container output. This shows three things:
|
||||||
sure to use the `podman unshare` command-wrapper to enter the usernamespace.
|
Systemd, Podman, and GitLab-Runner output. For example:
|
||||||
For example, to display the config:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ podman unshare cat $(podman unshare podman volume mount pipglr-config)/config.toml
|
|
||||||
```
|
|
||||||
|
|
||||||
Edit the config with your favorite `$EDITOR`:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ podman unshare $EDITOR $(podman unshare podman volume mount pipglr-config)/config.toml
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Debugging
|
|
||||||
|
|
||||||
The first thing to check is the container output:
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
$ podman logs --since 0 pipglr
|
$ podman logs --since 0 pipglr
|
||||||
```
|
```
|
||||||
|
|
||||||
Next, try running pipglr after an `export PODMAN_RUNNER_DEBUG=debug` to enable
|
Next, try running a pipglr image built with more verbose logging. Both
|
||||||
debugging on the inner-podman. If more runner detail is needed, you can instead/additionally
|
the `runner.service` and `podman.service` files have a `log-level` option.
|
||||||
set `export LOG_LEVEL=debug` to debug the gitlab-runner itself.
|
Simply increase one or both to the "info", or "debug" level. Start the
|
||||||
|
debug container, and reproduce the problem.
|
||||||
|
|
||||||
## Building
|
## Building
|
||||||
|
|
||||||
@@ -140,69 +150,34 @@ $ podman build -t registry.gitlab.com/qontainers/pipglr:latest .
|
|||||||
This will utilize the latest stable version of podman and the latest
|
This will utilize the latest stable version of podman and the latest
|
||||||
stable version of the gitlab runner.
|
stable version of the gitlab runner.
|
||||||
|
|
||||||
### Notes
|
|
||||||
|
|
||||||
* If you wish to use the `testing` or `upstream` flavors of the podman base image,
|
|
||||||
simply build with `--build-arg FLAVOR=testing` (or `upstream`).
|
|
||||||
|
|
||||||
* Additionally or alternatively, you may specify a specific podman base image tag
|
|
||||||
with `--build-arg BASE_TAG=<value>`. Where `<value>` is either `latest`, the
|
|
||||||
podman image version (e.g. `v4`, `v4.2`, `v4.2.0`, etc.)
|
|
||||||
|
|
||||||
### Build-args
|
### Build-args
|
||||||
|
|
||||||
Several build arguments are available to control the output image:
|
Several build arguments are available to control the output image:
|
||||||
|
|
||||||
* `FLAVOR` - Choose from 'stable', 'testing', or 'upstream'. These
|
* `PRUNE_INTERVAL` - A systemd.timer compatible `OnCalendar` value that
|
||||||
select the podman base-image to utilize - which may affect the
|
determines how often to prune Podman's storage of disused containers and
|
||||||
podman version, features, and stability. For more information
|
images. Defaults to "daily", but should be adjusted based on desired
|
||||||
see [the podmanimage README](https://github.com/containers/podman/blob/main/contrib/podmanimage/README.md).
|
caching-effect balanced against available storage space and job
|
||||||
* `BASE_TAG` - When `FLAVOR="stable"`, allows granular choice over the
|
execution rate.
|
||||||
exact podman version. Possible values include, `latest`, `vX`, `vX.Y`,
|
|
||||||
and `vX.Y.Z` (where, `X`, `Y`, and `Z` represent the podman semantic
|
|
||||||
version numbers). It's also possible to specify an image SHA.
|
|
||||||
* `CLEAN_INTERVAL` - A `sleep` (command) compatible time-argument that
|
|
||||||
determines how often to clean out podman storage of disused containers and
|
|
||||||
images. Defaults to 24-hours, but should be adjusted based on desired caching-effect
|
|
||||||
versus available storage space and rate of job execution.
|
|
||||||
* `EXCLUDE_PACKAGES` - A space-separated list of RPM packages to prevent
|
|
||||||
their existence in the final image. This is intended as a security measure
|
|
||||||
to limit the attack-surface should a gitlab-runner process escape it's
|
|
||||||
inner-container.
|
|
||||||
* `RUNNER_VERSION` - Allows specifying an exact gitlab runner version.
|
* `RUNNER_VERSION` - Allows specifying an exact gitlab runner version.
|
||||||
By default the `latest` is used, assuming the user is building a tagged
|
By default the `latest` is used, assuming the user is building a tagged
|
||||||
image anyway. Valid versions may be found on the [runner
|
image anyway. Valid versions may be found on the [runner
|
||||||
release page](https://gitlab.com/gitlab-org/gitlab-runner/-/releases).
|
release page](https://gitlab.com/gitlab-org/gitlab-runner/-/releases).
|
||||||
* `DNFCMD` - By default this is set to `dnf --setopt=tsflags=nodocs -y`.
|
|
||||||
However, if you'd like to volume-mount in `/var/cache/dnf` then you'll
|
|
||||||
need to use
|
|
||||||
`--build-arg DNFCMD="dnf --setopt=tsflags=nodocs -y --setopt keepcache=true`"
|
|
||||||
Note: Changing `DNFCMD` will cause build-time cache cleanup to be disabled.
|
|
||||||
* `TARGETARCH` - Supports inclusion of non-x86_64 gitlab runners. This
|
* `TARGETARCH` - Supports inclusion of non-x86_64 gitlab runners. This
|
||||||
value is assumed to match the image's architecture. If using the
|
value is assumed to match the image's architecture. If using the
|
||||||
`--platform` build argument, it will be set automatically.
|
`--platform` build argument, it will be set automatically. Note:
|
||||||
* `RUNNER_LISTEN_ADDRESS` - Disabled by default, setting this to the FQDN
|
as of this writing, only `amd64` and `arm64` builds of the gitlab-runner
|
||||||
and port supports various observability and debugging features of the
|
are available.
|
||||||
gitlab runner. For more information see the [gitlab runner advanced
|
* `NESTED_PRIVILEGED` - Defaults to 'true', may be set 'false' to prevent
|
||||||
configuration documentation](https://docs.gitlab.com/runner/configuration/advanced-configuration.html#the-global-section).
|
nested containers running in `--privileged` mode. This will affect
|
||||||
* `PRIVILEGED_RUNNER` - Defaults to 'true', may be set 'true' if you're brave.
|
the ability to build container images in CI jobs using tools like
|
||||||
However this may result in the gitlab-runner failing to launch inner-containers.
|
podman or buildah.
|
||||||
Setting it false will also prevent building container images using the runner.
|
|
||||||
* `RUNNER_TAGS` - Defaults to `podman_in_podman`, may be set to any comma-separated
|
|
||||||
list (with no spaces!) of tags. These show up in GitLab (not the runner
|
|
||||||
configuration), and determines where jobs are run.
|
|
||||||
* `RUNNER_UNTAGED` - Defaults to `true`, may be set to `false`. Allows
|
|
||||||
the runner to service jobs without any tags on them at all.
|
|
||||||
|
|
||||||
### Environment variables
|
### Environment variables
|
||||||
|
|
||||||
Nearly every option to every gitlab-runner sub-command may be specified via
|
Nearly every option to every gitlab-runner sub-command may be specified via
|
||||||
environment variable. Many important/required options are set in the
|
environment variable. Some of these are set in the `Containerfile` for
|
||||||
`Containerfile`. However it's entirely possible to pass them in via
|
the `register` *runlabel*. If you need to set additional runtime
|
||||||
either of the `podman container runlabel...` container commands. To
|
env. vars., please do so via additional `Environment` optionns in the
|
||||||
discover them, simply append `--help` to the end of the command.
|
`runner.service` file. See the *systemd.nspawn* man page for important
|
||||||
For example:
|
value-format details.
|
||||||
|
|
||||||
```bash
|
|
||||||
podman container runlabel $IMAGE register --help
|
|
||||||
```
|
|
||||||
|
|||||||
@@ -1,7 +0,0 @@
|
|||||||
|
|
||||||
# Ref: https://docs.gitlab.com/runner/configuration/advanced-configuration.html
|
|
||||||
|
|
||||||
concurrent = 8
|
|
||||||
# N/B: This is DIVIDED among the number of registered runners
|
|
||||||
check_interval = 10
|
|
||||||
listen_address = "@@RUNNER_LISTEN_ADDRESS@@" # Will be removed if undefined
|
|
||||||
13
containers.conf
Normal file
13
containers.conf
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
[containers]
|
||||||
|
netns="host"
|
||||||
|
userns="host"
|
||||||
|
ipcns="host"
|
||||||
|
utsns="private"
|
||||||
|
cgroupns="host"
|
||||||
|
cgroups="disabled"
|
||||||
|
log_driver = "k8s-file"
|
||||||
|
|
||||||
|
[engine]
|
||||||
|
cgroup_manager = "cgroupfs"
|
||||||
|
events_logger="file"
|
||||||
|
runtime="crun"
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# This script is intended to be called as the entrypoint for
|
|
||||||
# a podman-in-podman gitlab runner container. Any usage
|
|
||||||
# outside that context is not supported and may cause harm.
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
unset _debug_args
|
|
||||||
if [[ -n "$PODMAN_RUNNER_DEBUG" ]]; then
|
|
||||||
_debug_args="--log-level=$PODMAN_RUNNER_DEBUG"
|
|
||||||
fi
|
|
||||||
|
|
||||||
SOCKET="/tmp/podman-run-1000/podman/podman.sock"
|
|
||||||
if [[ "$1" == "run" ]] && [[ ! -S "$SOCKET" ]]; then
|
|
||||||
podman $_debug_args system service -t 0 &
|
|
||||||
/usr/local/bin/podman-in-podman-maintenance &
|
|
||||||
# Prevent SIGHUP propagation to podman process
|
|
||||||
disown -ar
|
|
||||||
sleep 1s # Give podman a chance to get going
|
|
||||||
# Verify podman is listening on it's socket
|
|
||||||
if [[ ! -S "$SOCKET" ]]; then
|
|
||||||
echo "ERROR: Inner-podman system service failed to start, expecting to find socket '$SOCKET'. Are all volume's owned & writeable by $(id -u podman):$(id -g podman)?" > /dev/stderr
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
exec gitlab-runner "$@"
|
|
||||||
3
kmsglog.conf
Normal file
3
kmsglog.conf
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
[Manager]
|
||||||
|
LogTarget=kmsg
|
||||||
|
LogColor=yes
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# This script is intended to be called by the entrypoint for
|
|
||||||
# a podman-in-podman gitlab runner container. Any usage
|
|
||||||
# outside that context is not supported and may cause harm.
|
|
||||||
|
|
||||||
set -eo pipefail
|
|
||||||
|
|
||||||
maintain_podman() {
|
|
||||||
# Two days seems to be a good happy-medium beween filling up
|
|
||||||
# about 40gig of storage space from moderate CI activity,
|
|
||||||
# and maintaining a useful level of caching.
|
|
||||||
while sleep "$CLEAN_INTERVAL"; do
|
|
||||||
if [[ -n "$PODMAN_RUNNER_DEBUG" ]]; then
|
|
||||||
echo "$(date --iso-8601=second) ${BASH_SOURCE[0] performing podman maintenance}"
|
|
||||||
fi
|
|
||||||
podman system prune --all --force
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
if [[ -z "$CLEAN_INTERVAL" ]]; then
|
|
||||||
echo "ERROR: Empty/unset \$CLEAN_INTERVAL"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
maintain_podman
|
|
||||||
18
podman.service
Normal file
18
podman.service
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=Podman API Service
|
||||||
|
Requires=podman.socket
|
||||||
|
After=podman.socket
|
||||||
|
Documentation=man:podman-system-service(1)
|
||||||
|
StartLimitIntervalSec=0
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Delegate=true
|
||||||
|
Type=exec
|
||||||
|
KillMode=process
|
||||||
|
Environment=LOGGING="--log-level=warn"
|
||||||
|
ExecStart=/usr/bin/podman $LOGGING system service
|
||||||
|
StandardOutput=journal+console
|
||||||
|
StandardError=inherit
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=default.target
|
||||||
11
podman.socket
Normal file
11
podman.socket
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=Podman API Socket
|
||||||
|
Documentation=man:podman-system-service(1)
|
||||||
|
|
||||||
|
[Socket]
|
||||||
|
ListenStream=/home/runner/podman.sock
|
||||||
|
SocketGroup=runner
|
||||||
|
SocketMode=0660
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=sockets.target
|
||||||
6
prune.service
Normal file
6
prune.service
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=Prune all disused podman volumes, images, and containers
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=oneshot
|
||||||
|
ExecStart=/usr/bin/podman system prune --all --force
|
||||||
6
prune.timer
Normal file
6
prune.timer
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=Execute the prune service periodically
|
||||||
|
|
||||||
|
[Timer]
|
||||||
|
OnCalendar=@@@PRUNE_INTERVAL@@@
|
||||||
|
RemainAfterElapse=no
|
||||||
7
runner.service
Normal file
7
runner.service
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=Gitlab-runner service
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
ExecStart=/usr/bin/gitlab-runner --log-level=warn run --user runner --working-directory=/home/runner
|
||||||
|
StandardOutput=journal+console
|
||||||
|
StandardError=inherit
|
||||||
109
setup.sh
Normal file
109
setup.sh
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
|
||||||
|
|
||||||
|
# This script is intended to be run during container-image build. Any
|
||||||
|
# other usage outside this context is likely to cause harm.
|
||||||
|
|
||||||
|
set -eo pipefail
|
||||||
|
|
||||||
|
for varname in PRUNE_INTERVAL RUNNER_VERSION TARGETARCH; do
|
||||||
|
if [[ -z "${!varname}" ]]; then
|
||||||
|
echo "Error: \$$varname must be non-empty."
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Make image smaller by not installing docs.
|
||||||
|
DNF="dnf --setopt=tsflags=nodocs -y"
|
||||||
|
|
||||||
|
for rpm in $(egrep -v '^(# )+' < /root/xpackages.txt); do
|
||||||
|
x+="--exclude=$rpm ";
|
||||||
|
done
|
||||||
|
|
||||||
|
set -x # show what's happening to make debugging easier
|
||||||
|
|
||||||
|
# DNF itself or a dependence may need upgrading, take care of it first.
|
||||||
|
$DNF upgrade
|
||||||
|
|
||||||
|
$DNF $x install \
|
||||||
|
podman \
|
||||||
|
systemd
|
||||||
|
|
||||||
|
# Gitlab-runner package contains scriptlets which do not function properly inside a
|
||||||
|
# container-build environment where systemd is not active/running.
|
||||||
|
$DNF $x --setopt=tsflags=noscripts install \
|
||||||
|
https://gitlab-runner-downloads.s3.amazonaws.com/$RUNNER_VERSION/rpm/gitlab-runner_${TARGETARCH}.rpm
|
||||||
|
|
||||||
|
# Allow removing dnf, sudo, etc. packages. Also don't start unnecessary or broken
|
||||||
|
# systemd services, like anything kernel related or login gettys.
|
||||||
|
rm -rf \
|
||||||
|
/etc/dnf/protected.d/* \
|
||||||
|
/etc/sytemd/system/getty.target.wants/* \
|
||||||
|
/etc/sytemd/system/multi-user.target.wants/* \
|
||||||
|
/etc/sytemd/system/sysinit.target.wants/* \
|
||||||
|
/etc/sytemd/system/timers.target.wants/* \
|
||||||
|
/lib/systemd/system/graphical.target.wants/* \
|
||||||
|
/lib/systemd/system/multi-user.target.wants/{getty.target,systemd-ask-password-wall.path} \
|
||||||
|
/lib/systemd/system/sys-kernel*.mount
|
||||||
|
|
||||||
|
# Remove unnecessary packages, see xpackages.txt to learn how this list was generated.
|
||||||
|
# This makes the image smaller and reduces the attack-surface.
|
||||||
|
dnf remove -y $(egrep -v '^(# )+' /root/xpackages.txt)
|
||||||
|
|
||||||
|
# Wipe out the DNF cache, then remove it entirely, again to make the image smaller.
|
||||||
|
$DNF clean all
|
||||||
|
rm -rf /var/cache/dnf /var/log/dnf* /var/log/yum.*
|
||||||
|
rpm -e dnf
|
||||||
|
|
||||||
|
# Workaround https://bugzilla.redhat.com/show_bug.cgi?id=1995337
|
||||||
|
rpm --setcaps shadow-utils
|
||||||
|
|
||||||
|
# Prevent copying of skel since it can interfere with the gitlab-runner
|
||||||
|
mkdir -p /home/podman /home/runner
|
||||||
|
# Guarantee uid/gid 1000 for user 'podman' / 1001 for user 'runner'.
|
||||||
|
groupadd -g 1000 podman
|
||||||
|
groupadd -g 1001 runner
|
||||||
|
# Separate users for services to increase process isolation.
|
||||||
|
# The 'podman' user's socket service writes /home/runner/podman.socket
|
||||||
|
useradd -M -u 1000 -g podman -G runner podman
|
||||||
|
useradd -M -u 1001 -g runner runner
|
||||||
|
# Allow 'podman' user to create socket file under /home/runner.
|
||||||
|
chmod 770 /home/runner
|
||||||
|
|
||||||
|
# Overwrite defaults, only user 'podman' permited to have a user-namespace
|
||||||
|
# Split the namespaced ID's around the containers root (ID 0) and the user
|
||||||
|
# IDs 1000 and 1001 (defined above) to prevent hijacking from a nested container.
|
||||||
|
echo -e "podman:1:999\npodman:1002:64533" | tee /etc/subuid > /etc/subgid
|
||||||
|
# Host volume mount necessary for nested-podman to use overlayfs2 for container & volume storage.
|
||||||
|
mkdir -p /home/podman/.local/share/containers
|
||||||
|
# Nested-container's local container-cache volume mount, recommended by gitlab-runner docs.
|
||||||
|
mkdir -p /cache
|
||||||
|
# Both the gitlab-runner and podman need access to the cache directory / volume mount.
|
||||||
|
chown podman:runner /cache
|
||||||
|
|
||||||
|
# Setup persistent 'podman' user services to start & run without a login.
|
||||||
|
mkdir -p /var/lib/systemd/linger
|
||||||
|
touch /var/lib/systemd/linger/podman
|
||||||
|
# Setup 'podman' socket and a container-storage pruning service for 'podman' user.
|
||||||
|
mkdir -p /home/podman/.config/systemd/user/{sockets.target.wants,default.target.wants}
|
||||||
|
cd /home/podman/.config/systemd/user/
|
||||||
|
ln -s $PWD/podman.socket ./sockets.target.wants/ # Added from Containerfile
|
||||||
|
ln -s $PWD/prune.timer ./default.target.wants/ # also from Containerfile
|
||||||
|
# Substitute value from --build-arg if specified, otherwise use default from Containerfile.
|
||||||
|
sed -i -e "s/@@@PRUNE_INTERVAL@@@/$PRUNE_INTERVAL/" ./prune.timer
|
||||||
|
# Containerfile ADD instruction does not properly set ownership/permissions.
|
||||||
|
chown -R 1000:1000 /home/podman
|
||||||
|
chmod 700 /home/podman
|
||||||
|
|
||||||
|
# Setup persistent 'runner' user services to start & run without a login.
|
||||||
|
touch /var/lib/systemd/linger/runner
|
||||||
|
mkdir -p /home/runner/.config/systemd/user/default.target.wants
|
||||||
|
cd /home/runner/.config/systemd/user/
|
||||||
|
# Does not depend on podman.socket file availablility, will retry if not present.
|
||||||
|
ln -s $PWD/runner.service ./default.target.wants/
|
||||||
|
# gitlab-runner will create side-car '.runner_system_id' file next to 'config.toml'
|
||||||
|
# on first startup. Ensure access is allowed. Also link to future config file
|
||||||
|
# presented as a container-secret.
|
||||||
|
mkdir -p /home/runner/.gitlab-runner
|
||||||
|
ln -s /var/run/secrets/config.toml /home/runner/.gitlab-runner/config.toml
|
||||||
|
# Containerfile ADD instruction does not properly set ownership/permissions.
|
||||||
|
chown -R runner:runner /home/runner
|
||||||
|
chmod -R 700 /home/runner/.gitlab-runner
|
||||||
21
xpackages.txt
Normal file
21
xpackages.txt
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
# This list was formed by running the following commands in the base image:
|
||||||
|
# for package in $(rpm -qa); do if dnf erase $package; then echo "$package" >> remove; fi; done
|
||||||
|
# cat remove
|
||||||
|
# Including those packages in this file. Finally, repeatedly running the container build
|
||||||
|
# untill no dependency errors were raised.
|
||||||
|
|
||||||
|
criu
|
||||||
|
criu-libs
|
||||||
|
crypto-policies-scripts
|
||||||
|
dejavu-sans-fonts
|
||||||
|
findutils
|
||||||
|
fonts-filesystem
|
||||||
|
gdb-gdbserver
|
||||||
|
langpacks-core-en
|
||||||
|
langpacks-core-font-en
|
||||||
|
langpacks-en
|
||||||
|
libnet
|
||||||
|
protobuf-c
|
||||||
|
rootfiles
|
||||||
|
vim-minimal
|
||||||
|
yum
|
||||||
Reference in New Issue
Block a user