How can I mount a btrfs filesystem on a GitLab hosted CI runner?

Problem to solve

I’m developing a tool to manage btrfs snapshots. For testing, it requires a real btrfs filesystem to be mounted on the system. I haven’t found any meaningful way to stub or fake this out.

I want to run my tests on GitLab-hosted CI, but I can’t seem to mount btrfs filesystems from within docker, despite that the containers run with --privileged. I reckon the btrfs module isn’t mounted on the host, but I can’t find a way to load the module from the container.

Steps to reproduce / Configuration

A minimal gitlab-ci.yml to reproduce:

stages:                                                                         
- test                                                                          
                                                                                
repro:                                                                          
  stage: test                                                                   
  image: alpine                                                                 
  script:                                                                       
  - apk add btrfs-progs                                                         
  - truncate -s $((1024*1024*1024)) /test.dd                                    
  - mkfs.btrfs /test.dd                                                         
  - mount -o loop /test.dd /mnt   

I ran this and got:

$ mount -o loop /test.dd /mnt
mount: mounting /dev/loop0 on /mnt failed: Invalid argument

Investigation, alternatives and workarounds

If I run the steps outlined above with docker run --privileged on my laptop, if the btrfs module is not loaded, I also get Invalid argument.

If I modprobe btrfs on the host, before or after the container is created, the mount succeeds.

In another gitlab-ci.yml test I confirmed that cat /proc/filesystems does not contain btrfs.

Elsewhere I’ve seen that when a docker container requires a specific module, one practice is to mount /lib/modules as a volume and let the container load modules as necessary. See linuxserver-wireguard for an example. On GitLab, I don’t see /lib/modules mounted in the runner, nor a way to cause this.

I imagine I could run my tests in qemu, which would remove the need to run tests as root, but would require a lot of work to make a test harness to do this, and possibly rewriting all my tests to make use of it.

I can’t think of any other workarounds.

Versions

  • Self-managed
  • GitLab.com SaaS
  • Self-hosted Runners