Compressing the root file system represents using an algorithm like gzip, zstd, etc. to reduce the size of the rootfs on disk.
This has the added benefit of reducing the time it takes to push the image to the Unikraft Cloud platform, as you transfer less data.
It also means that the size on disk on the host side reduces, which can be beneficial when dealing with many images or large images.
This size can drop depending on the contents of the rootfs and the compression algorithm used.
For example, text files often compress by up to 90% and more, whilst already compressed files like images or videos don't compress well at all.
Getting started
The Unikraft Platform supports both compressed and uncompressed rootfses, but it's highly recommended to use uncompressed ones if size allows. Decompressing is a step done by the kernel at boot time, resulting in slower access times across the board. That's why the first attempt at using the platform should always be with uncompressed rootfses.
Both formats, CPIO and EROFS, support compression.
CPIO does full file system compression (like running zip on the file).
EROFS does per-block compression meaning that the system decompresses only the accessed blocks on-the-fly.
Both of them support most compression algorithms, but the recommended ones are those that have fast decompression speeds like lz4hc.
As presented in the rootfs formats tutorial and in the FAQ, the performance characteristics of the two formats differ.
When using compression, the system amplifies these differences further.
For CPIO, the system must decompress the entire archive first before using it.
This means that boot times increase further, and memory usage during boot is also higher negating the benefit of using compression in the first place.
EROFS is better, as the system decompresses only the accessed blocks on-the-fly, meaning that boot times are less affected, and memory usage is also kept lower.
This has the added downside that Direct Access (DAX) isn't possible when using compression, as the host side can't map a compressed image into guest memory.
This caveat results in having to load the entire compressed rootfs into guest memory, increasing memory usage by at least the size of the compressed rootfs.
Still, if many files aren't accessed in boot, the cold boot time might decrease compared to an uncompressed EROFS rootfs.
Packaging a Compressed rootfs
Packaging a compressed rootfs is different depending on the format used.
The kraft CLI implements CPIO compression directly, while EROFS compression must happen externally using the mkfs.erofs tool.
CPIO Compression
To package a compressed CPIO rootfs using kraft, you can use the --compress flag when running the kraft pkg or kraft cloud deploy command.
This uses gzip compression to compress the initrd file before packaging it into a OCI image and uploading it to the Unikraft Cloud platform.
Code
EROFS Compression
Currently, kraft has no direct support for compressing EROFS rootfses.
To package a compressed EROFS rootfs, you need to use the mkfs.erofs tool before packaging it with kraft.
To do this you will also have to first export the image built from the Dockerfile into a tar archive:
Code
You can then use the resulting tar archive to create a compressed EROFS rootfs using the following command.
Note that you can change the compression algorithm and level by modifying the -z option.
In this example the level is 9 (maximum) and the algorithm is lz4hc (high compression lz4):
Code
Finally, you can package and deploy the compressed EROFS rootfs using kraft:
Code
Performance of Compressed rootfs vs. Uncompressed rootfs Images
To illustrate the performance differences between compressed and uncompressed rootfses, below you can see the same node-22 image packaged and deployed four times:
-
Uncompressed
CPIOUncompressed CPIO -
Compressed
CPIOCompressed CPIO -
Uncompressed
EROFSUncompressed EROFS -
Compressed
EROFSCompressed EROFS
Results
| rootfs Type | Compression | Image Size | Boot Time | Instance Memory Usage |
|---|---|---|---|---|
| CPIO | No | 824 MiB | 621.28 ms | 2400 MiB |
| CPIO | Yes (gzip) | 299 MiB | 2079.74 ms | 2400 MiB |
| EROFS | No | 830 MiB | 121.75 ms | 900 MiB |
| EROFS | Yes (lz4hc) | 410 MiB | 92.36 ms | 900 MiB |
As expected from the previous assumptions, the compressed CPIO rootfs boots slower than the uncompressed one. This happens due to the need to decompress the entire archive before use. EROFS performs better in both compressed and uncompressed forms, compared to CPIO. The compressed EROFS rootfs boots even faster than the uncompressed one. This is likely due to the reduced amount of data that the system reads from disk, resulting in faster access times despite the decompression overhead. This only happens in the cold boot scenario. In warm boots, the uncompressed EROFS rootfs tops the charts as the system needs no decompression at all on demand.
Conclusion
As a rule of thumb, use uncompressed rootfses whenever possible and try to always use EROFS over CPIO for better performance.
If limited by size constraints, try using compressed EROFS rootfses with a fast decompression algorithm like lz4hc.
Learn more
- The rootfs formats tutorial for understanding the differences between
CPIOandEROFS. - The
mkfs.erofsdocumentation for more information on creating compressedEROFSfile systems. - The
kraft cloudcommand-line tool reference, and in particular the deploy subcommand. - The
kraft pkgcommand reference for packaging images.