From 1cd06e54ae790d7863ba15ac7de3132dffbe2a33 Mon Sep 17 00:00:00 2001 From: Jonathan Lebon Date: Tue, 12 Nov 2024 10:49:51 -0500 Subject: [PATCH] builder/daemonless: pass through `/dev/kvm` if present Currently, if `devices.kubevirt.io/kvm` resources are requested in the build object, the resource request makes it to the build pod, but it doesn't really have any visible effect because the nested build process itself doesn't have access to it. The only reason we'd have `/dev/kvm` in our pod is if the user wants to use it in their build. So just pass it through if we find it. The use case for this is being able to build artifacts which would normally require privileges. One example includes base bootable container (bootc) images. Building these currently requires privileges because it itself uses containerization features. In the future, this should work with user namespacing, currently in Tech Preview. However, because we need not just uid 0 but `CAP_SYS_ADMIN`, and capabilities would still be restricted by default, we would still require access to non-default SCCs. (And of course, the builder would also have to be adapted to pass through the capabilities.) Another example is building disk images and shipping them in container images. This is done for example by Kubevirt and podman-machine. Two common ways to build disk images currently are via loopback devices or virtualization. The former can't be used because loopback devices are not namespaced and require privileges. This patch enables the latter. Using virtualization enables us to build these artifacts all while using the _default_ OpenShift restricted SCC. --- pkg/build/builder/daemonless.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/pkg/build/builder/daemonless.go b/pkg/build/builder/daemonless.go index b30fd03898..ab30d67234 100644 --- a/pkg/build/builder/daemonless.go +++ b/pkg/build/builder/daemonless.go @@ -298,6 +298,13 @@ func buildDaemonlessImage(sc types.SystemContext, store storage.Store, isolation // in runtime-tools's generator logic. seccompProfilePath := "/usr/share/containers/seccomp.json" + // If we have /dev/kvm, pass it down to the build process since it likely means + // that it was allocated to us with that expectation. + devices := []string{} + if _, err := os.Stat("/dev/kvm"); err == nil { + devices = append(devices, "/dev/kvm") + } + options := imagebuildah.BuildOptions{ ContextDirectory: contextDir, PullPolicy: pullPolicy, @@ -334,6 +341,7 @@ func buildDaemonlessImage(sc types.SystemContext, store storage.Store, isolation MaxPullPushRetries: DefaultPushOrPullRetryCount, PullPushRetryDelay: DefaultPushOrPullRetryDelay, SkipUnusedStages: types.OptionalBoolFalse, + Devices: devices, } if os.Getenv("BUILDAH_QUIET") == "true" {