Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for systemd v248+ #172

Merged
merged 4 commits into from
Nov 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ ENV PIP_DEFAULT_TIMEOUT 60

# Install the docker client for multiplatform builds
RUN apt update && \
apt install ca-certificates curl && \
apt -y install ca-certificates curl && \
install -m 0755 -d /etc/apt/keyrings && \
curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc && \
chmod a+r /etc/apt/keyrings/docker.asc && \
Expand Down
6 changes: 6 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -640,6 +640,12 @@ the run step:
# 'BUILDRUNNER_SYSTEMD'.
# If found, systemd=true will be assumed.
systemd: true/false
# (Ignored when systemd is not enabled)
# For systemd 248+, a read-write mount for /sys/fs/cgroup is required as well as a tmpfs mounted at /run, and
# this flag enables this behavior
# If this is ommitted, the image will be inspected for the label
# 'BUILDRUNNER_SYSTEMD_V248' and that value will be used instead.
systemd_v248: true/false

# Docker supports certain kernel capabilities, like 'SYS_ADMIN'.
# see https://goo.gl/gTQrqW for more infromation on setting these.
Expand Down
1 change: 1 addition & 0 deletions buildrunner/config/models_step.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ class RunAndServicesBase(StepTask):
ports: Optional[Dict[int, Optional[int]]] = None
pull: Optional[bool] = None
systemd: Optional[bool] = None
systemd_v248: Optional[bool] = None
containers: Optional[List[str]] = None
caches: Optional[Dict[str, Union[str, List[str]]]] = None

Expand Down
17 changes: 13 additions & 4 deletions buildrunner/docker/runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,8 @@ def start(
dns_search=None,
extra_hosts=None,
containers=None,
systemd=None,
systemd: bool = False,
systemd_v248: bool = False,
cap_add=None,
privileged=False,
): # pylint: disable=too-many-arguments,too-many-locals
Expand All @@ -172,11 +173,17 @@ def start(

security_opt = None
command = shell
tmpfs = {}
cgroupns = None
if systemd:
# If we are running in a systemd context,
# the following 3 settings are necessary to
# If we are running in a systemd context, the following 3 settings are necessary to
# allow services to run.
volumes["/sys/fs/cgroup"] = "/sys/fs/cgroup:ro"
if systemd_v248:
volumes["/sys/fs/cgroup/buildrunner.scope"] = "/sys/fs/cgroup:rw"
tmpfs["/run"] = ""
cgroupns = "host"
else:
volumes["/sys/fs/cgroup"] = "/sys/fs/cgroup:ro"
security_opt = ["seccomp=unconfined"]
command = "/usr/sbin/init"

Expand Down Expand Up @@ -225,6 +232,8 @@ def start(
security_opt=security_opt,
cap_add=cap_add,
privileged=privileged,
tmpfs=tmpfs,
cgroupns=cgroupns,
),
}
if entrypoint:
Expand Down
55 changes: 35 additions & 20 deletions buildrunner/steprunner/tasks/run.py
Original file line number Diff line number Diff line change
Expand Up @@ -598,6 +598,7 @@ def _start_service_container(self, name, service: Service):
)
self._service_runners[name] = service_runner
cont_name = self.step_runner.id + "-" + name
systemd = self.is_systemd(service, _image)
service_container_id = service_runner.start(
name=cont_name,
volumes=_volumes,
Expand All @@ -614,7 +615,8 @@ def _start_service_container(self, name, service: Service):
extra_hosts=_extra_hosts,
working_dir=_cwd,
containers=_containers,
systemd=self.is_systemd(service, _image, service_logger),
systemd=systemd,
systemd_v248=self.is_systemd_v248(systemd, service, _image),
)
self._service_links[cont_name] = name

Expand Down Expand Up @@ -1022,8 +1024,9 @@ def run(self, context: dict): # pylint: disable=too-many-statements,too-many-br
log=self.step_runner.log,
)
# Figure out if we should be running systemd. Has to happen after docker pull
container_args["systemd"] = self.is_systemd(
self.step, _run_image, self.step_runner.log
container_args["systemd"] = self.is_systemd(self.step, _run_image)
container_args["systemd_v248"] = self.is_systemd_v248(
container_args["systemd"], self.step, _run_image
)

container_id = self.runner.start(
Expand Down Expand Up @@ -1143,22 +1146,34 @@ def cleanup(self, context): # pylint: disable=unused-argument
for image in self.images_to_remove:
python_on_whales.docker.image.remove(image, force=True)

def is_systemd(self, run_service: RunAndServicesBase, image, logger):
"""Check if an image runs systemd"""
# Unused argument
_ = logger
def _get_label_is_truthy(self, image, label_name: str) -> bool:
labels = (
self._docker_client.inspect_image(image).get("Config", {}).get("Labels", {})
)
if not labels or label_name not in labels:
return False
# Labels will be set as the string value. Make sure we handle '0' and 'False'
value = labels.get(label_name, False)
return bool(value and value != "0" and value != "False")

rval = False
if run_service.systemd:
rval = run_service.systemd
else:
labels = (
self._docker_client.inspect_image(image)
.get("Config", {})
.get("Labels", {})
)
if labels and "BUILDRUNNER_SYSTEMD" in labels:
rval = labels.get("BUILDRUNNER_SYSTEMD", False)
def is_systemd(self, run_service: RunAndServicesBase, image: str) -> bool:
"""
Check if an image runs systemd
"""
if run_service.systemd is not None:
return run_service.systemd
return self._get_label_is_truthy(image, "BUILDRUNNER_SYSTEMD")

# Labels will be set as the string value. Make sure we handle '0' and 'False'
return bool(rval and rval != "0" and rval != "False")
def is_systemd_v248(
self, systemd: bool, run_service: RunAndServicesBase, image: str
) -> bool:
"""
Check if an image needs the changes for systemd v248+
"""
if not systemd:
# Do not run any other checks if we are not using systemd at all
return False

if run_service.systemd_v248 is not None:
return run_service.systemd_v248
return self._get_label_is_truthy(image, "BUILDRUNNER_SYSTEMD_V248")
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
from setuptools import setup, find_packages


BASE_VERSION = "3.13"
BASE_VERSION = "3.14"

SOURCE_DIR = os.path.dirname(os.path.abspath(__file__))
BUILDRUNNER_DIR = os.path.join(SOURCE_DIR, "buildrunner")
Expand Down
35 changes: 35 additions & 0 deletions tests/test-files/test-systemd.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,16 @@ steps:
run:
systemd: true
cmd: ps -p 1 -o cmd | tail -1 | grep /usr/sbin/init
test-systemd-v248-on:
build:
dockerfile: |
# Rocky linux 9 has 248+ installed
FROM {{ DOCKER_REGISTRY }}/rockylinux:9.0
RUN yum install -y procps-ng && yum clean all
run:
systemd: true
systemd_v248: true
cmd: ps -p 1 -o cmd | tail -1 | grep /usr/sbin/init

test-systemd-on-built:
build:
Expand All @@ -71,6 +81,16 @@ steps:
run:
cmd: ps -p 1 -o cmd | tail -1 | grep /usr/sbin/init

test-systemd-v248-on-built:
build:
dockerfile: |
FROM {{ DOCKER_REGISTRY }}/rockylinux:9.0
RUN yum install -y procps-ng && yum clean all
LABEL BUILDRUNNER_SYSTEMD=1
LABEL BUILDRUNNER_SYSTEMD_V248=1
run:
cmd: ps -p 1 -o cmd | tail -1 | grep /usr/sbin/init

{% for v in ["", "0", "False"]: %}
test-systemd-off-built-{{ v }}:
build:
Expand Down Expand Up @@ -98,3 +118,18 @@ steps:
image: {{ DOCKER_REGISTRY }}/rockylinux:8.5
pull: false
cmd: curl http://s1:8001 1>/dev/null 2>&1
test-systemd-v248-service:
run:
services:
s1:
build:
dockerfile: |
FROM {{ DOCKER_REGISTRY }}/rockylinux:9.0
RUN yum -y install python3 procps-ng && yum clean all
LABEL BUILDRUNNER_SYSTEMD=1
LABEL BUILDRUNNER_SYSTEMD_V248=1
systemd: true
cmd: ps -p 1 -o cmd | tail -1 | grep /usr/sbin/init && python3 -m http.server 8001
image: {{ DOCKER_REGISTRY }}/rockylinux:8.5
pull: false
cmd: curl http://s1:8001 1>/dev/null 2>&1
Loading