SSD Nodes Learn 🎉 VPS від $5.50/міс
Посібники Matt ConnorВід Matt Connor · Оновлено 2026-08-13

ZFS на FreeBSD і Linux: скільки RAM потребує ARC

ZFS дає контрольні суми, знімки, send/receive та стиснення, але ARC використовує RAM. Дізнайтеся, як оцінити компроміс на VPS із 2 або 4 GB.

Що дає ZFS і чого він потребує

ZFS у FreeBSD і Linux тепер використовує спільну кодову базу OpenZFS, тому функції в обох системах однакові. Сервер із ZFS отримує дані з контрольними сумами, знімки, які не займають додаткового місця, доки дані не змінюються, реплікацію за допомогою zfs send і стиснення, яке вмикається однією властивістю. За це потрібна пам’ять: ARC (adaptive replacement cache) за замовчуванням використовує значну частину RAM, а на VPS (virtual private server) із 2 GB або 4 GB це саме та пам’ять, яка потрібна вашому застосунку.

У цьому посібнику ZFS розглядається на орендованому VPS з одним або двома віртуальними дисками, а не на системі зберігання із сорока відсіками для дисків. Функції, які зберігають практичну цінність у таких умовах, варті вашої уваги. Про обмеження функцій, які не працюють так само добре в цьому середовищі, варто знати до створення пулу.

OpenZFS у FreeBSD і Linux: одна кодова база, два способи постачання

FreeBSD містить ZFS у базовій системі з FreeBSD 7.0, випущеного у 2008 році. Спочатку це була експериментальна функція. Починаючи з OpenZFS 2.0 у грудні 2020 року, FreeBSD і Linux збираються з одного дерева вихідного коду, тому zfs і zpool працюють однаково в обох системах, а пул, створений в одній системі, можна імпортувати в іншій.

Причина, через яку ZFS є пакетом у Linux і частиною базової системи у FreeBSD, полягає в ліцензуванні. OpenZFS поширюється за CDDL (common development and distribution license). Ядро Linux поширюється за GPL (general public license) версії 2. Проєкт ядра вважає ці ліцензії несумісними, тому код ZFS не включено до основної гілки Linux, а спосіб його постачання визначає кожен дистрибутив окремо. У FreeBSD такого конфлікту немає, тому ZFS просто входить до системи. Практично це означає лише одну відмінність у способі постачання, і вам не потрібно обирати чиюсь сторону.

SSD Nodes не пропонує образи FreeBSD, тому на орендованому тут сервері застосовується частина цього посібника для Linux. Якщо ви використовуєте FreeBSD в іншому місці, сервер FreeBSD отримує ZFS без потреби збирати модуль і проходити оновлення ядра.

Встановлення ZFS і створення пулу

В Ubuntu модуль входить до складу пакетів ядра, тому потрібно встановити лише команди.

sudo apt update
sudo apt install -y zfsutils-linux
zfs version

zfs version виводить два рядки: версію userland і версію модуля ядра. Один рядок означає, що модуль не завантажився. Пакет міститься в компоненті universe, який образи Ubuntu Server вмикають за замовчуванням. Якщо apt не може його знайти, спочатку виконайте sudo add-apt-repository universe.

У Debian пакети містяться в компоненті contrib, а модуль збирається на вашій машині за допомогою DKMS (dynamic kernel module support). Додайте contrib до рядка Components: у файлі /etc/apt/sources.list.d/debian.sources, виконайте sudo apt update, а потім:

sudo apt install -y linux-headers-$(dpkg --print-architecture) zfs-dkms zfsutils-linux

Під час встановлення модуль компілюється та виводиться Building initial module for 6.12.0-.... Це займає кілька хвилин. Важливо розуміти наслідки: після кожного оновлення ядра модуль потрібно збирати повторно. Якщо збірка завершиться помилкою, пул не імпортується, доки ви не усунете проблему.

У FreeBSD нічого встановлювати не потрібно. Увімкніть службу та запустіть її.

sysrc zfs_enable=YES
service zfs start

Тепер створіть пул. Спочатку перегляньте стабільні шляхи до пристроїв, оскільки /dev/vdb призначається в порядку виявлення пристроїв і може змінитися після підключення іншого тому.

ls -l /dev/disk/by-id/
sudo zpool create -o ashift=12 tank /dev/disk/by-id/virtio-abc123def456
zpool status tank

zpool status має вивести state: ONLINE зі списком вашого пристрою в tank. Параметр ashift=12 встановлює мінімальний розмір блока пулу 4 KiB. Це відповідає сучасним SSD і не може бути змінено після створення пулу.

Більшість орендованих образів завантажуються з кореневої файлової системи ext4, тому тут ZFS використовується як пул даних на другому томі, а не як коренева файлова система. Перед створенням пулу переконайтеся, що пристрій справді той, який ви очікуєте. Перевірка придбаного NVMe-диска займає одну хвилину, а повторне створення системи — цілий день.

Хеш-суми виконують відновлення лише за наявності надлишковості в пулі

Кожен блок, який записує ZFS, містить хеш-суму, а під час кожного читання вона перевіряється. Виявлення помилки працює завжди. Для відновлення потрібна друга копія.

У пулі з одним диском ZFS повідомляє правду й на цьому зупиняється. zpool status -v показує це так:

status: One or more devices has experienced an error resulting in data
        corruption.
action: Restore the file in question if possible.  Otherwise restore the
        entire pool from backup.
errors: Permanent errors have been detected in the following files:

        /tank/data/archive.tar

У повідомленні вказано пошкоджений файл. ext4 повернув би ці байти без жодного повідомлення, тому вже сама можливість виявлення помилки має цінність. ZFS все одно не може виправити дані, оскільки в пулі немає другої копії, з якої можна виконати відновлення.

У mirror той самий блок читається з працездатної сторони, пошкоджений блок перезаписується, а подія з’являється в стовпці CKSUM у zpool status. Це самовідновлення, і для нього потрібні два пристрої.

sudo zpool create -o ashift=12 tank mirror /dev/disk/by-id/DISK1 /dev/disk/by-id/DISK2

У VPS сховище хоста зазвичай уже має надлишковість, часто RAID 10 у hypervisor. Це захищає від відмови диска. Але воно не повідомляє, коли блок повернувся пошкодженим, оскільки масив не може визначити, яка копія правильна. ZFS це знає, бо порівнює дані з хеш-сумою, яку записав сам.

Якщо у вас один віртуальний диск і потрібна певна можливість відновлення, sudo zfs set copies=2 tank/important зберігає дві копії кожного блока цього dataset на тому самому диску. Це вдвічі збільшує простір, який використовує dataset, дає змогу пережити пошкодження блока, але не допоможе, якщо зникне весь том.

Scrub читає всі дані в пулі та перевіряє їх.

sudo zpool scrub tank
zpool status tank

Завершення перевірки працездатного пулу містить рядок на кшталт scan: scrub repaired 0B in 00:04:11 with 0 errors. Заплануйте цю операцію; для невеликого пулу достатньо виконувати її щомісяця.

systemctl list-unit-files 'zfs-scrub*'
sudo systemctl enable --now zfs-scrub-monthly@tank.timer

Набори даних є одиницею політики

Набір даних — це файлова система всередині пулу. Створення набору даних не потребує значних ресурсів, тому створюйте окремий набір для кожної задачі. Властивості успадковуються від пулу, тож достатньо один раз задати значення за замовчуванням і перевизначити його там, де це потрібно.

sudo zfs create tank/data
sudo zfs create tank/pg
sudo zfs set compression=lz4 tank
sudo zfs set atime=off tank
sudo zfs set quota=20G tank/data
sudo zfs set recordsize=16K tank/pg
zfs get -r compression,compressratio,quota tank

Стиснення часто вимикають через обережність, але це неправильний підхід. lz4 потребує небагато процесорних ресурсів і зменшує обсяг даних, які потрібно записати на диск, тому для даних, що добре стискаються, читання та запис зазвичай пришвидшуються. zstd стискає сильніше, але потребує більше процесорних ресурсів. Це підходить для журналів і архівів, до яких ви рідко звертаєтеся повторно. Перевірте фактичний результат за допомогою zfs get compressratio tank і пам’ятайте: коефіцієнт враховує лише дані, записані після встановлення властивості.

recordsize — це найбільший блок, який записує набір даних; за замовчуванням його розмір становить 128K. Якщо база даних записує сторінки розміром 8 KiB у записи розміром 128 KiB, одна мала операція запису спричиняє читання всього запису, його зміну та повторний запис. Встановіть recordsize=16K для набору даних бази даних до завантаження даних, оскільки властивість застосовується лише до нових блоків.

quota дає змогу не допустити, щоб один набір даних заповнив увесь пул. Пул ZFS, заповнений майже на 100%, працює повільно, а звільнення місця в ньому стає складним, тому навмисно залишайте резерв вільного простору.

Знімки не займають місця, доки дані не змінюються

ZFS ніколи не перезаписує активний блок. Вона записує новий блок і оновлює вказівники. Саме це називається copy-on-write. Знімок — це запис із вказівкою зберегти блоки, на які цей dataset посилається в поточний момент. Тому його створення виконується миттєво й не потребує додаткового місця.

sudo zfs snapshot tank/data@2026-08-11
zfs list -t snapshot -o name,used,refer -r tank/data

У стовпці USED для знімка вказано місце, яке займає лише цей знімок. Спочатку воно майже дорівнює нулю, а потім зростає, коли ви змінюєте або видаляєте дані, оскільки старі блоки вже не можна звільнити.

Щоб відновити файл, не потрібен окремий етап restore.

ls /tank/data/.zfs/snapshot/
cp /tank/data/.zfs/snapshot/2026-08-11/notes.txt /tank/data/notes.txt

Каталог .zfs прихований навіть від ls -a, доки ви не виконаєте sudo zfs set snapdir=visible tank/data. Створіть знімок заздалегідь, перш ніж він знадобиться. Без знімка випадковий rm -rf спрямовує вас до процедури відновлення ext4, яка починається з демонтування диска, а далі ситуація лише ускладнюється.

Відкат видаляє все, що було записано після створення знімка.

sudo zfs rollback tank/data@2026-08-11

Операція завершується помилкою, якщо існують новіші знімки, а -r видаляє ці новіші знімки, щоб продовжити. Двічі перевірте ім’я dataset, перш ніж натиснути Enter.

Знімок не є резервною копією. Він зберігається в тому самому pool, на тому самому volume і на тому самому сервері. Відмова volume або один zpool destroy призведе до втрати знімків разом із даними. Знімки захищають від власного rm і невдалого оновлення. Це охоплює багато типових інцидентів, але знімки не захищають від подій, які безпосередньо впливають на pool. Повний розбір наведено тут: чому знімок VPS не є резервною копією.

Надсилання й отримання: реплікація однією командою

zfs send перетворює snapshot на потік байтів у стандартний вивід, а zfs receive перетворює цей потік назад на dataset. Перша копія передається повністю.

sudo zfs snapshot tank/data@daily-2026-08-11
sudo zfs send tank/data@daily-2026-08-11 | ssh backup.example.com "sudo zfs recv -F backup/data"

Після цього передавайте лише зміни між двома snapshot.

sudo zfs snapshot tank/data@daily-2026-08-12
sudo zfs send -i tank/data@daily-2026-08-11 tank/data@daily-2026-08-12 | ssh backup.example.com "sudo zfs recv backup/data"

На стороні отримувача має зберігатися snapshot, з якого ви виконуєте надсилання. Якщо його немає, отримання зупиняється з помилкою cannot receive incremental stream: most recent snapshot of backup/data does not match incremental source, оскільки ZFS не має бази для застосування різниці. Передавайте дані зі snapshot, який є на обох сторонах, або почніть знову з повного надсилання.

Надайте права на цільовій системі замість використання віддаленого root: sudo zfs allow -u backupuser create,mount,receive backup/data.

Це повноцінна резервна копія на віддаленому майданчику за однієї умови. На віддаленому кінці має бути ZFS pool, оскільки object storage не може приймати потік. Якщо цільовим сховищем є S3-compatible storage або звичайний Linux host, використовуйте інструмент, який працює з ним. Для такого сценарію дивіться резервні копії restic із VPS.

Чому ZFS використовує так багато RAM? ARC

ARC (adaptive replacement cache) — це кеш читання ZFS. Він розташований у пам’яті ядра, а не у звичайному кеші сторінок Linux, тому free -h не показує його в розділі buff/cache. Ця пам’ять відображається як використана. Сервер ZFS, на якому пам’ять майже повністю зайнята, зазвичай має прогрітий кеш. Саме це пояснює більшість повідомлень «ZFS з’їв мою RAM».

Ліміт за замовчуванням навмисно встановлено досить високим. OpenZFS 2.3 встановлює максимальний розмір ARC на більше з двох значень: обсяг RAM мінус 1 GiB або 5/8 обсягу RAM. У OpenZFS 2.2 і старіших версіях у Linux використовувалася половина RAM, тоді як FreeBSD уже використовувала нове правило. Виконайте zfs version, щоб перевірити, яке правило застосовується у вашій системі.

ChartDefault maximum ARC size by instance RAM, from the OpenZFS default rule (GiB)
The data behind this chart
[
  {
    "label": "2 GB VPS",
    "openzfs_2_2_linux_gib": 1,
    "openzfs_2_3_gib": 1.25
  },
  {
    "label": "4 GB VPS",
    "openzfs_2_2_linux_gib": 2,
    "openzfs_2_3_gib": 3
  },
  {
    "label": "8 GB VPS",
    "openzfs_2_2_linux_gib": 4,
    "openzfs_2_3_gib": 7
  },
  {
    "label": "16 GB VPS",
    "openzfs_2_2_linux_gib": 8,
    "openzfs_2_3_gib": 15
  }
]

Ці значення обчислено за задокументованим правилом за замовчуванням для поширених розмірів інстансів. Це не вимірювання на запущеному сервері. Для інстансу з 4 GB правило 2.3 дозволяє ARC розміром 3 GiB. На тому самому сервері з версією 2.2 ліміт у Linux становить 2 GiB. Для інстансу з 2 GB за правилом 2.3 ARC може займати 1.25 GiB. Застосунок отримує решту пам’яті.

Замість таблиці перегляньте фактичні значення на своєму сервері:

grep -E '^(size|c_max) ' /proc/spl/kstat/zfs/arcstats
arc_summary | head -n 20

У третьому стовпці вказано байти. c_max — це поточний встановлений верхній ліміт, а size — обсяг пам’яті, який ARC займає зараз.

ARC повертає пам’ять системі. Ядро сигналізує про нестачу пам’яті, після чого ARC зменшується. Проблема полягає в часі реакції: зменшення ARC запускається саме через тиск на пам’ять, тому процес, якому одночасно потрібно кілька сотень MiB, може зіткнутися з OOM (out of memory) killer, поки ARC ще звільняє пам’ять. На сервері з 2 GB, де працюють база даних і вебсервер, це не рідкісна ситуація. У посібнику OpenZFS про ручну зміну ліміту сказано те саме: його зменшення «не призведе до зменшення ARC без тиску на пам’ять, який ініціює це зменшення».

Як обмежити ARC на невеликому VPS

Спочатку визначте потреби робочого навантаження в пам’яті. Підсумуйте обсяг, потрібний базі даних і застосунку, залиште запас для операційної системи, а решту виділіть ARC. Для інстансу з 4 GB пам’яті, на якому працюють Postgres і один вебзастосунок, розумним початковим значенням буде від 512 MiB до 1 GiB ARC.

Застосуйте значення без перезавантаження, у байтах. У цьому прикладі це 1 GiB.

echo 1073741824 | sudo tee /sys/module/zfs/parameters/zfs_arc_max

Збережіть це налаштування після перезавантаження.

echo 'options zfs zfs_arc_max=1073741824' | sudo tee /etc/modprobe.d/zfs.conf
sudo update-initramfs -u

Крок із initramfs важливий, оскільки модуль може завантажитися з initramfs до монтування кореневої файлової системи. У такому разі він не прочитає файл, який ви щойно створили. Після перезавантаження перевірте значення за рядком c_max з arcstats.

З самого посібника випливають два застереження. Не можна встановити це значення назад у 0 під час роботи системи. Щоб скасувати налаштування, відредагуйте файл і перезавантажте систему. Зменшення значення також не зменшує великий ARC негайно.

У FreeBSD таке саме обмеження задається через sysctl у vfs.zfs.arc. Виконайте sysctl vfs.zfs.arc, щоб переглянути поточні значення та точну назву параметра у вашій версії, а потім запишіть максимальне значення в /boot/loader.conf.

Для невеликого сервера важливі ще два правила роботи з пам’яттю. Не вмикайте дедуплікацію, оскільки таблиця дедуплікації зберігається в пам’яті, а поширене орієнтовне правило становить від 1 до 3 GB RAM на 1 TB унікальних даних. Не розміщуйте swap на zvol — блоковому пристрої, створеному з пулу, — оскільки обмін через файлову систему, яка намагається звільнити пам’ять, може призвести до взаємного блокування системи. Використовуйте для swap звичайний розділ або файл swap за межами пулу.

Коли ext4 або XFS у поєднанні з restic є кращим варіантом

ZFS виправдовує себе на сервері з вільною оперативною пам’яттю та другим томом. В інших випадках звичайна файлова система в поєднанні зі спеціалізованим інструментом резервного копіювання є кращим вибором. Обирайте ext4 або XFS, якщо:

  • Екземпляр має 2 GB або 4 GB RAM, і робочому навантаженню потрібен увесь доступний обсяг.
  • Є один віртуальний диск і немає другої копії, тому ZFS лише виявляє пошкодження, але не може їх виправити.
  • Цільовим сховищем для резервних копій є object storage або звичайний хост Linux, тому жодна з цих систем не може приймати потік zfs send.
  • Ви використовуєте Debian із DKMS і не можете дозволити собі оновлення ядра, після якого модуль залишиться незбірним.
  • Вам потрібен ZFS у кореневій файловій системі, а образи провайдера пропонують лише ext4.

Залишайте ZFS, якщо маєте окремий том даних, достатній запас RAM (8 GB і більше — комфортний обсяг) і план, у якому snapshots та zfs send використовуються за призначенням, а не просто ввімкнені. В усіх інших випадках ext4 із restic, який записує зашифровані дедупліковані резервні копії у сховище, що не контролюється сервером, забезпечує більшість аналогічних можливостей без витрат оперативної пам’яті.

Типові причини збоїв і повідомлення, які ви побачите

Пул зникає після перезавантаження. zpool status виводить no pools available. Сервіс імпорту читає /etc/zfs/zpool.cache, тому пул, якого немає в цьому файлі, під час завантаження не імпортується. sudo zpool import показує, які пули можна імпортувати, sudo zpool import tank повертає пул, а sudo zpool set cachefile=/etc/zfs/zpool.cache tank зберігає цю зміну. Пул, який не було коректно експортовано з іншої системи, виводить cannot import 'tank': pool may be in use from other system, а sudo zpool import -f tank скасовує це обмеження, якщо ви впевнені, що цей пул не використовується іншим хостом.

modprobe: FATAL: Module zfs not found in directory /lib/modules/6.12.0-... у Debian після оновлення ядра. DKMS не зібрав модуль для нового ядра, зазвичай тому, що не встановлено відповідні заголовки. dkms status показує, для яких ядер виконано складання. Потім sudo apt install -y linux-headers-$(uname -r) повторно sudo dkms autoinstall збирає модуль, а sudo zpool import tank повертає пул.

Пул заповнений, але файли вже видалено. Видалені дані залишаються на диску, доки на них посилається snapshot, тому du і df показують різні значення. zfs list -o space -r tank розділяє використання на USEDDS і USEDSNAP, і велике значення USEDSNAP пояснює причину. Знищіть старі snapshot за допомогою sudo zfs destroy tank/data@2026-06-01, після чого місце звільниться.

Кількість CKSUM у zpool status зростає. Щось на рівні нижче ZFS повертає пошкоджені дані. У mirror це попередження, а блок було відновлено. У пулі з одним диском файл втрачено, zpool status -v називає його, а відновити цей файл можна з резервної копії, яка не зберігається в цьому пулі.

Сервер працює повільно й використовує swap. Обмежте ARC, як описано вище, потім виконайте arc_summary і перевірте коефіцієнт влучань. Якщо ARC замалий, щоб умістити робочий набір, кожне читання звертається до диска. У такій ситуації звичайна файлова система, що використовує page cache, працювала б краще.

FAQ

Скільки RAM потрібно ZFS на VPS?

ZFS працює на інстансі з 2 GB RAM. Справжнє питання полягає в тому, скільки RAM залишиться для застосунку. Без додаткового налаштування OpenZFS 2.3 збільшує ARC до більшого з двох значень: RAM мінус 1 GiB або 5/8 від RAM. Тому сервер із 4 GB RAM може передати кешу 3 GiB. Установіть zfs_arc_max у значення, яке може виділити ваше робоче навантаження, а потім перевірте його за рядком c_max з /proc/spl/kstat/zfs/arcstats.

Чи є знімок ZFS резервною копією?

Ні. Знімок зберігається в тому самому пулі, що й дані. Він переживе пошкодження rm і невдале оновлення, але буде втрачений разом із пулом або інстансом. Перетворіть його на резервну копію, передавши на іншу машину за допомогою zfs send, або запустіть інструмент резервного копіювання, який записує дані до сховища, не контрольованого цим сервером.

Чи однаково працює ZFS у FreeBSD і Linux?

Починаючи з OpenZFS 2.0 у грудні 2020 року, використовується та сама кодова база, ті самі команди й той самий формат даних на диску, а пули можна переносити між цими системами. Відмінність полягає в пакуванні. FreeBSD постачає ZFS у базовій системі. У Linux кожен дистрибутив вирішує це окремо: Ubuntu збирає модуль у своїх пакетах ядра, а Debian збирає його на вашій машині за допомогою DKMS. Тому після оновлення ядра модуль може бути відсутнім, доки його повторне збирання не завершиться успішно.

Чи може ZFS виправити пошкодження на VPS з одним диском?

ZFS виявляє пошкодження та вказує ім’я файлу, але не може його виправити, оскільки для виправлення потрібна друга копія блоку. zfs set copies=2 для dataset створює таку копію ціною подвоєння використаного простору. Це дає змогу обробити пошкоджений блок, але не втрачене сховище. Дзеркало між двома томами — це рішення, яке справді виправляє пошкодження.

Чи сповільнює стиснення роботу сервера?

lz4 зазвичай пришвидшує роботу. Стиснені блоки означають менше записаних і прочитаних байтів, а витрати CPU на обробку блоку невеликі порівняно з дисковим введенням-виведенням, якого вдається уникнути. Установіть compression=lz4 у корені пулу, щоб усі dataset успадкували це налаштування, а потім перевірте zfs get compressratio tank після запису реальних даних.