Accessing faster builds with /dev/fuse
You can configure your pods with the /dev/fuse device to enable faster and more efficient container image builds, particularly for unprivileged users. This device allows unprivileged pods to mount overlay filesystems, which can be leveraged by tools like Podman.
Configuring /dev/fuse for unprivileged builds in pods
By exposing the /dev/fuse device to an unprivileged pod, you grant it the capability to perform Filesystem in Userspace (FUSE) mounts. This is achieved by adding the io.kubernetes.cri-o.Devices: "/dev/fuse" annotation to your pod definition. This setup allows an unprivileged user within the pod to use tools like podman with storage drivers such as fuse-overlayfs by mimicking privileged build capabilities in a secure and efficient manner without granting full privileged access to the pod.
-
Define the pod with
/dev/fuseaccess:-
Create a YAML file named
fuse-builder-pod.yamlwith the following content:apiVersion: v1 kind: Pod metadata: name: fuse-builder-pod annotations: io.kubernetes.cri-o.Devices: "/dev/fuse" spec: containers: - name: build-container image: quay.io/podman/stable command: ["/bin/sh", "-c"] args: ["echo 'Container is running. Use oc exec to get a shell.'; sleep infinity"] securityContext: runAsUser: 1000where:
io.kubernetes.cri-o.Devices-
The
io.kubernetes.cri-o.Devices: "/dev/fuse"annotation makes the FUSE device available. image-
This annotation specifies a container that uses an image that includes
podman(for example,quay.io/podman/stable). args-
This command keeps the container running so you can
execinto it. securityContext-
This annotation specifies a
securityContextthat runs the container as an unprivileged user (for example,runAsUser: 1000).Note
Depending on your cluster’s Security Context Constraints (SCCs) or other policies, you might need to further adjust the
securityContextspecification, for example, by allowing specific capabilities if/dev/fusealone is not sufficient forfuse-overlayfsto operate.
-
Create the pod by running the following command:
$ oc apply -f fuse-builder-pod.yaml
-
-
Verify that the pod is running:
$ oc get pods fuse-builder-pod -
Access the pod and prepare the build environment:
After the
fuse-builder-podpod is in theRunningstate, open a shell session into thebuild-containerenvironment:$ oc exec -ti fuse-builder-pod -- /bin/bashYou are now inside the container. Because the default working directory might not be writable by the unprivileged user, change to a writable directory like
/tmp:$ cd /tmp$ pwd/tmp -
Create a dockerfile and build an image using Podman:
Inside the pod’s shell and within the
/tmpdirectory, you can now create aDockerfileand usepodmanto build a container image. Iffuse-overlayfsis the default or configured storage driver, Podman is able to leveragefuse-overlayfsbecause of the available/dev/fusedevice.-
Create a sample
Dockerfile:$ cat > Dockerfile <<EOF FROM registry.access.redhat.com/ubi9/ubi-minimal RUN microdnf install -y findutils && microdnf clean all RUN echo "This image was built inside a pod with /dev/fuse by user $(id -u)" > /app/build_info.txt COPY Dockerfile /app/Dockerfile_copied WORKDIR /app CMD ["sh", "-c", "cat /app/build_info.txt && echo '--- Copied Dockerfile ---' && cat /app/Dockerfile_copied"] EOF -
Build the image using
podman. The-tflag tags the image:$ podman build -t my-fuse-built-image:latest .You should see Podman executing the build steps.
-
-
Optional: Test the built image:
Still inside the
fuse-builder-pod, you can run a container from the image you just built to test it:$ podman run --rm my-fuse-built-image:latestThis should output the content of the
/app/build_info.txtfile and the copied Dockerfile. -
Exit the pod and clean up:
-
After you are done, exit the shell session in the pod:
$ exit -
Delete the pod if it’s no longer needed:
$ oc delete pod fuse-builder-pod -
Remove the local YAML file:
$ rm fuse-builder-pod.yaml
-