ZFS: все в одном — RAID, LVM, сжатие и шифрование

ZFS: все в одном — RAID, LVM, сжатие и шифрование

Иван Коваленко
Иван Коваленко Системный администратор
26 июня 2025

Рассказываем об архитектуре ZFS — без воды и излишних деталей.

Изображение записи

Допустим, вы используете mdadm для отказоустойчивости, bcache — для ускорения медленных HDD, cryptsetup — для шифрования данных, LVM — потому что нужно создавать в рейде несколько блочных устройств, и btrfs — за любовь к сжатию и снапшотам. А теперь представьте, что все это можно заменить одной файловой системой — ZFS. Но как именно? Разберемся в ее устройстве.

Архитектура ZFS

Отправная точка — пул (zpool), именно он создается в первую очередь. Пул расположен на виртуальном устройстве (vdev), которое, в свою очередь, может находиться на одном или нескольких физических дисках. Привычных уровней рейда здесь нет: в ZFS используется уникальный тип отказоустойчивого массива — raidz. Однако почти все его варианты вам покажутся уже знакомыми.

  • stripe — данные распределяются по дискам, без избыточности. По сути — RAID 0.
  • mirror — данные пишутся зеркально на два (или больше) диска. Похоже на RAID 1.
  • raidz1 — данные распределены по всем дискам, но есть избыточность. fault tolerance — один диск (именно это и означает цифра в типе raidz). Аналог RAID 5.
  • raidz2 — тот же raidz1, но с избыточностью в два диска: zpool продолжит работу, даже если они оба выйдут из строя. Прямо как в RAID 6.
  • raidz3 — допускается выход из строя сразу трех дисков. Прямых аналогов среди классических уровней RAID нет. 

Dataset и Volume

Внутри zpool можно создать volume и dataset. С dataset все понятно: это та самая файловая система, которую мы можем примонтировать и сложить туда файлы. А вот volume — это уже интереснее. Такая сущность встречается в LVM, но не в обычных ФС. Формально это такой же dataset, но без файловой системы внутри, который нельзя примонтировать, но можно использовать как блочное устройство (в DevFS — /dev/{zvol0,zvol1,zvol2,…}). При этом для него будут применимы все фичи ZFS — например, сжатие, шифрование, кэширование и снапшоты. И все это — внутри отказоустойчивого zpool. Удобно! 

Использовать volume можно как диск ВМ или для iSCSI, когда вам нужен сетевой диск на одном из серверов. На этом же уровне реализованы сжатие и шифрование, причем для разных dataset и volume можно использовать разные настройки (алгоритмы шифрования и/или сжатия, ключи шифрования).

Кэширование в ZFS: чтение и запись 

Юмористическая иллюстрация.

Чтобы понять, как устроено кэширование, разберемся, как данные попадают в zpool и как они оттуда читаются. Кто-то может возразить, что у ZFS нет функции кэширования записи, но будут правы лишь формально. Начнем с того, что существует два типа записи: асинхронная — например, через системный вызов aio_write() или write() без флага O_SYNC, а также синхронная — например, тот же write(), но с O_SYNC.

В случае асинхронной записи ZFS работает как большинство кэшируемых систем: сначала сохраняет данные в оперативной памяти, а затем в фоновом режиме записывает их в zpool. Минус очевиден — есть риск потери данных при внезапном отключении питания, сбое ядра и любом другом негативном сценарии. Однако для асинхронной записи это допустимо.

Синхронная запись требует полной надежности, поэтому перед записью в zpool данные временно попадают в «лимб» — ZIL (ZFS Intent Log). Его задача — обеспечение целостности записываемых в zpool данных, чтобы непредвиденная остановка работы системы не привела к потере записываемых данных. 

Все изменения в ZIL собираются в группы транзакций (TXG) и вносятся в zpool одним большим блоком. Это работает благодаря методу записи ZFS: при изменении блока обновленные данные записываются в новое место, а старый блок помечается как свободный. Такой подход избавляет от необходимости изменять данные мелкими блоками на месте, снижает фрагментацию и ускоряет операции ввода-вывода.

Визуализация работы ФС.
Как работает файловая система с копированием при записи. Запись новой версии блока и разблокировка старой. Источник.

По указанной причине zpool нельзя заполнять «под завязку». Если не останется свободного места, даже удаление файлов станет невозможным, и пул уйдет в режим read-only. Чтобы избежать деградации производительности, рекомендуем оставлять около 10% свободного пространства.

Такой подход к записи помогает сократить количество операций ввода-вывода с мелкими блоками, где даже топовые «blazing-fast Gen5 Ultra Mega SSD Max» показывают достаточно слабые результаты. Что уж говорить о HDD.

Запись: ZIL и SLOG

По умолчанию ZIL находится в zpool, что может показаться странным: это не дает прироста в скорости, а данные пишутся дважды, сокращая ресурс SSD. Однако ZIL существует не просто так: его можно вынести на отдельный vdev — SLOG.

Несколько рекомендаций по размещению SLOG.

  • Используйте отдельный vdev с резервированием (обычно используют mirror) — на случай сбоя.
  • Выбирайте устройства с минимальной задержкой записи и хорошей работой с «мелкоблочкой» — подойдут SLC SSD или Intel Optane.

Когда я только начинал изучать ZFS, часто натыкался на рекомендации: «Вам не нужен больший объем SLOG — ведь у TXG есть таймаут, по истечении которого ZFS будет синхронно ждать ее внесения в zpool». Однако это вредный совет: если придерживаться его, то каждые пять секунд ZFS будет вносить все изменения из ZIL в zpool. Также новые операции записи будут выполняться намного дольше. 

Таймаут TXG — это настраиваемый параметр, так что вам ничего не мешает указать его на ваше усмотрение — хоть до нескольких минут. Так вы увеличите эффективно используемое пространство SLOG.

Итог: SLOG — это фактически кэш для синхронной записи в ZFS. Он может быть практически любых размеров и при правильной конфигурации дает заметный прирост производительности.

Чтение: ARC и L2ARC

С чтением все проще, чем с записью. ZFS кэширует наиболее часто используемые блоки (MFU) и недавно прочитанные (MRU) прямо в оперативной памяти. Как можно догадаться, обращение к ним происходит очень быстро! Этот кэш называется ARC (Adaptive Replacement Cache).

Размер ARC — это тоже настраиваемая сущность (в OpenZFS — по умолчанию половина от установленной ОЗУ). При этом в ARC реализован предиктивный механизм — например если вы прочитали последовательно несколько блоков файла, то ZFS заранее подгрузит в кэш несколько последующих блоков еще до того, как вы их запросите. 

Если блоки вытесняются из ARC, они могут быть отправлены во второй уровень кэша — L2ARC, если он настроен. L2ARC располагается на отдельном cache vdev, избыточность для него не требуется: данные уже сохранены в zpool, и в случае сбоя данные не будут утеряны.

В завершение

ZFS решает сразу несколько задач — отказоустойчивость, шифрование, сжатие, снапшоты, кэширование и блочное хранение. Все это — в одной системе, без необходимости собирать франкенштейна из mdadm, bcache, cryptsetup, LVM и прочих. В будущих текстах разберемся, как установить ОС на ZFS и как с ее помощью настроить инкрементное резервное копирование без привязки к базовой РК.