В подобной задаче: у нас были сотни миллионов файлов мы их хранили на виртуальных дисках. Одна из причин такого подхода - это ограничение по inode и по iops.
На низлежащей базовой файловой системе эти файлы не хранили, а только на виртуальных дисках.
Таким подходом решались следующие проблемы:
1. Cнимались проблемы с количеством inode
2. Двигать виртуальные диски быстрее, т.к. копирование образа идет с наиболее эффективной скоростью, чем пофайлово. т.е. любые перемещения, перекладки, преобразование хранилища давались меньшей кровью.
3. Делать резервное копирование проще с образами, чем с миллионами файлов.
4. Если вдруг рухнет какая-то файловая система, то она может рухнуть, не утащив за собой все. да, мы попутно разделяли на разные блочные устройства. Чтобы доступ к одному блочному устройству не вешал всю систему.
при это rootfs вообще лучше сделать маленьким и разместить в RAM. Надо сказать, что с разрушением фс на сторадже мы не сталкивались, несмотря на бутерброд: drbd -> ext4 -> loop image -> ext4
5. За счет loop имиджей достигалась экономия пространства за счет оверселлинга: суммарные объем внутри виртуальных дисков мог быть равным или превышать объем низлежащего блочного устройства. Конечно за этим надо следить. Этому помогал zabbix и статичность хранимых файлов.
6. Для прикладных приложений все оставалось обычными файлами. Не пришлось менять код.
В момент создания этого проекта технологий было меньше чем сейчас, еще меньше было проверенных технологий. Все облачные масштабируемые хранилища слишком медленные и не дают прямого доступа к файлам.
Поэтому использовали обычный набор:
1. DRBD для сетевого зеркаливания между нодами.
2. EXT3/EXT4 инициализированные с большим количеством inode.
3. loop images - штатная возможность создания блочных устройств в файлах.
4. sparse files - технология пропуска пустых блоков внутри файла.
5. обычные symlinks.
Несмотря на некоторую сложность в начале, подход себя оправдал.
По монтированию все выглядит примерно так:
root /
+- block device ext4
+- block device ext4
+- block device ext4
...
Внутри каждого блочного устройства block device ext4:
vdisk0.img
vdisk1.img
vdisk2.img
...
Монтируются они все в каталоги в дерево виртуального хранилища:
/virtstore
+- virtfolder0
+- virtfolder1
+- virtfolder2
...
За счет древовидной структуры каталогов, симлинков получали более менее пригодную схему для работы
Что еще можно сделать:
1. для миллионов мелких файлов можно в образе диска использовать btrfs со сжатием. для доступа только на чтение получается серьезная экономия по месту. но только в режиме чтения. при перезаписи плотность "упаковки" падает.
2. для интенсивной записи нужно разнести запись на разные блочные устройства. Чем больше физических блочных устройств, тем легче расшить узкие места по нагрузке и получить приемлемую производительность всей системы.
Для примера, команды для работы:
Создаем sparse имидж на 850 гб
dd if=/dev/zero bs=1M seek=850000 count=1 of=/path/to/image.img
либо
truncate -s 850G /path/to/image.img
Инициализация ФС:
mkfs.ext4 -m 0 -O dir_index -O resize_inode -t ext4 /path/to/image.img
Монтируем имидж:
mount -o loop /path/to/image.img /path/to/mount/point/
Для ускорения работы, монтировать лучше с оптимизированным параметрами монтирования, например:
rw,nosuid,nodev,noatime,nodiratime,strictatime
Соответственно такие образы можно монтировать, размонтировать, копировать и двигать. Можно уменьшать и увеличивать размер такого образа.