Продовжую for fun and profit сетапити собі домашній сервер з FreeBSD на Lenovo ThinkCentre M720s SFF.
І сьогодні, нарешті, зробимо основне – налаштуємо ZFS pool на реальних дисках, подивимось на роботу з datasets, шифруванням, снапшотами, моніторингом.
Попередні пости цієї серії:
- FreeBSD: Home NAS, part 1 – налаштування ZFS mirror (RAID1) (тест на віртуальній машині)
- FreeBSD: Home NAS, part 2 – знайомство з Packet Filter (PF) firewall
- FreeBSD: Home NAS, part 3 – WireGuard VPN, Linux peer та routing
- FreeBSD: Home NAS, part 4 – локальний DNS з Unbound
Зміст
Підготовка дисків
Дивимось, які диски фізично присутні в системі:
root@setevoy-nas:~ # geom disk list Geom name: nda0 Providers: 1. Name: nda0 Mediasize: 500107862016 (466G) ... Geom name: ada0 Providers: 1. Name: ada0 Mediasize: 4000787030016 (3.6T) ... Geom name: ada1 Providers: 1. Name: ada1 Mediasize: 4000787030016 (3.6T) ...
Або з camcontrol:
root@setevoy-nas:~ # camcontrol devlist <Samsung SSD 870 EVO 4TB SVT03B6Q> at scbus0 target 0 lun 0 (pass0,ada0) <Samsung SSD 870 EVO 4TB SVT03B6Q> at scbus1 target 0 lun 0 (pass1,ada1) <CT500P310SSD8 VACR001> at scbus7 target 0 lun 1 (pass3,nda0)
Тут в мене ada1 та ada2 – це SATA-диски для самого NAS storage, а nda0 – NVMe, на якому встановлена система (там зараз UFS, але потім, скоріш за все, перевстановлю із ZFS теж).
Імена пристроїв на кшталт /dev/ada0, /dev/ada1 або /dev/nda0 можуть змінюватися залежно від порядку підключення дисків, а тому напряму використовувати їх у ZFS не рекомендується – далі створимо власні GPT labels.
Створення GPT tables
Про всяк випадок – видаляємо існуючі таблиці розділів.
ВАЖЛИВО: таблиця розділів буде знищена. Дані залишаються на носії, але стануть недоступними.
В моєму випадку – диски нові, тому бачимо помилку “Invalid argument“:
root@setevoy-nas:~ # gpart destroy -F ada0 gpart: arg0 'ada0': Invalid argument root@setevoy-nas:~ # gpart destroy -F ada1 gpart: arg0 'ada1': Invalid argument
Створюємо таблиці GPT (GUID Partition Table):
root@setevoy-nas:~ # gpart create -s gpt ada0 ada0 created root@setevoy-nas:~ # gpart create -s gpt ada1 ada1 created
Перевіряємо з gpart:
root@setevoy-nas:~ # gpart show ada0
=> 40 7814037088 ada0 GPT (3.6T)
40 7814037088 - free - (3.6T)
root@setevoy-nas:~ # gpart show ada1
=> 40 7814037088 ada1 GPT (3.6T)
40 7814037088 - free - (3.6T)
Створення GPT labels
Для подальшої роботи з дисками створимо постійні GPT lables – іменовані ідентифікатори розділів, які зберігаються в GPT-таблиці розділів і читаються при старті системи.
Вони не змінюються після reboot, не залежать від порядку SATA портів, не залежать від того, як ядро виявило диск.
Додаємо для обох дисків:
root@setevoy-nas:~ # gpart add -t freebsd-zfs -l zfs_disk1 ada0 ada0p1 added root@setevoy-nas:~ # gpart add -t freebsd-zfs -l zfs_disk2 ada1 ada1p1 added
Перевіряємо в /dev/gpt/:
root@setevoy-nas:~ # ls -l /dev/gpt/ total 0 crw-r----- 1 root operator 0x9b Dec 19 13:32 zfs_disk1 crw-r----- 1 root operator 0xa9 Dec 19 13:32 zfs_disk2
Або з gpart:
root@setevoy-nas:/home/setevoy # gpart show -l ada0
=> 40 7814037088 ada0 GPT (3.6T)
40 7814037088 1 zfs_disk1 (3.6T)
root@setevoy-nas:/home/setevoy # gpart show -l ada1
=> 40 7814037088 ada1 GPT (3.6T)
40 7814037088 1 zfs_disk2 (3.6T)
Або з glabel:
root@setevoy-nas:~ # glabel status
Name Status Components
gpt/zfs_disk1 N/A ada0p1
gptid/67ebfac9-dcce-11f0-98bf-00d861f3bff0 N/A ada0p1
diskid/DISK-S758NX0Y701757D N/A ada0
gpt/zfs_disk2 N/A ada1p1
gptid/6a9c3ee5-dcce-11f0-98bf-00d861f3bff0 N/A ada1p1
diskid/DISK-S758NX0Y701756A N/A ada1
Диски готові – переходимо до ZFS, нам треба:
- налаштувати ZFS pool з mirror
- створити datasets
- подивитись на шифрування даних
- перевірити, як працювати зі snapshots
І в кінці окремо поговоримо про моніторинг дисків та ZFS pool.
Створення ZFS mirror pool
Використовуємо такі параметри:
ashift=12: розмір фізичного сектора, який ZFS використовує для I/O- розмір сектора визначається як 2^ashift байт, тобто
2¹²= 4096 байт - замінити значення
ashiftпісля створення Pool не можна
- розмір сектора визначається як 2^ashift байт, тобто
atime=off: вимикаємо оновлення часу доступу до файлів, зменшує кількість зайвих записів на дискcompression=lz4: швидка компресія даних на диску з мінімальним CPU-оверхедомxattr: налаштування зберігання атрибутів файлі:xattr=on: старий і default варіант, extended attributes зберігаються як окремі приховані файлиxattr=sa:xattrзберігаються безпосередньо вdnodeфайлу (аналогinodeв UFS/ext4), без створення окремих прихованих файлів – менше звернень до диска і краща продуктивність
mirror: використовуємо ZFS mirror (аналог RAID1) – дані синхронно записуються на обидва диски (див. такожvdev)
Див. ZFS Tuning Recommendations.
Створюємо пул з дисків /dev/gpt/zfs_disk1 та /dev/gpt/zfs_disk2:
root@setevoy-nas:~ # zpool create -o ashift=12 -O atime=off -O compression=lz4 -O xattr=sa nas mirror /dev/gpt/zfs_disk1 /dev/gpt/zfs_disk2
Перевіряємо:
root@setevoy-nas:~ # zpool status
pool: nas
state: ONLINE
config:
NAME STATE READ WRITE CKSUM
nas ONLINE 0 0 0
mirror-0 ONLINE 0 0 0
gpt/zfs_disk1 ONLINE 0 0 0
gpt/zfs_disk2 ONLINE 0 0 0
errors: No known data errors
Додаємо підключення при ребутах:
root@setevoy-nas:/home/setevoy # sysrc zfs_enable=YES zfs_enable: NO -> YES
Створення ZFS datasets
ZFS dataset – це окрема файлова система всередині ZFS pool, яка має власні властивості (compression, quota, mountpoint тощо) і керується незалежно від інших datasets.
Зараз у нас один, корневий dataset:
root@setevoy-nas:~ # zfs list NAME USED AVAIL REFER MOUNTPOINT nas 420K 3.51T 96K /nas
Корінь pool – це технічний корінь, а не місце для даних, тому створимо кілька окремих.
Не факт, що в мене датасети залишаться такими і надалі, але просто як ідея того, як можна розділити простір на дисках:
nas/data: основний dataset для збереження всяких даних типу музики-фільмівnas/backups: сюди можна буде копіювати якісь periodic бекапи з робочого і домашнього ноутбуківnas/private: зашифрований розділ для приватних даних та/або баз даних типу KeePass або бекапів 1Passwordnas/shared: загальнодоступний dataset для доступу з телефонів і ноутбуків через Samba share (про налаштування Samba – окремим постом, вже є в чернетках)
Створюємо новий датасет з іменем nas/data:
root@setevoy-nas:~ # zfs create nas/data
Перевіряємо список ще раз:
root@setevoy-nas:~ # zfs list NAME USED AVAIL REFER MOUNTPOINT nas 540K 3.51T 96K /nas nas/data 96K 3.51T 96K /nas/data
І каталог цього датасету:
root@setevoy-nas:~ # ls -la /nas/data/ total 1 drwxr-xr-x 2 root wheel 2 Dec 19 13:41 . drwxr-xr-x 3 root wheel 3 Dec 19 13:41 ..
Він жеж має власну точку підключення:
root@setevoy-nas:/home/setevoy # mount | grep data nas/data on /nas/data (zfs, local, noatime, nfsv4acls)
Яка задана у властивостях датасету:
root@setevoy-nas:/home/setevoy # zfs get mountpoint nas/data NAME PROPERTY VALUE SOURCE nas/data mountpoint /nas/data default
Додамо ще один:
root@setevoy-nas:~ # zfs create nas/backups
Ще раз список:
root@setevoy-nas:~ # zfs list NAME USED AVAIL REFER MOUNTPOINT nas 696K 3.51T 96K /nas nas/backups 96K 3.51T 96K /nas/backups nas/data 96K 3.51T 96K /nas/data
Шифрування dataset
Хочеться мати окремий dataset для чутливих даних, тому глянемо, як це зроблено у ZFS.
Документація – Encrypting ZFS File Systems.
Важливо:
- включити шифрування можна тільки створенні dataset – але можна відключити після
- якщо батьківський dataset не зашифрований – дочірній можна зашифрувати
- якщо батьківський зашифрований – дочірні успадковують його шифрування
Створимо новий dataset, вказуємо, що шифрується з паролем:
root@setevoy-nas:~ # zfs create -o encryption=on -o keyformat=passphrase -o keylocation=prompt nas/private Enter new passphrase: Re-enter new passphrase:
Перевіряємо цей датасет:
root@setevoy-nas:~ # zfs get encryption,keyformat,keylocation nas/private NAME PROPERTY VALUE SOURCE nas/private encryption aes-256-gcm - nas/private keyformat passphrase - nas/private keylocation prompt local
Як це буде виглядати після reboot:
- pool
nasімпортується nas/privateбуде заблокований, і mountpoint не зʼявиться, доки вручну не ввести пароль і не розблокувати його
Для розблокування потім використовуємо:
root@setevoy-nas:~ # zfs load-key nas/private root@setevoy-nas:~ # zfs mount nas/private
На відміну від, наприклад, шифрування розділів з LUKS – ZFS дозволяє змінювати пароль для зашифрованого dataset без перешифрування даних. Фактично змінюється лише ключ, який захищає основний ключ шифрування.
Якщо хочемо змінити пароль – виконуємо zfs change-key:
root@setevoy-nas:~ # zfs change-key nas/private Enter new passphrase for 'nas/private':
Замість використання паролю можемо створити файл-ключ, який буде використаний про ребутах для підключення датасету.
Генеруємо ключ:
root@setevoy-nas:/home/setevoy # dd if=/dev/random of=/root/nas-private-pass.key bs=32 count=1
Змінюємо пароль, який вказали при створені датасету:
root@setevoy-nas:/home/setevoy # zfs change-key -o keyformat=raw -o keylocation=file:///root/nas-private-pass.key nas/private
Перевіряємо атрибути:
root@setevoy-nas:/home/setevoy # zfs get encryption,keyformat,keylocation nas/private NAME PROPERTY VALUE SOURCE nas/private encryption aes-256-gcm - nas/private keyformat raw - nas/private keylocation file:///root/nas-private-pass.key local
Ребутаємо машину:
root@setevoy-nas:/home/setevoy # shutdown -r now Shutdown NOW! shutdown: [pid 13519]
І потім перевіряємо розділи:
root@setevoy-nas:/home/setevoy # mount | grep nas nas on /nas (zfs, local, noatime, nfsv4acls) nas/backups on /nas/backups (zfs, local, noatime, nfsv4acls) nas/data on /nas/data (zfs, local, noatime, nfsv4acls)
Та з zfs list:
root@setevoy-nas:/home/setevoy # zfs list NAME USED AVAIL REFER MOUNTPOINT nas 200G 3.32T 112K /nas nas/backups 200K 500G 104K /nas/backups nas/data 96K 3.51T 96K /nas/data nas/private 200K 3.32T 200K /nas/private
Налаштування dataset quotas
ZFS datasets підтримують задання квот на розмір датасетів – тобто, максимальний розмір, який він може займати.
Документація – Setting Quotas on ZFS File Systems.
Зручно, наприклад, аби якийсь backups/ випадково не забив весь диск.
Є ще dataset reservation, але про це трохи далі.
Задамо ліміт в 500 гігабайт на nas/backups:
root@setevoy-nas:~ # zfs set quota=500G nas/backups
Перевіряємо:
root@setevoy-nas:~ # zfs get quota,used,available nas/backups NAME PROPERTY VALUE SOURCE nas/backups quota 500G local nas/backups used 96K - nas/backups available 500G -
Налаштування dataset reservation
ZFS дозволяє зарезервувати місце для датасету, гарантуючи доступний простір незалежно від заповненості пулу.
Документація – Setting Reservations on ZFS File Systems.
Важливо, що ZFS Reservation резервує місце незалежно від того, використовується воно чи ні.
Задамо мінімально доступний розмір основного датасету nas/data:
root@setevoy-nas:~ # zfs set reservation=200G nas/data
Перевіряємо:
root@setevoy-nas:~ # zfs get reservation,used,available nas/data NAME PROPERTY VALUE SOURCE nas/data reservation 200G local nas/data used 96K - nas/data available 3.51T -
Аби змінити reservation чи видалити – просто раз виконуємо zfs set з новим значенням:
root@setevoy-nas:~ # zfs set reservation=100G nas/data root@setevoy-nas:~ # zfs set reservation=none nas/data
Використання ZFS snapshots
ZFS Snapshots – це миттєві read-only знімки стану dataset, які дозволяють швидко відкотитись до попереднього стану.
Документація – Overview of ZFS Snapshots.
Як це працює, коротко:
- ZFS працює за принципом COW (Copy On Write), тобто при зміні в блоках даних – зміни робляться в новому блоку, а старі блоки не перезаписуються, поки на них є активні посилання
- при створенні снапшоту ZFS не копіює дані, а створює таке посилання на цей блок
- далі, коли ми робимо зміни в даних датасета, для якого є снапшот – то зміни на диску робляться в нових блоках даних, а доступ до старих зберігається через снапшот
Створення snapshots
Перевіряємо на прикладі.
Створимо тестовий файл в /nas/data/:
root@setevoy-nas:/home/setevoy # echo test-snap >> /nas/data/test-snap.txt
Створюємо снапшот:
root@setevoy-nas:/home/setevoy # zfs snapshot nas/data@test-snap
Перевіряємо його:
root@setevoy-nas:/home/setevoy # zfs list -t snapshot nas/data@test-snap NAME USED AVAIL REFER MOUNTPOINT nas/data@test-snap 0B - 104K -
Його атрибути:
root@setevoy-nas:/home/setevoy # zfs get creation,used,referenced nas/data@test-snap NAME PROPERTY VALUE SOURCE nas/data@test-snap creation Sat Dec 20 15:46 2025 - nas/data@test-snap used 0B - nas/data@test-snap referenced 104K -
Відновлення зі snapshot
Снапшоти зберігаються в каталозі .zfs датасета – /nas/data/.zfs/snapshot/:
root@setevoy-nas:/home/setevoy # ll /nas/data/.zfs/snapshot/test-snap/ total 1 -rw-r--r-- 1 root wheel 10 Dec 20 15:45 test-snap.txt
І звідси ми можемо отримати доступ і до нашого тестового файлу:
root@setevoy-nas:/home/setevoy # cat /nas/data/.zfs/snapshot/test-snap/test-snap.txt test-snap
Тепер видаляємо оригінальний файл з датасета:
root@setevoy-nas:/home/setevoy # rm /nas/data/test-snap.txt root@setevoy-nas:/home/setevoy # file /nas/data/test-snap.txt /nas/data/test-snap.txt: cannot open `/nas/data/test-snap.txt' (No such file or directory)
Але в снапшоті він доступний:
root@setevoy-nas:/home/setevoy # cat /nas/data/.zfs/snapshot/test-snap/test-snap.txt test-snap
Аби відновити зі снапшоту – можна або просто скопіювати з каталога /nas/data/.zfs/snapshot/test-snap/ з cp, або, якщо треба відкотити весь датасет, то використати zfs rollback – але в такому разі всі зміни, які були зроблені після створення снапшоту будуть втрачені:
root@setevoy-nas:/home/setevoy # zfs rollback nas/data@test-snap
І тепер файл знов на місці:
root@setevoy-nas:/home/setevoy # file /nas/data/test-snap.txt /nas/data/test-snap.txt: ASCII text root@setevoy-nas:/home/setevoy # cat /nas/data/test-snap.txt test-snap
Ну і ZFS Boot Environments працюють через ті самі снапшоти – під час виконання freebsd-update install автоматично створюється копія даних, на яку можна відкотитись в разі проблем.
Взагалі ZFS Boot Environments дуже цікава штука, може, окремо про неї напишу.
Замість повного rollback – аби не перезаписувати дані на поточному датасеті – можна зробити клонування снапшоту в новий датасет:
root@setevoy-nas:~ # zfs clone nas/data@test-snap nas/data-restored
Перевіряємо:
root@setevoy-nas:/home/setevoy # zfs list NAME USED AVAIL REFER MOUNTPOINT nas 200G 3.32T 120K /nas ... nas/data 168K 3.51T 104K /nas/data nas/data-restored 0B 3.32T 104K /nas/data-restored ...
І тепер файл доступний тут:
root@setevoy-nas:/home/setevoy # cat /nas/data-restored/test-snap.txt test-snap
Видалення snapshot
Для видалення використовуємо zfs destroy:
root@setevoy-nas:/home/setevoy # zfs destroy nas/data@test-snap
Аналогічно видаляються і датасети:
root@setevoy-nas:/home/setevoy # zfs destroy nas/data-restore
Копіювання snapshot
Снапшоти можна передавати між хостами і з zfs receive створювати новий снапшот, можна просто створити tar.gz архів.
Документація і багато прикладів – Sending and Receiving ZFS Data.
Для передачі використовуємо zfs send, а потім через пайп – отримувача, наприклад – zfs receive:
root@setevoy-nas:/home/setevoy # zfs send nas/data@test-snap | zfs receive nas/backups/data-$(date +%Y%m%d)
Тепер в датасеті nas/backups у нас є новий датасет nas/backups/data-20251221:
root@setevoy-nas:/home/setevoy # zfs list | grep data nas/backups/data-20251221 104K 500G 104K /nas/backups/data-20251221 nas/data 104K 3.51T 104K /nas/data
В якому міститься копія снапшоту:
root@setevoy-nas:/home/setevoy # ll /nas/backups/data-20251221/.zfs/snapshot/ total 1 drwxr-xr-x 2 root wheel 4 Dec 20 15:45 test-snap
Також можна створювати інкрементальні копії снапшотів з -i та копіювати зашифровані снапшоти.
Якщо в снапшоті конфіденційна інформація, то для zfs send задаємо ключ -w (raw send) – в такому випадку дані передаються в зашифрованому вигляді.
FreeBSD Periodic та автоматизація створення снапшотів
Є кілька утиліт, які допомогають автоматизувати створення снапшотів, з основних – це zfsnap, zfs-periodic (див. більше на ZFS Orchestration Tools – Part 1: Snapshots).
Спробуємо зі zfsnap – встановлюємо його:
root@setevoy-nas:~ # pkg install zfsnap
Важливий нюанс – сам файл називається zfSnap а не zfsnap:
root@setevoy-nas:~ # pkg info -l zfsnap
zfsnap-1.11.1_1:
...
/usr/local/sbin/zfSnap
...
Разом зі zfsnap додається набір Periodic-файлів:
root@setevoy-nas:/home/setevoy # ll /usr/local/etc/periodic/daily/ | grep Snap -r-xr-xr-x 1 root wheel 1512 Nov 30 01:57 402.zfSnap -r-xr-xr-x 1 root wheel 1073 Nov 30 01:57 403.zfSnap_delete
Які по суті являють собою просто shell-скрипти:
root@setevoy-nas:/home/setevoy # cat /usr/local/etc/periodic/daily//402.zfSnap
#!/bin/sh
# If there is a global system configuration file, suck it in.
#
if [ -r /etc/defaults/periodic.conf ]; then
. /etc/defaults/periodic.conf
source_periodic_confs
fi
...
Включити запуск скриптів можна в файлі /etc/periodic.conf (або, краще, /etc/periodic.conf.local):
daily_zfsnap_enable="YES" daily_zfsnap_recursive_fs="nas/data" daily_zfsnap_delete_enable="YES"
Запустити виконання всіх daily задач, для яких в /etc/defaults/periodic.conf задано “YES” – з командою periodic:
root@setevoy-nas:/home/setevoy # periodic daily
І тепер нас є новий снапшот:
root@setevoy-nas:/home/setevoy # zfs list -t snapshot NAME USED AVAIL REFER MOUNTPOINT ... nas/data@daily-2025-12-21_16.41.03--1w 0B - 104K -
Моніторинг ZFS
Для моніторингу у нас є цілий набір утиліт – як дефолтні від самої файлової системи, так і додаткові, які можна встановити окремо.
Є класний документ Monitoring ZFS, хоча і 2017 року, але все ще актуальний.
З основного, чим можемо користуватись і що бажано моніторити:
- SMART: перевірка самих дисків
zpool status: перевірка, що нема проблем на самих ZFS poolszfs scrub: не зовсім про моніторинг, але може показати проблемиzpool events: події пулівarcstats: корисно перевіряти ефективність роботи кешу ZFS
Перевірка S.M.A.R.T. для SSD
Диски зовсім нові, але just in case і на майбутнє – налаштуємо S.M.A.R.T. (Self-Monitoring, Analysis, and Reporting Technology).
Встановлюємо пакет:
root@setevoy-nas:~ # pkg install smartmontools
І перевіряємо стан дисків:
root@setevoy-nas:~ # smartctl -a /dev/ada0 root@setevoy-nas:~ # smartctl -a /dev/ada1
Нам цікаві в основному такі показники:
SMART overall-health self-assessment test result: PASSED: перевірку пройдено (але зазвичай FAILED тут з’являється, коли все зовсім погано)- помилки:
Reallocated_Sector_Ct:- кількість битих секторів, які диск знайшов і замінив резервними
- 0 – ідеально, зростання цього значення – поганий сигнал
Runtime_Bad_Block:- кількість некоректних блоків, знайдених під час нормальної роботи або деградацію лінка (наприклад, падіння швидкості SATA)
- 0 – ідеально, зростання цього значення – поганий сигнал
Uncorrectable_Error_Cnt:- кількість помилок читання/запису, які неможливо було виправити
- 0 – обов’язково має залишатися, зростання – вже серйозна проблема
- Wear/Used reserve:
Wear_Leveling_Count:- показує знос елементів памʼяті SSD
- 0 означає, що диск практично новий або знос мінімальний
Used_Rsvd_Blk_Cnt_Tot:- скільки резервних блоків уже використано для заміни зношених
- 0 – ідеальний стан
Power_On_Hours:- кількість годин, протягом яких диск був увімкнений
- 83 години – диски тільки нещодавно купив і підключив
CRC_Error_Count:- кількість помилок передачі даних між диском і контролером (кабель, порт)
- 0 – норма, зростання часто означає проблеми з кабелем, а не з самим диском
Total_LBAs_Written/Host_Writes/NAND_Writes:- скільки даних реально записано на диск
- порівнюємо зі TBW (Total Bytes Written) від виробника
- в моєму випадку
Total_LBAs_Written= 77982, де LBA – це Logical Block Address, який зазвичай SMART рахує по 512 байт, тобто записано на диск ~40 мегабайт – при заявлених Samsung 2400 TB
Temperature/Temperature_Celsius/Airflow_Temperature_Cel- температура дисків, в мене зараз 28 градусів
SMART Periodic
Для запуска SMART є власні скрипти в /usr/local/etc/periodic.
Аби включити перевірку і репорти – додаємо запуск smartd в автостарт:
root@setevoy-nas:/home/setevoy # sysrc smartd_enable="YES"
І налаштовуємо periodic в /etc/periodic.conf.local.
Аби включити перевірку – треба явно задати диски, по яким цю перевірку робити:
daily_status_smart_devices="/dev/ada0 /dev/ada1"
Результат в репорті:
ZFS Pool Status
zpool status вже запускали вище, тепер додамо запуск по крону і відправку повідомлень.
Скрипти для ZFS /etc/periodic/daily/, наприклад /etc/periodic/daily/404.status-zfs.
Додаємо до /etc/periodic.conf.local:
daily_status_zfs_enable="YES"
Запускаємо скрипти:
root@setevoy-nas:/home/setevoy # periodic daily
Отримуємо листа:
root@setevoy-nas:/home/setevoy # mail -u root Mail version 8.1 6/6/93. Type ? for help. "/var/mail/root": 12 messages 4 new 12 unread ... N 12 root@setevoy-nas Sun Dec 21 17:20 82/3368 "setevoy-nas daily run output" &
Читаємо його (вказуємо номер листа – 12, Enter):
(про налаштування пересилки пошти напишу окремо)
ZFS Scrubbing
ZFS Scrubbing – перевірка цілісності даних.
Під час scrub ZFS порівнює checksum кожного блоку зі збереженим значенням і у разі виявлення помилки система фіксує її в логах та, за наявності mirror, автоматично відновлює дані з другої копії.
Оскільки для цього виконується багато I/O операцій, тому не варто запускати scrubbing часто – раз на місяць буде достатньо.
Запускаємо вручну:
root@setevoy-nas:/home/setevoy # zpool scrub nas
І перевіряємо в zpool status:
root@setevoy-nas:/home/setevoy # zpool status
pool: nas
state: ONLINE
scan: scrub repaired 0B in 00:00:00 with 0 errors on Fri Dec 19 16:54:04 2025
config:
NAME STATE READ WRITE CKSUM
nas ONLINE 0 0 0
mirror-0 ONLINE 0 0 0
gpt/zfs_disk1 ONLINE 0 0 0
gpt/zfs_disk2 ONLINE 0 0 0
errors: No known data errors
Тепер в scan є “scrub repaired 0B” – все добре.
Скрипт – /etc/periodic/daily/800.scrub-zfs, в якому перевіряється значення daily_scrub_zfs_default_threshold, і, якщо пройшло більше днів, ніж задано в threshold – то запускається zpool scrub.
З daily_scrub_zfs_pools можна вказати, які саме пули перевіряти.
Додаємо до нашого /etc/periodic.conf.local:
... # SCRUB daily_scrub_zfs_enable="YES" daily_scrub_zfs_default_threshold=35 daily_scrub_zfs_pools="nas" ...
ZFS Events та History
З zpool events можна перевірити всі останні події в пулі:
root@setevoy-nas:/home/setevoy # zpool events TIME CLASS Dec 20 2025 16:46:39.702350180 sysevent.fs.zfs.history_event Dec 20 2025 16:46:39.711350328 ereport.fs.zfs.config_cache_write Dec 20 2025 16:46:39.711350328 sysevent.fs.zfs.config_sync Dec 20 2025 16:46:39.711350328 sysevent.fs.zfs.pool_import Dec 20 2025 16:46:39.712349914 sysevent.fs.zfs.history_event Dec 20 2025 16:46:39.720349727 sysevent.fs.zfs.config_sync Dec 20 2025 14:46:44.749348450 sysevent.fs.zfs.config_sync ... Dec 21 2025 17:26:30.905209986 sysevent.fs.zfs.history_event
Аби побачити деталі – додаємо -z:
root@setevoy-nas:/home/setevoy # zpool events -v
TIME CLASS
Dec 20 2025 16:46:39.702350180 sysevent.fs.zfs.history_event
version = 0x0
class = "sysevent.fs.zfs.history_event"
pool = "nas"
pool_guid = 0x2f9ad6b17a5e8426
pool_state = 0x0
pool_context = 0x0
history_hostname = ""
history_internal_str = "pool version 5000; software version zfs-2.2.7-0-ge269af1b3; uts 14.3-RELEASE 1403000 amd64"
history_internal_name = "open"
history_txg = 0x2d65
history_time = 0x6946b6cf
time = 0x6946b6cf 0x29dd0364
eid = 0x1
...
А з zpool history можна подивитись всі команди, які запускались:
root@setevoy-nas:/home/setevoy # zpool history History for 'nas': 2025-12-19.13:37:17 zpool create -o ashift=12 -O atime=off -O compression=lz4 -O xattr=sa nas mirror /dev/gpt/zfs_disk1 /dev/gpt/zfs_disk2 2025-12-19.13:41:00 zfs create nas/data 2025-12-19.13:44:19 zfs create nas/backups 2025-12-19.13:48:44 zfs create -o encryption=on -o keyformat=passphrase -o keylocation=prompt nas/private ... 2025-12-21.17:26:30 zfs snapshot -r nas/data@daily-2025-12-21_17.26.30--1w
ZFS I/O statistic
Інформація по I/O операціям з zpool iostat:
root@setevoy-nas:/home/setevoy # zpool iostat
capacity operations bandwidth
pool alloc free read write read write
---------- ----- ----- ----- ----- ----- -----
nas 1.68M 3.62T 0 0 28 584
ZFS ARC моніторинг
ARC (Adaptive Replacement Cache) – кешування в пам’яті даних, які часто використовуються.
Перевірити поточні значення можна з sysctl:
root@setevoy-nas:/home/setevoy # sysctl kstat.zfs.misc.arcstats.size kstat.zfs.misc.arcstats.size: 9379192 root@setevoy-nas:/home/setevoy # sysctl kstat.zfs.misc.arcstats.hits kstat.zfs.misc.arcstats.hits: 26181 root@setevoy-nas:/home/setevoy # sysctl kstat.zfs.misc.arcstats.misses kstat.zfs.misc.arcstats.misses: 6
Або встановити утиліту zfs-stats:
root@setevoy-nas:/home/setevoy # pkg install zfs-stats
І запустити з -E:
root@setevoy-nas:/home/setevoy # zfs-stats -E
------------------------------------------------------------------------
ZFS Subsystem Report Sun Dec 21 18:07:59 2025
------------------------------------------------------------------------
ARC Efficiency: 104.72 k
Cache Hit Ratio: 99.87% 104.58 k
Cache Miss Ratio: 0.13% 137
Actual Hit Ratio: 99.87% 104.58 k
Data Demand Efficiency: 100.00% 0
CACHE HITS BY CACHE LIST:
Most Recently Used: 23.21% 24.28 k
Most Frequently Used: 76.79% 80.30 k
Most Recently Used Ghost: 0.00% 0
Most Frequently Used Ghost: 0.00% 0
CACHE HITS BY DATA TYPE:
Demand Data: 0.00% 0
Prefetch Data: 0.00% 0
Demand Metadata: 99.96% 104.54 k
Prefetch Metadata: 0.04% 39
CACHE MISSES BY DATA TYPE:
Demand Data: 0.00% 0
Prefetch Data: 0.00% 0
Demand Metadata: 91.24% 125
Prefetch Metadata: 8.76% 12
Або використати zfs-mon:
Ну і по моніторингу ZFS цього, мабуть, вистачить.
Ще окремо будемо говорити вже про повноцінний моніторинг системи – планую з VictoriaMetrics, і тоді можна буде додати якийсь експортер для ZFS, наприклад zfs_exporter.


