# tmpfs и overlayfs - RAM-disk и слои _Файловая система · LinuxLab Knowledge Base_ **TL;DR:** tmpfs - ФС в RAM (с swap'ом). Дефолт для /run, /dev/shm, часто /tmp. overlayfs - lower + upper = merged: RO-база + RW-слой над ней. Основа Docker (overlay2), Live-ISO, immutable distro. ## Зачем эти псевдо-ФС Не всё хранится на диске. Linux умеет: - **tmpfs** - ФС в RAM, может swap'ить - **overlayfs** - объединить две (или больше) ФС в одну view - **devtmpfs** - `/dev` с динамическими node'ами - **proc**, **sysfs** - интерфейсы к ядру tmpfs и overlayfs - две самые часто используемые в проде. ## tmpfs - RAM-disk ### Где встречается по дефолту ```bash $ mount | grep tmpfs tmpfs on /run type tmpfs (rw,nosuid,nodev,size=...) tmpfs on /run/lock type tmpfs (rw,nosuid,nodev,noexec,relatime) tmpfs on /dev/shm type tmpfs (rw,nosuid,nodev,inode64) tmpfs on /run/user/1000 type tmpfs (rw,nosuid,nodev,relatime,size=...) ``` Системные tmpfs: | Mount | Зачем | |-------|-------| | `/run` | состояние демонов после boot'а (PID-файлы, сокеты) | | `/run/lock` | lock-файлы | | `/run/user/$UID` | per-user runtime (X11/wayland, dbus, systemctl --user) | | `/dev/shm` | shared memory сегменты POSIX (`shm_open`) | | `/tmp` (часто) | временные файлы; на серверах часто на диске | ### Создать свой tmpfs ```bash sudo mount -t tmpfs -o size=2G,mode=1777 tmpfs /mnt/cache ``` Опции: | Опция | Что | |-------|-----| | `size=N` | максимум; default - 50% RAM | | `nr_inodes=N` | максимум inode | | `mode=1777` | права на корень (1777 = sticky как /tmp) | | `uid=`, `gid=` | владелец | | `noexec`, `nosuid`, `nodev` | hardening | | `huge=advise` | использовать transparent huge pages | В fstab: ```fstab tmpfs /mnt/cache tmpfs size=2G,mode=1777,noexec,nosuid,nodev 0 0 ``` ### tmpfs vs ramfs Старая `ramfs` - просто RAM, без swap, без size-limit. Опасна: можно её заполнить и подвесить машину. **Не используй** - tmpfs её заменяет на 100%. ### tmpfs и swap По дефолту tmpfs может попасть в [[swap|swap]]. Это плюс (не падает на ENOSPC при превышении RAM), и минус (медленнее). В контейнерах часто запрещают swap - тогда tmpfs ограничена RAM. Файл в tmpfs не подгружается через page cache (он **уже в RAM**) - чтение быстрое, но не "free": `RES` процессов не учитывает tmpfs. Часто на 16GB-машине из-за tmpfs `free -h` показывает "доступно 8GB". ### Когда использовать - Build-кэши (`/tmp` под `cargo`/`go build` - в разы быстрее на HDD) - Сессии веб-приложений - Inter-process queues (но лучше unix-сокеты или shm POSIX) - Тестовая ФС в CI - быстрая mkfs+mount без блочного устройства (но это уже не tmpfs, а loop+tmpfs) ## overlayfs - слои ### Идея Берёшь две (или больше) директорий: одна - **lower** (read-only база), другая - **upper** (changes layer). Монтируешь их через overlayfs - получаешь **merged**: вид "lower + upper", где запись идёт в upper. ``` lower: /var/lib/docker/.../l1 ├─ /etc/passwd ├─ /usr/bin/sh upper: /var/lib/docker/.../diff └─ /etc/passwd ← переписали merged: /var/lib/docker/.../merged ├─ /etc/passwd ← из upper └─ /usr/bin/sh ← из lower ``` - Чтение существующего файла - lower (если в upper нет) - Запись существующего файла - **copy-up** в upper, потом запись в copy - Удаление - **whiteout** marker в upper - Создание директории - в upper ### Mount ```bash mount -t overlay overlay \ -o lowerdir=/lower,upperdir=/upper,workdir=/work \ /merged ``` - **lowerdir** - база (read-only); может быть несколько через `:` (`l1:l2:l3`) - **upperdir** - changes; должен быть на той же ФС что workdir - **workdir** - служебная пустая директория, нужна для атомарных операций - **lowerdir БЕЗ upper/work** - read-only overlay (всё read-only) Несколько lower: ```bash mount -t overlay overlay \ -o lowerdir=/l1:/l2:/l3,upperdir=/up,workdir=/work /merged ``` Поиск файла идёт **сверху вниз**: `l1` побеждает `l2`, `l2` побеждает `l3`. ### Где встречается - **Docker overlay2** storage driver - каждый image-слой = lower, container changes = upper - **podman**, **containerd** - тот же overlayfs - **Live-ISO** - read-only ISO как lower, tmpfs как upper - **OSTree / Fedora Silverblue / NixOS** - immutable system - **systemd-sysext** / **confext** - расширения системы поверх RO root'а - **CI build кэш** - layers per-step ### Ограничения - **Не nested без труда** - lower не должен быть overlayfs (на новых ядрах можно через `redirect_dir=on`, но осторожно) - **No NFS lower** на старых ядрах (5.10+ работает) - **selinux/security-context** - upper должен поддерживать xattr, `tmpfs` его поддерживает с ядром 6+, раньше нужна была ext4/xfs - **inode-номера** меняются между lower и upper - ломает hardlink-deduplication ### Команды и проверка ```bash mount | grep overlay # все overlayfs-mount'ы cat /proc/self/mounts | grep overlay findmnt -t overlay ``` Внутри Docker контейнера `/proc/self/mountinfo` показывает все слои: ```bash awk '$5=="/" { print $4 }' /proc/self/mountinfo ``` ## tmpfs + overlayfs = живой Live-USB ```bash # / - read-only с ISO mount -t squashfs -o ro /dev/sr0 /mnt/iso/ # tmpfs для изменений mount -t tmpfs tmpfs /mnt/upper mkdir /mnt/upper/data /mnt/upper/work # Объединить mount -t overlay overlay \ -o lowerdir=/mnt/iso,upperdir=/mnt/upper/data,workdir=/mnt/upper/work \ /mnt/merged ``` Изменения в `/mnt/merged` пишутся в RAM. После перезагрузки ISO снова чистый. ## Когда что-то пошло не так - **`tmpfs: Bad value for ...`** - неверная опция; на старых ядрах нет `inode64` или `huge=`. - **tmpfs съел всю RAM, OOM** - не указали `size=`. Default 50% может вылиться в OOM при набивке. Всегда `size=N` явно. - **overlayfs `Invalid argument`** - `lowerdir` и `upperdir` на разных ФС, либо `workdir` не пустой, либо отсутствует, либо нет xattr-поддержки на upper. - **`Operation not supported` при copy-up** - upper-FS не поддерживает нужные xattr (старая или специфичная). Только ext4/xfs/btrfs/tmpfs(>=6.0). - **Docker диск распух непонятно** - удалённые файлы в верхнем слое не освобождают место в нижнем (lower иммутабелен). Нужен `docker image prune` и пересборка. - **Файл "пропал" после chown в overlayfs** - copy-up прав может отличаться от lower. Проверь `ls -l` на обеих сторонах. ## Команды ```bash sudo mount -t tmpfs -o size=1G,mode=1777,noexec tmpfs /mnt/cache ``` Создать tmpfs на 1GB - быстрый кэш для билда/тестов ```bash df -h | grep tmpfs ``` Все смонтированные tmpfs и сколько занято - быстрый аудит RAM-затрат ```bash mount | grep overlay ``` Все overlayfs - в Docker-хосте обычно много (по одному на контейнер) ```bash sudo mount -t overlay overlay -o lowerdir=/base,upperdir=/changes,workdir=/work /merged ``` Базовое overlayfs-монтирование - lower RO, upper RW, merged - результат ```bash findmnt -t tmpfs,overlay ``` Иерархичный список pseudo-ФС - быстрый view с флагами ```bash mount -t tmpfs -o remount,size=2G tmpfs /tmp ``` Изменить лимит размера tmpfs на лету - без размонтирования ```bash stat -c '%T' -f /tmp ``` Тип ФС текущей mountpoint - подтвердить что /tmp реально tmpfs ## См. также - [bind mount - монтирование каталога в другое место](/kb/bind-mount.md) - [mount и /etc/fstab - подключение ФС](/kb/mount-and-fstab.md) - [Linux namespaces](/kb/namespaces.md) - [Filesystem Hierarchy Standard (FHS)](/kb/fhs.md) - [Swap - когда RAM кончается](/kb/swap.md)