Ken Muse

Mounting Files as Volumes


Continuing the explorations from last week, there are other primitives in Linux that can help with containerized workloads (and Kubernetes). Containers mount volumes in order to share data between the host and the container (or between multiple containers). Kubernetes drivers prefer to mount entire drives as volumes. This ensures that the data is isolated and reduces the risk of a workload gaining access to the host system. On the other extreme, folders can be mounted as volumes. This makes more efficient use of the file system, but can increase the security risk.

There is another approach that is the basis for some third-party CSI (Container Storage Interface) drivers. This approach mounts individual files and treats them as volumes. This combines the benefits of both methods. It encapsulates the file system and restrict navigation on the host. At the same time, it allows the hard drive to be sliced into multiple independent volumes, potentially making more efficient use of the available space.

This post is not about covering the tradeoffs with this approach or how to implement it in Kubernetes. Instead, I want to show you how this works under the covers. To do this, we’ll use a loop device. If you’re not familiar with the term, a loop device simply makes a file look like a block device (drive).

First, we need to create a blank file:

1dd if=/dev/zero of=/mydrive.img bs=1024 count=51200

This command reads 1024 bytes from /dev/zero and writes them to the file /mydrive.img, repeating this 51,200 times. This creates a 50MiB file, initialized with zeros. Now, we need to create a loop device that will treat this file as a blank drive.

1# Find the next available loop device (such as /dev/loop0) and store it in a variable
2DEVICE=$(losetup -f)
3
4# Create a loop device for the file
5losetup $DEVICE /mydrive.img

You can verify the loop device was created by typing losetup. In this case, it shows the device /dev/loop0 is now backed by the file /mydrive.img:

1# losetup
2NAME       SIZELIMIT OFFSET AUTOCLEAR RO BACK-FILE    DIO LOG-SEC
3/dev/loop0         0      0         0  0 /mydrive.img   0     512

Now that the file is mounted as loop device, it can be formatted with a file system. For this example, I’ll use ext4:

1mkfs -t ext4 -v $DEVICE

The file now contains a formatted file system and is ready to be mounted:

1mkdir /mnt/mydrive
2mount $DEVICE /mnt/mydrive

It’s now possible to navigate to /mnt/mydrive and create additional files and folders. As those changes are made, they are stored in the file /mydrive.img. That file is now holding an entire file system.

To unmount the file system and remove the loop device:

1umount /mnt/mydrive
2losetup -d $DEVICE

And that’s all there is to creating and using a file as a drive in Linux! Now you understand how to use the Linux command line to create and use this technique. In a future post, we can look at how this is used by CSI drivers in Kubernetes.