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 such as Podman.
Configure /dev/fuse for unprivileged builds in pods
You can grant an unprivileged pod the capability to perform Filesystem in Userspace (FUSE) mounts by exposing the /dev/fuse device. With this setup, an unprivileged user within the pod can use tools such as 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.
You expose the /dev/fuse device by adding the io.kubernetes.cri-o.Devices: "/dev/fuse" annotation to your pod definition.
Procedure
-
Define the pod with
/dev/fuseaccess:-
Create a YAML file named
fuse-builder-pod.yamlwith the following content:apiVersion: v1kind: Podmetadata:name: fuse-builder-podannotations:io.kubernetes.cri-o.Devices: "/dev/fuse"spec:containers:- name: build-containerimage: quay.io/podman/stablecommand: ["/bin/sh", "-c"]args: ["echo 'Container is running. Use oc exec to get a shell.'; sleep infinity"]securityContext:runAsUser: 1000where:
metadata.annotations- Specifies that the
io.kubernetes.cri-o.Devices: "/dev/fuse"annotation makes the FUSE device available. spec.containers.image- Specifies a container that uses an image that includes
podman(for example,quay.io/podman/stable). spec.containers.args- Specifies a command to keep the container running so you can
execinto it. spec.containers.securityContext- Specifies a
securityContextthat runs the container as an unprivileged user (for example,runAsUser: 1000).
noteDepending 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 by running the following command:
$ 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 by running the following command:$ oc exec -ti fuse-builder-pod -- /bin/bashYou are now inside the container.
-
Because the default working directory might not be writable by an unprivileged user, change to a writable directory such as
/tmpby running the following commands:$ cd /tmp$ pwd/tmp
-
-
Create a dockerfile and build an image by 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 <<EOFFROM registry.access.redhat.com/ubi9/ubi-minimalRUN microdnf install -y findutils && microdnf clean allRUN echo "This image was built inside a pod with /dev/fuse by user $(id -u)" > /app/build_info.txtCOPY Dockerfile /app/Dockerfile_copiedWORKDIR /appCMD ["sh", "-c", "cat /app/build_info.txt && echo '--- Copied Dockerfile ---' && cat /app/Dockerfile_copied"]EOF -
Build the image by running the following command. 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 by running the following command:$ 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 by running the following command:
$ exit
- Delete the pod if it is no longer needed by running the following command:
$ oc delete pod fuse-builder-pod
- Remove the local YAML file by running the following command:
$ rm fuse-builder-pod.yaml
- After you are done, exit the shell session in the pod by running the following command: