ZFS: файловая система, которой можно доверять данные

zfsstoragelinuxbackup

Серверная стойка с дисковыми полками

Когда речь заходит о хранении данных, которые действительно важны — базы данных, бэкапы, медиа-архивы, виртуальные машины — я выбираю ZFS. Не потому что это модно или хайпово, а потому что ZFS решает проблемы, о которых другие файловые системы даже не задумываются. Контрольные суммы на каждом блоке, атомарные снапшоты, встроенная репликация, copy-on-write — всё это не маркетинговые фичи, а фундаментальные свойства архитектуры.

В этой статье разберём ZFS с практической стороны: от создания пула до настройки репликации между серверами.

Почему ZFS

Допустим, у вас ext4 на RAID-массиве. Контроллер сообщает, что массив здоров. Но гарантирует ли это целостность данных? Нет. RAID защищает от выхода диска из строя, но не от bit rot — тихой порчи данных на пластинах. Контроллер не знает, что файл, записанный год назад, уже содержит повреждённые биты. Вы узнаете об этом, только когда попытаетесь его прочитать.

ZFS решает эту проблему на уровне архитектуры:

Контрольные суммы (checksums). Каждый блок данных и метаданных имеет контрольную сумму, хранящуюся в родительском блоке. При чтении ZFS проверяет checksum и, если данные повреждены, автоматически восстанавливает их из зеркала или parity-блока.

Copy-on-Write (CoW). ZFS никогда не перезаписывает данные на месте. Новые данные пишутся в свободное место, и только после успешной записи обновляются указатели. Это означает, что файловая система всегда консистентна — даже после внезапного отключения питания. Никаких fsck при загрузке.

Атомарные снапшоты. Благодаря CoW, снапшот создаётся мгновенно и не занимает дополнительного места (пока вы не начнёте изменять данные). Это бесплатная точка восстановления.

Встроенный RAID. ZFS управляет дисками самостоятельно — не нужен аппаратный RAID-контроллер. Более того, ZFS рекомендуется использовать с HBA (Host Bus Adapter), чтобы иметь прямой доступ к дискам.

Установка ZFS на Linux

На Ubuntu ZFS поддерживается из коробки:

# Ubuntu 22.04+
sudo apt update
sudo apt install zfsutils-linux

# Проверяем
zfs version

На Debian нужно подключить contrib-репозиторий:

# Debian 12
sudo apt install linux-headers-amd64
sudo apt install -t bookworm-backports zfs-dkms zfsutils-linux

# Загружаем модуль
sudo modprobe zfs

После установки убедитесь, что модуль загружен:

lsmod | grep zfs

Создание пула (zpool)

Пул — это основная единица хранения в ZFS. Пул создаётся из одного или нескольких дисков (vdevs). Тип vdev определяет уровень избыточности.

Зеркало (mirror)

Аналог RAID1 — данные дублируются на два диска:

sudo zpool create tank mirror /dev/sda /dev/sdb

Потеря одного диска не приводит к потере данных. Доступная ёмкость — размер одного диска.

RAIDZ1

Аналог RAID5 — один диск на parity, остальные на данные:

sudo zpool create tank raidz /dev/sda /dev/sdb /dev/sdc

Выдерживает потерю одного диска. Из трёх дисков по 4 ТБ доступно 8 ТБ.

RAIDZ2

Аналог RAID6 — два диска на parity:

sudo zpool create tank raidz2 /dev/sda /dev/sdb /dev/sdc /dev/sdd

Выдерживает потерю двух дисков одновременно. Для больших массивов (от 6 дисков) я рекомендую именно raidz2 — при ресилверинге большого диска вероятность отказа второго диска ненулевая.

Комбинированный пул

Для высокой производительности и надёжности — несколько vdevs:

sudo zpool create tank 
    mirror /dev/sda /dev/sdb 
    mirror /dev/sdc /dev/sdd

Это аналог RAID10 — stripe из двух зеркал. Максимальная производительность с сохранением избыточности.

Важно: всегда используйте идентификаторы дисков по ID, а не /dev/sdX — буквы могут меняться после перезагрузки:

sudo zpool create tank mirror 
    /dev/disk/by-id/ata-WDC_WD40EFRX-001 
    /dev/disk/by-id/ata-WDC_WD40EFRX-002

Datasets и свойства

Dataset — это логический раздел внутри пула. В отличие от обычных разделов, datasets создаются мгновенно и делят пространство пула динамически:

# Создание datasets
sudo zfs create tank/documents
sudo zfs create tank/backups
sudo zfs create tank/vms
sudo zfs create tank/media

Каждый dataset монтируется автоматически в /tank/documents, /tank/backups и т.д.

Компрессия

Включаю компрессию на всех datasets — это практически бесплатно по CPU и экономит место:

# LZ4 — быстрая компрессия (рекомендую по умолчанию)
sudo zfs set compression=lz4 tank

# ZSTD — лучшее сжатие, чуть больше нагрузки
sudo zfs set compression=zstd tank/backups

Проверка эффективности:

sudo zfs get compressratio tank/backups

Для текстовых данных и бэкапов баз компрессия даёт коэффициент 2-5x. Для медиафайлов (видео, фото) — почти 1x, но потери производительности нет.

Квоты и резервирование

# Квота — максимальный размер dataset
sudo zfs set quota=500G tank/media

# Резервирование — гарантированное место
sudo zfs set reservation=100G tank/vms

Квоты предотвращают ситуацию, когда один dataset заполняет весь пул. Резервирование гарантирует, что для критичных данных (виртуальные машины) всегда будет место.

Другие полезные свойства

# Размер записи (для баз данных обычно 8K или 16K)
sudo zfs set recordsize=16K tank/databases

# Отключить atime (ускоряет работу)
sudo zfs set atime=off tank

# Включить расширенные атрибуты
sudo zfs set xattr=sa tank

Снапшоты и откат

Снапшоты — одна из главных причин использовать ZFS. Они создаются мгновенно, не потребляют место до тех пор, пока данные не начнут изменяться, и позволяют откатиться к любой точке.

Создание снапшота

# Формат: dataset@имя_снапшота
sudo zfs snapshot tank/documents@2025-11-01

# Рекурсивный снапшот (все дочерние datasets)
sudo zfs snapshot -r tank@before-upgrade

Просмотр снапшотов

sudo zfs list -t snapshot
sudo zfs list -t snapshot -o name,used,refer,creation

Откат к снапшоту

# Откат — удаляет все изменения после снапшота
sudo zfs rollback tank/documents@2025-11-01

Если после целевого снапшота были созданы другие снапшоты, нужно добавить флаг -r (удалит промежуточные снапшоты):

sudo zfs rollback -r tank/documents@2025-11-01

Автоматические снапшоты

Для автоматизации использую zfs-auto-snapshot или простой cron:

# /etc/cron.d/zfs-snapshots

# Ежечасные снапшоты (хранить 24)
0 * * * * root /sbin/zfs snapshot tank/documents@hourly-$(date +%Y%m%d-%H%M) && /sbin/zfs list -t snapshot -o name -H | grep "tank/documents@hourly" | head -n -24 | xargs -r -n1 /sbin/zfs destroy

# Ежедневные снапшоты (хранить 30)
0 2 * * * root /sbin/zfs snapshot tank/documents@daily-$(date +%Y%m%d) && /sbin/zfs list -t snapshot -o name -H | grep "tank/documents@daily" | head -n -30 | xargs -r -n1 /sbin/zfs destroy

Для более серьёзных задач рекомендую утилиту sanoid — она реализует гибкие политики ротации снапшотов.

Репликация: zfs send/receive

Аппаратное обеспечение сервера

Одна из мощнейших возможностей ZFS — отправка снапшотов на другой сервер. Это полноценная репликация на уровне блоков.

Полная отправка

# Локально
sudo zfs send tank/documents@2025-11-01 | sudo zfs receive backup/documents

# На удалённый сервер через SSH
sudo zfs send tank/documents@2025-11-01 | ssh backupserver sudo zfs receive backup/documents

Инкрементальная отправка

После первой полной отправки можно отправлять только изменения:

# Создаём новый снапшот
sudo zfs snapshot tank/documents@2025-11-02

# Отправляем разницу между двумя снапшотами
sudo zfs send -i tank/documents@2025-11-01 tank/documents@2025-11-02 | 
    ssh backupserver sudo zfs receive backup/documents

Инкрементальная отправка передаёт только изменённые блоки — это быстро и экономно по трафику.

Скрипт автоматической репликации

#!/bin/bash
# replicate.sh — ежедневная репликация на бэкап-сервер

DATASET="tank/documents"
REMOTE="backupserver"
REMOTE_DATASET="backup/documents"
TODAY=$(date +%Y%m%d)
YESTERDAY=$(date -d "yesterday" +%Y%m%d)

# Создаём снапшот
zfs snapshot "${DATASET}@repl-${TODAY}"

# Инкрементальная отправка
if zfs list -t snapshot "${DATASET}@repl-${YESTERDAY}" > /dev/null 2>&1; then
    zfs send -i "${DATASET}@repl-${YESTERDAY}" "${DATASET}@repl-${TODAY}" | 
        ssh "${REMOTE}" zfs receive -F "${REMOTE_DATASET}"
else
    # Первая отправка — полная
    zfs send "${DATASET}@repl-${TODAY}" | 
        ssh "${REMOTE}" zfs receive -F "${REMOTE_DATASET}"
fi

# Удаляем старый снапшот на источнике
zfs destroy "${DATASET}@repl-${YESTERDAY}" 2>/dev/null

Для продакшена рекомендую syncoid (часть пакета sanoid) — он автоматически управляет снапшотами и инкрементальной репликацией.

Scrub: проверка целостности

Scrub — это фоновая проверка всех блоков в пуле. ZFS читает каждый блок, проверяет контрольную сумму и, при наличии зеркала или parity, восстанавливает повреждённые данные.

# Запуск scrub
sudo zpool scrub tank

# Прогресс
sudo zpool status tank

Вывод после scrub:

  pool: tank
 state: ONLINE
  scan: scrub repaired 0B in 03:45:12 with 0 errors on Sat Nov  1 05:45:12 2025
config:

        NAME                       STATE     READ WRITE CKSUM
        tank                       ONLINE       0     0     0
          mirror-0                 ONLINE       0     0     0
            /dev/disk/by-id/...    ONLINE       0     0     0
            /dev/disk/by-id/...    ONLINE       0     0     0

errors: No known data errors

Если в столбце CKSUM появляются ненулевые значения — диск начал деградировать. Нужно менять.

Рекомендации по расписанию scrub:

  • Для зеркал — раз в неделю
  • Для raidz/raidz2 — раз в месяц (scrub на больших массивах занимает часы)
# /etc/cron.d/zfs-scrub
0 3 * * 0 root /sbin/zpool scrub tank

Настройка ARC-кэша

ARC (Adaptive Replacement Cache) — это кэш ZFS в оперативной памяти. По умолчанию ZFS может использовать до 50% RAM под кэш, что иногда вызывает конфликты с другими приложениями.

# Текущий размер ARC
cat /proc/spl/kstat/zfs/arcstats | grep "^size"

# Статистика попаданий в кэш
arc_summary

Ограничение ARC:

# Максимум 8 ГБ для ARC
echo "options zfs zfs_arc_max=8589934592" | sudo tee /etc/modprobe.d/zfs.conf

# Применить без перезагрузки
echo 8589934592 | sudo tee /sys/module/zfs/parameters/zfs_arc_max

Для серверов с базами данных (PostgreSQL, MySQL), которые имеют собственный кэш, ARC лучше ограничить до 1-2 ГБ, чтобы избежать двойного кэширования.

Для файловых серверов и NAS, наоборот, дайте ARC побольше RAM — это значительно ускорит чтение часто запрашиваемых файлов.

Мониторинг

Базовые команды для мониторинга:

# Состояние пула
sudo zpool status tank

# Использование пространства
sudo zpool list
sudo zfs list

# Производительность ввода-вывода (обновление каждые 5 секунд)
sudo zpool iostat tank 5

# Подробная статистика по vdevs
sudo zpool iostat -v tank 5

Для интеграции с системой мониторинга (Prometheus + Grafana) можно использовать zfs_exporter или парсить вывод zpool status через node_exporter textfile collector:

#!/bin/bash
# /usr/local/bin/zfs-metrics.sh
# Запускать через cron каждую минуту

OUTPUT="/var/lib/node_exporter/textfile/zfs.prom"

# Здоровье пула
STATE=$(zpool get -H -o value health tank)
if [ "$STATE" = "ONLINE" ]; then
    echo "zfs_pool_healthy 1" > "$OUTPUT"
else
    echo "zfs_pool_healthy 0" > "$OUTPUT"
fi

# Использование в процентах
CAPACITY=$(zpool get -H -o value capacity tank | tr -d '%')
echo "zfs_pool_capacity_percent ${CAPACITY}" >> "$OUTPUT"

ZFS vs ext4 vs btrfs

Свойствоext4btrfsZFS
Контрольные суммы данныхНетДаДа
Copy-on-WriteНетДаДа
СнапшотыНет (LVM)ДаДа
Встроенный RAIDНетДа (нестабильный RAID5/6)Да (стабильный)
Репликация send/receiveНетДаДа
КомпрессияНетДаДа
Максимальный размер ФС1 ЭБ16 ЭБ256 квадриллионов ЗБ
ЗрелостьОчень высокаяСредняяОчень высокая
Потребление RAMМинимальноеСреднееВысокое (ARC)

ext4 — надёжная, проверенная временем, но без встроенных возможностей по защите данных. Хороша для boot-раздела и систем с ограниченной RAM.

btrfs — многообещающая, но RAID5/6 до сих пор считается нестабильным. Для зеркал (RAID1) и одиночных дисков вполне пригодна.

ZFS — лучший выбор для хранения ценных данных. Требует больше RAM, но обеспечивает уровень защиты, недостижимый для альтернатив.

Практические сценарии для homelab

NAS для медиа и бэкапов

# Пул из 4 дисков в raidz2
sudo zpool create storage raidz2 
    /dev/disk/by-id/ata-disk1 
    /dev/disk/by-id/ata-disk2 
    /dev/disk/by-id/ata-disk3 
    /dev/disk/by-id/ata-disk4

# Общие настройки
sudo zfs set compression=lz4 storage
sudo zfs set atime=off storage

# Datasets
sudo zfs create storage/media
sudo zfs create storage/backups
sudo zfs create storage/timemachine

# Квоты
sudo zfs set quota=2T storage/media
sudo zfs set reservation=500G storage/backups

Хранилище для виртуальных машин

# Быстрый пул на SSD в зеркале
sudo zpool create vmpool mirror 
    /dev/disk/by-id/nvme-samsung1 
    /dev/disk/by-id/nvme-samsung2

sudo zfs create vmpool/vms
sudo zfs set recordsize=64K vmpool/vms
sudo zfs set compression=lz4 vmpool/vms

# Снапшот перед обновлением ВМ
sudo zfs snapshot vmpool/vms@before-update

# Что-то пошло не так? Откатываемся
sudo zfs rollback vmpool/vms@before-update

Бэкап PostgreSQL

# Dataset для WAL и бэкапов
sudo zfs create tank/pgbackup
sudo zfs set compression=zstd tank/pgbackup
sudo zfs set recordsize=128K tank/pgbackup

# Снапшот после pg_basebackup
pg_basebackup -D /tank/pgbackup/base -Ft -z -P
sudo zfs snapshot tank/pgbackup@base-2025-11-02

# Репликация на бэкап-сервер
sudo zfs send tank/pgbackup@base-2025-11-02 | 
    ssh backup-server sudo zfs receive offsite/pgbackup

Типичные ошибки

Не заполняйте пул более чем на 80%. Производительность ZFS деградирует при заполнении пула свыше 80-85%. Copy-on-Write требует свободного места для записи новых блоков. Настройте мониторинг и алерты заранее.

Не используйте аппаратный RAID-контроллер. ZFS должен видеть диски напрямую. Используйте HBA или переведите контроллер в режим IT/JBOD.

Не забывайте про ECC-память. ZFS хранит данные в RAM перед записью на диск. ECC не является строго обязательным, но для важных данных настоятельно рекомендуется.

Не меняйте recordsize без понимания. По умолчанию 128K — оптимально для большинства нагрузок. Для баз данных нужен размер, совпадающий с размером страницы БД (обычно 8K или 16K).

Итого

ZFS — это файловая система, спроектированная для людей, которые не хотят терять данные. Да, она требует больше ресурсов, чем ext4. Да, она сложнее в начальной настройке. Но те гарантии, которые она даёт — контрольные суммы, атомарные снапшоты, встроенная репликация, self-healing — стоят этих усилий.

Для homelab с несколькими дисками ZFS превращает обычный сервер в надёжное хранилище корпоративного уровня. А возможность в любой момент откатить данные к снапшоту пятиминутной давности спасала меня не раз.

Начните с простого зеркала из двух дисков, настройте автоматические снапшоты и scrub — и вы получите систему хранения, которой действительно можно доверять.

© 2026 Terminal Notes. Built with SvelteKit.