ZFS Proxmox: значення зберігання ВМ, які варто змінити негайно

Було корисно?

Більшість «таємниць» продуктивності Proxmox+ZFS насправді не таємниці. Це — стандартні налаштування. Налаштування, обрані, щоб бути безпечними, універсальними та сумісними — але потім тихо застосовані у вашій дуже конкретній реальності зберігання: споживчі SSD з ненадійним захистом від втрати живлення, RAIDZ-пули з випадковим I/O, гостьові ОС, що виконують sync-записи, і гіпервізор, який любить кешувати поверх уже кешованого.

Якщо ваші ВМ здаються швидкими до того моменту, коли перестають бути такими — коли відбувається контрольна точка бази даних, оновлення Windows або вікно резервного копіювання і все перетворюється на «гіперцукор» — це для вас. Ми змінимо ті значення за замовчуванням, які дійсно важливі, пояснимо чому та покажемо, як довести результати командами, що не брешуть.

Мислення: припиніть задовольнятися зберіганням «в моїй лабораторії працює»

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

Ключова пастка — припущення, що віртуалізація «випрямляє» речі. Насправді вона робить протилежне. Віртуалізація множить різні патерни I/O — послідовні, випадкові, вибухоподібні, sync-важкі, метадані-важкі — і мультиплексує їх у спільний пул. Цей пул повинен давати обіцянки: обіцянки надійності (семантика sync), обіцянки розподілу (copy-on-write), обіцянки кешування (ARC/L2ARC) і обіцянки справедливості (планувальник). Параметри за замовчуванням — це точка старту, а не стратегія.

Ось рамка, яку я використовую в продакшені:

  • Знайте, які записи мають бути безпечними. Якщо гість попросив sync, вважайте, що це важливо, доки ви свідомо не обмінюєте надійність на швидкість.
  • Підібрати розмір блоків до реальності. ZFS не може прочитати те, що не було записано. Якщо ви обираєте volblocksize, який конфліктує з навантаженням, ви платитимете вічно.
  • Мінімізуйте «подвійну роботу». Подвійне кешування, подвійні контрольні суми, подвійні CoW-шари: кожен окремо може бути виправданий; разом вони — податок.
  • Вимірюйте на правильному шарі. iostat всередині гостя може виглядати нормально, поки хост палає. І навпаки: ZFS може виглядати нормально, поки гість робить патологічні fsync-цикли.

Цікаві факти та історичний контекст (коротко, корисно)

  1. ZFS зробив звичним end-to-end checksumming у масових розгортаннях, перетворивши мовчазну корупцію з «міфічної» на «вимірювану». Це змінило підхід операційних команд до довіри до зберігання.
  2. Copy-on-write (CoW) — причина дешевих знімків (snapshots), а також причина того, чому випадкові записи можуть бути дорогими — особливо на RAIDZ під віртуалізацією.
  3. Compression на ZFS часто є функцією продуктивності, а не лише економії місця, бо менше байтів для переміщення може перекрити вартість CPU (особливо з lz4).
  4. «Sync-записи повільні» раніше залишалися проблемою баз даних; ZFS зробив це системним питанням, строго дотримуючись семантики sync.
  5. SLOG-пристрої стали окремою нішею, бо люди боляче вивчали, що «просто SSD» ≠ «безпечний, низьколатентний лог-пристрій».
  6. Proxmox перевів багатьох користувачів з LVM-thin на ZFS через зручність знімків і реплікації — поки не виявили, як значення за замовчуванням впливають на затримки.
  7. Індустрія роками переосмислювала write amplification: маленькі випадкові записи на CoW-файлових системах можуть розростися в значно більшу фізичну роботу, особливо з паритетними RAID.
  8. Помилки ashift — назавжди (фактично): якщо ви створили пул з неправильною припущеною фізичною розмірністю секторів, продуктивність може бути назавжди обмежена.

Стандартні налаштування Proxmox+ZFS, яким варто одразу не довіряти

1) Поведінка sync: її більше не можна ігнорувати

Стандартні налаштування Proxmox не врятують вас від затримок sync-записів. Ваші гості можуть виконувати sync-запити (fsync, O_DSYNC, barriers/flushes), і ZFS трактуватиме ці записи як «мають бути стійкими при відключенні живлення». Якщо у вас немає SLOG і ваш пул на HDD або насичених SSD, sync-важкі навантаження почуватимуться як будинок з привидами.

Але найгірше — це неоднозначність: деякі навантаження стають sync-важкими тільки в певні фази — коміти бази даних, скидання журналів, резервне копіювання ВМ, що тригерить поведінку файлової системи. Тож ви отримаєте періодичні страждання та хибне відчуття «переважно все нормально».

Рішення: якщо вам важлива надійність, залишайте sync=standard і будуйте пул, щоб витримувати це. Якщо не важлива (лабораторія, епhemeral CI), ви можете свідомо обрати sync=disabled — ніколи випадково.

2) volblocksize: налаштування, яке тихо визначає економіку I/O

ZVOL мають volblocksize. Datasets мають recordsize. Люди їх плутають, а потім дивуються, чому їхні тюнінги не дали результату.

volblocksize встановлюється при створенні zvol і фактично постійний (ви можете змінити його, але вже записані блоки не переписуються; зазвичай потрібна міграція, щоб повністю скористатися змінами). Proxmox часто створює zvol з дефолтним значенням, яке може не відповідати вашому навантаженню.

Типові рекомендації (не догма):

  • 16K: часто підходить для загальних дисків VM, змішаних навантажень і баз даних з великою кількістю маленьких випадкових I/O.
  • 8K: може допомогти для особливо sync-важких або лог-орієнтованих патернів, але може збільшити накладні витрати на метадані.
  • 64K/128K: чудово для великих послідовних навантажень (медіа, резервні копії), часто помилково для системних дисків ОС.

На RAIDZ менші блоки можуть бути особливо болісними через паритет і поведінку read-modify-write. Саме тут народжуються чутки «ZFS повільний».

3) Compression: не витягайте продуктивність зі столу

Якщо ви не використовуєте compression=lz4 на сховищі ВМ, ви фактично обираєте переміщати більше байтів, ніж потрібно. Для багатьох навантажень ВМ (файли ОС, логи, текст, пакети) стиснення зменшує фізичний I/O і покращує затримку під навантаженням.

Стиснення може нашкодити на CPU-обмежених хостах або при нескомпресованих даних (зашифровані томи, стиснені медіа). Але для більшості гіпервізорів Proxmox lz4 — це дефолт, який варто бажати.

4) atime: смерть від тисячі читань

atime=on означає, що читання стають записами, бо оновлюється час доступу. На сховищі ВМ це зазвичай марна активність. Якщо ви цінуєте ресурс SSD і затримку, встановіть atime=off для dataset ВМ.

5) Primary cache: подвійне кешування — це не характеристика

ZFS ARC агресивно кешує. Гості також кешують. Якщо дозволите ZFS кешувати дані ВМ, які гість знову закешує, ви витрачатимете пам’ять з обох боків і отримаєте менш ефективне кешування загалом.

Типовий підхід: для дисків VM на базі zvol розгляньте primarycache=metadata (кешувати метадані, а не дані), щоб зменшити подвійне кешування. Це ситуативно: якщо ваші гості малі, а хост має величезну RAM, кеш даних може і допомогти. Але вирішувати потрібно свідомо.

6) Thin provisioning: «вільне місце» — соціальна конструкція

Thin zvols виглядають як ефективність доти, доки пул не опиниться на краю прірви. Коли ZFS-пул сильно заповнюється, продуктивність може впасти через тиск на алокацію і фрагментацію. «Але в нас ще 15% вільно!» — так люди говорять незадовго до поганого дня.

Операційне правило: зберігайте значущий обсяг вільного місця. Для багатьох пулів з великою кількістю ВМ вважайте нормою 20–30% вільного. Якщо це здається марнотратним, ви незабаром відчуєте, як виглядає екстрене придбання сховища.

Жарт #1: RAIDZ з майже повним пулом — як зустріч, яка «могла бути листом». Вона триває, повільніє, і ніхто не може піти.

ZVOL проти файлів у dataset (raw/qcow2): оберіть найменш погане для вашого використання

ZVOL (блокові пристрої): простий шлях, чіткі семантики

ZVOL — це блокові пристрої, підкріплені ZFS. Proxmox їх любить, бо знімки й реплікація інтегруються чисто, і ви уникаєте частини дивної поведінки «файлова система на файловій системі».

Торгівлі:

  • volblocksize має велике значення, і у вас не безкінечні повторні спроби.
  • Поводження з Discard/TRIM може бути складним залежно від версій та налаштувань. Потрібно перевірити, що звільнення місця дійсно працює.
  • Семантика кешування (primarycache) стає важливою, щоб не конкурувати з гостем.

Файли dataset (raw/qcow2): гнучкість з додатковим шаром

Зберігання дисків ВМ як файлів у dataset може бути цілком пристойним. Головний ризик — насладання CoW-шарів (qcow2 — CoW; ZFS — CoW). Це може посилити фрагментацію і накладні витрати на метадані, особливо при випадкових записах.

Рекомендації за позицією:

  • Віддавайте перевагу raw перед qcow2 на ZFS, якщо вам не потрібна конкретна функція qcow2.
  • Використовуйте qcow2 обережно для нішевих випадків (с sparse + внутрішні знімки), але розумійте, що платите за цю гнучкість.

Як швидко вирішити

  • Якщо у вас бази даних або чутливі до затримки сервіси: zvol з адекватним volblocksize та планом для sync-записів.
  • Якщо у вас переважно послідовні великі дані: файли в dataset можуть бути прийнятними, налаштуйте recordsize і тримайте все просто.
  • Якщо у вас багато маленьких ВМ і ви цінуєте простоту управління: з більшим шансом zvols легше розуміти в інструментах Proxmox.

Зміни, які я роблю в перший день (і чому)

Зміна 1: Увімкніть compression=lz4 на сховищі ВМ

Робіть це, якщо немає доказів протилежного. lz4 має низьку латентність, а диски ВМ зазвичай стискувані. Перевага найкраще помітна під навантаженням, коли пул зайнятий.

Зміна 2: Вимкніть atime для dataset ВМ

Це класичне «дрібне» налаштування, що запобігає марним операціям. Сховище ВМ не потребує записів часу доступу.

Зміна 3: Явно вирішіть політику sync

Більшість людей випадково працюють з sync=standard на обладнанні, яке не може це витримати, а потім «виправляють» вимкненням sync глобально й забувають про це. Не будьте тим, хто так робить.

Оберіть одне:

  • Дорога надійність: sync=standard, додайте належний SLOG за потреби й перевірте затримки.
  • Швидкість за будь-яку ціну: sync=disabled на конкретних dataset/zvol, де втрата даних допустима.

Зміна 4: Встановіть primarycache обдумано для сховища з великою кількістю zvol

Якщо хост обмежений за пам’яттю, ARC, що конкурує з гостями, — як бій ножами. Для багатьох дисків VM на zvol, primarycache=metadata є розумним дефолтом. Якщо у вас велика RAM і переважно read-орієнтовані гості, кеш даних може допомогти. Вимірюйте, а не орієнтуйтеся на відчуття.

Зміна 5: Припиніть переповнювати пулив

Запишіть це: пул ZFS на 85–90% заповнення — це не «нормально». Це інцидент з латентністю, про який ви вже попереджені.

Зміна 6: Використовуйте правильні опції диска в віртуалізації (і перевіряйте)

Налаштування диска Proxmox як-от cache, discard, iothread та модель контролера мають значення. Але «мають значення» означає «виявляються у вимірах», а не «звучать круто в форумі». Ваш базовий стан має бути стабільна затримка й передбачувана поведінка при відмовах.

Жарт #2: Увімкнути всі перемикачі продуктивності одночасно — це як випити п’ять енергетиків, щоб «краще спати». Ви дізнаєтеся щось, але не те, чого хотіли.

Практичні завдання: команди, виводи та рішення

Ось реальні перевірки, які я виконую на хості Proxmox, коли сховище ВМ повільне, непослідовне або підозріло «добре до моменту, коли ні». Кожне завдання включає команду, приклад виводу, що означає вивід, і наступне рішення.

Завдання 1: Визначте пули, їхній стан і очевидні червоні прапори

cr0x@server:~$ zpool status
  pool: rpool
 state: ONLINE
status: Some supported features are not enabled on the pool.
action: Upgrade the pool to enable all features.
  scan: scrub repaired 0B in 00:12:44 with 0 errors on Sun Dec 22 03:12:26 2025
config:

        NAME                        STATE     READ WRITE CKSUM
        rpool                       ONLINE       0     0     0
          mirror-0                  ONLINE       0     0     0
            ata-SAMSUNG_SSD_1TB_A   ONLINE       0     0     0
            ata-SAMSUNG_SSD_1TB_B   ONLINE       0     0     0

errors: No known data errors

Що це означає: Пул онлайн, помилок немає, scrub чистий. Попередження про фічі не є само по собі проблемою продуктивності.

Рішення: Якщо ви бачите degraded vdevs, checksum errors або постійні resilver, припиніть тюнінг і спочатку виправте апарат. Налаштування продуктивності на несправному пулі — це креативний шлях отримати незвичні звіти про простої.

Завдання 2: Перевірте заповненість пулу (тихий вбивця продуктивності)

cr0x@server:~$ zfs list -o name,used,avail,refer,mountpoint -r rpool
NAME                 USED  AVAIL  REFER  MOUNTPOINT
rpool                720G   180G   104K  /rpool
rpool/data           680G   180G   104K  /rpool/data
rpool/data/vmdata    640G   180G    96K  /rpool/data/vmdata

Що це означає: ~80% використано. Ви входите в зону, де фрагментація й накладні витрати на алокацію починають проявлятися.

Рішення: Якщо ви вище ~80–85% на пулі з великим навантаженням ВМ, плануйте роботу з ємністю зараз: додайте vdevs, перемістіть холодні ВМ або розділіть навантаження. Не намагайтеся «оптимізувати» фізичні обмеження.

Завдання 3: Перевірте критичні властивості dataset (compression, atime, sync)

cr0x@server:~$ zfs get -o name,property,value -s local,default compression,atime,sync,primarycache rpool/data/vmdata
NAME               PROPERTY      VALUE
rpool/data/vmdata  compression   off
rpool/data/vmdata  atime         on
rpool/data/vmdata  sync          standard
rpool/data/vmdata  primarycache  all

Що це означає: Compression вимкнено і atime увімкнено: ви платите зайвий I/O. sync standard: діє семантика надійності. primarycache all: ARC може подвійно кешувати дані гостя.

Рішення: Увімкніть compression=lz4 і atime=off на dataset ВМ, якщо немає причин інакше. Оцініть primarycache залежно від навантаження пам’яті і кешування в гостях.

Завдання 4: Застосуйте безпечні, відкотні зміни dataset (lz4 + atime off)

cr0x@server:~$ sudo zfs set compression=lz4 atime=off rpool/data/vmdata
cr0x@server:~$ zfs get -o name,property,value compression,atime rpool/data/vmdata
NAME               PROPERTY     VALUE
rpool/data/vmdata  compression  lz4
rpool/data/vmdata  atime        off

Що це означає: Майбутні записи будуть стиснені; оновлення часу доступу припинять генерувати зайві операції.

Рішення: Зазвичай це загальна вигода. Якщо CPU стане вузьким місцем (рідко з lz4), ви побачите це в метриках CPU хоста під I/O навантаженням.

Завдання 5: Перелічіть zvol і перевірте volblocksize

cr0x@server:~$ zfs list -t volume -o name,volblocksize,used,refer,logicalused -r rpool/data/vmdata
NAME                         VOLBLOCKSIZE  USED  REFER  LOGICALUSED
rpool/data/vmdata/vm-101-disk-0  128K       64G   64G       120G
rpool/data/vmdata/vm-102-disk-0  8K         20G   20G        22G

Що це означає: У вас різні volblocksize. 128K-диск ОС часто погано поводиться для випадкового I/O. LOGICALUSED > REFER вказує на компресію/знімки або ефекти thin provisioning.

Рішення: Для загальних VM-дисків стандартизуйте (часто 16K), якщо немає виміреної причини інакше. Для існуючих дисків плануйте міграцію, щоб повністю отримати користь.

Завдання 6: Перевірте, чи ви зловживаєте sync семантикою (стрибки затримки)

cr0x@server:~$ sudo zpool iostat -v rpool 1 5
              capacity     operations     bandwidth
pool        alloc   free   read  write   read  write
----------  -----  -----  -----  -----  -----  -----
rpool        720G   180G    150    980  12.4M  5.1M
  mirror-0   720G   180G    150    980  12.4M  5.1M
    ata-SAMSUNG_SSD_1TB_A     -      -     75    490  6.2M  2.6M
    ata-SAMSUNG_SSD_1TB_B     -      -     75    490  6.2M  2.6M

Що це означає: Помірний bandwidth, але багато write operations: класичне навантаження малих записів. Якщо під час цього спостерігається погана затримка, sync-записи можуть змушувати чекати.

Рішення: Далі проінспектуйте затримку ZFS і поведінку sync (завдання нижче). Якщо це хост бази даних, вважайте, що sync важливий, поки не доведено протилежне.

Завдання 7: Перевірте затримку ZFS безпосередньо

cr0x@server:~$ sudo zpool iostat -rlv rpool 1 3
                              read                              write
pool        r/s   w/s  rMB/s  wMB/s  rlat  wlat  cholat  dlat
----------  ----  ---- -----  -----  ----  ----  ------  ----
rpool        120   950  10.1   4.9   2ms   38ms   42ms   1ms

Що це означає: Затримка запису ~38ms, вища під навантаженням. Це «ВМ почуваються пригальмовано» — особливо для метаданих і журналів.

Рішення: Якщо wlat регулярно підскакує в десятки/сотні мілісекунд, потрібно вирішувати питання sync-шляху, насичення пулу або поведінки пристрою (прошивка/PLP). Налаштування гостей цього не виправить.

Завдання 8: Перевірте, чи взагалі у вас є окремий лог (SLOG)

cr0x@server:~$ zpool status -v rpool
  pool: rpool
 state: ONLINE
config:

        NAME                        STATE     READ WRITE CKSUM
        rpool                       ONLINE       0     0     0
          mirror-0                  ONLINE       0     0     0
            ata-SAMSUNG_SSD_1TB_A   ONLINE       0     0     0
            ata-SAMSUNG_SSD_1TB_B   ONLINE       0     0     0

errors: No known data errors

Що це означає: Немає секції logs. Sync-записи потрапляють на основні vdev.

Рішення: Якщо у вас sync-важкі навантаження і болить затримка, оцініть придбання належного SLOG (з дзеркалом, захистом від втрати живлення). Якщо у вас немає PLP, ви просто купуєте нові способи швидко втратити дані.

Завдання 9: Перевірте тиск ARC і реальний стан пам’яті

cr0x@server:~$ grep -E 'MemTotal|MemFree|MemAvailable' /proc/meminfo
MemTotal:       131900192 kB
MemFree:         4021184 kB
MemAvailable:   18944128 kB
cr0x@server:~$ cat /proc/spl/kstat/zfs/arcstats | egrep '^(size|c |c_min|c_max|hits|misses) '
size                            4    82463313920
c                               4    85899345920
c_min                           4    4294967296
c_max                           4    85899345920
hits                            4    2840093011
misses                          4    390129220

Що це означає: ARC ≈82G, може зрости до ≈85G. MemAvailable ≈18G свідчить, що хост не голодує, але гості можуть.

Рішення: Якщо хост свопить або MemAvailable постійно мізерний, зменшіть ARC (або додайте RAM). Якщо гості позбавлені пам’яті, розгляньте primarycache=metadata для zvol дисків ВМ, щоб хост припинив «занадто допомагати».

Завдання 10: Перевірте, чи увімкнено discard/TRIM наскрізно

cr0x@server:~$ lsblk -D
NAME        DISC-ALN DISC-GRAN DISC-MAX DISC-ZERO
sda                0      512B       2G         0
sdb                0      512B       2G         0
cr0x@server:~$ sudo zpool get autotrim rpool
NAME   PROPERTY  VALUE     SOURCE
rpool  autotrim  off       default

Що це означає: Диски підтримують discard, але autotrim пулу вимкнено.

Рішення: Розгляньте увімкнення autotrim на SSD пулах, де звільнення місця важливе і ваше навантаження не постраждає від додаткової активності trim. Потім перевірте, чи увімкнено discard у Proxmox для дисків ВМ.

Завдання 11: Увімкніть autotrim (якщо доречно) і спостерігайте

cr0x@server:~$ sudo zpool set autotrim=on rpool
cr0x@server:~$ sudo zpool get autotrim rpool
NAME   PROPERTY  VALUE  SOURCE
rpool  autotrim  on     local

Що це означає: Пул передаватиме trims далі. Це може допомогти довгостроковій продуктивності SSD і поведінці місця.

Рішення: Якщо увімкнення trim корелює зі стрибками затримки на деяких SSD, вимкніть його й натомість виконуйте планові trims у тихі вікна.

Завдання 12: Перевірте фрагментацію (особливо на довгоживучих VM пулах)

cr0x@server:~$ zpool list -o name,size,alloc,free,frag,cap,dedupratio
NAME   SIZE  ALLOC   FREE  FRAG  CAP  DEDUP
rpool  900G   720G   180G   42%  80%  1.00x

Що це означає: 42% фрагментації не катастрофа, але може додавати до випадкової I/O-затримки на навантажених пулах, особливо в поєднанні з високим заповненням.

Рішення: Якщо frag висока і пул також повний, припиніть експерименти. Плануйте міграцію або розширення. «Тюнінг» фрагментації — це здебільшого управління ємністю в іншому вбранні.

Завдання 13: Перевірте, чи випадково увімкнено dedup

cr0x@server:~$ zfs get -o name,property,value dedup -r rpool/data/vmdata
NAME               PROPERTY  VALUE
rpool/data/vmdata  dedup     off

Що це означає: Dedup вимкнено. Добре.

Рішення: Якщо dedup включений для сховища ВМ і ви не планували цього, вимкніть для нових записів і сплануйте ремедіацію. Dedup без правильного обсягу пам’яті та тестування перетворює RAM на вузьке місце продуктивності.

Завдання 14: Спостерігайте затримку по vdev за допомогою iostat

cr0x@server:~$ iostat -x 1 3
Linux 6.8.12-pve (server) 	12/25/2025 	_x86_64_	(32 CPU)

avg-cpu:  %user   %nice %system %iowait  %steal   %idle
           8.12    0.00    2.91   11.44    0.00   77.53

Device            r/s     w/s   rkB/s   wkB/s  avgrq-sz avgqu-sz   await  r_await  w_await  svctm  %util
sda             85.0   490.0  6200.0  2600.0     27.4     3.10   38.2     3.1     44.1    0.8   46.2
sdb             85.0   490.0  6200.0  2600.0     27.4     3.06   37.9     3.0     43.7    0.8   46.0

Що це означає: iowait хосту немалий (11%). Очікування записів ≈44ms: це збігається з wlat ZFS. Пристрої не завантажені на 100%, але затримка все одно висока — типова ситуація, коли пристрій виконує внутрішній GC або обробляє flush-и.

Рішення: Якщо await високий, а %util не зашитий, підозрюйте поведінку flush, прошивку або тиск від sync, а не просто пропускну здатність.

Завдання 15: Перевірте конфіг диска VM у Proxmox щодо ризикованих режимів кешу

cr0x@server:~$ qm config 101 | egrep 'scsi|virtio|ide|sata|boot'
boot: order=scsi0;net0
scsi0: rpool/data/vmdata/vm-101-disk-0,discard=on,iothread=1,cache=writeback,ssd=1

Що це означає: cache=writeback може бути швидким, але змінює семантику відмовостійкості. З writeback хост може підтввердити запис, перш ніж він буде безпечним на диску.

Рішення: Для баз даних і чого-небудь, що залежить від правильності, віддавайте перевагу безпечнішим режимам кешу (і покладайтеся на ZFS + належне обладнання). Якщо ви свідомо обираєте writeback, документуйте це, ніби це заряджена зброя.

Завдання 16: Підтвердіть ashift пулу (бо потім не виправиш)

cr0x@server:~$ sudo zdb -C rpool | egrep 'ashift|vdev_tree' -n | head
54:        vdev_tree:
86:            ashift: 12

Що це означає: ashift=12 (4K сектора). Зазвичай це правильно для сучасних дисків.

Рішення: Якщо ви коли-небудь побачите ashift=9 на дисках, що насправді 4K, очікуйте проблем з продуктивністю. Виправлення зазвичай означає перебудову пулу. Плануйте це відповідно.

Завдання 17: Перевірте «роздуття» snapshot-ів (бо «вільне місце» може бути заповнено)

cr0x@server:~$ zfs list -o name,used,usedbysnapshots,usedbydataset,logicalused -r rpool/data/vmdata | head
NAME               USED  USEDSNAP  USEDDS  LOGICALUSED
rpool/data/vmdata  640G     210G    96K       1.1T

Що це означає: 210G зайнято snapshot-ами. Це не «погано» саме по собі; це політичне рішення. Але це впливає на заповненість пулу і продуктивність.

Рішення: Якщо знімки їдять простір і штовхають вас у зону високого заповнення, скоротіть політику зберігання або перенесіть резервні копії в інше місце. «Ми зберігаємо все назавжди» — не стратегія зберігання.

Завдання 18: Перевірте, чи стиснення справді працює (перевірка коефіцієнта)

cr0x@server:~$ zfs get -o name,property,value compressratio -r rpool/data/vmdata | head
NAME               PROPERTY      VALUE
rpool/data/vmdata  compressratio 1.38x

Що це означає: 1.38x — відчутна вигода. Ви зменшуєте фізичний I/O для багатьох навантажень.

Рішення: Якщо compressratio ≈1.00x для зашифрованих/нестиснюваних даних — це очікувано. Проте накладні витрати lz4 зазвичай низькі, тому його варто залишати ввімкненим.

Парафразована ідея — John Allspaw: Надійність походить від проектування систем, що безпечно відпрацьовують відмови, а не від припущення, що відмов не буде.

Швидкий план діагностики (перші/другі/треті перевірки)

Це короткий потік триажу, коли в тикеті написано «сховище ВМ повільне» і у вас є 15 хвилин до наступної наради, яку ви все одно ігноруватимете.

Перше: чи хворий шар зберігання хоста або він просто зайнятий?

  • Запустіть zpool status: подивіться на degraded devices, checksum errors, resilvering або scrubs, що працюють у пікові години.
  • Запустіть zpool iostat -rlv 1 3: перевірте write latency (wlat). Якщо wlat високий, проблеми на шарі зберігання.
  • Запустіть iostat -x 1 3: підтвердіть await пристроїв і iowait. Високий await підтверджує проблему на рівні пристрою.

Друге: чи тонете ви в sync-записах?

  • Перевірте властивість sync dataset/zvol (не припускайте автоматично). Якщо sync=standard, sync-записи чекатимуть на стабільне зберігання.
  • Підтвердіть наявність SLOG. Якщо немає — sync-затримка сплачується на основних vdev.
  • Шукайте навантаження, що тригерить sync-шторм: бази даних, пошта, NFS всередині гостей, файлові системи з журналом під тиском.

Третє: чи ви обмежені ємністю та фрагментацією?

  • Перевірте cap та frag пулу. Висока ємність у поєднанні з високою фрагментацією множить затримки.
  • Перевірте використання snapshot-ів. Знімки можуть «закривати» простір і пришвидшувати поведінку «пул занадто повний».
  • Перевірте несподіваності thin provisioning: гості думають, що мають простір, а пул — ні.

Якщо ці три перевірки чисті

Тоді дивіться на конфігурацію ВМ: режим кешу, шину диска, iothread, глибину черги та поведінку файлової системи гостя. Але не починайте з цього. Інакше ви закінчите тюнінгом приладової панелі, поки двигун працює з одним циліндром.

Поширені помилки: симптом → корінна причина → виправлення

1) Симптом: «Усе зависає на 1–5 секунд рандомно»

Корінна причина: Стрибки затримки sync-записів (flush-и, fsync-шторм) на пулі без належного SLOG, часто в поєднанні зі споживчими SSD, що зависають під тиском flush.

Виправлення: Залишайте sync=standard для важливих даних, додайте дзеркальний SLOG з PLP за потреби і валідуйте zpool iostat -rlv. Якщо дані витратні, встановіть sync=disabled для конкретного dataset/zvol і задокументуйте ризик.

2) Симптом: «ВМ синтетично швидкі, але реальні додатки повільні»

Корінна причина: Бенчмарки тестують послідовні шляхи; додатки — випадкові sync-важкі патерни та метадані. Також поширено: невідповідний volblocksize для zvol.

Виправлення: Підберіть volblocksize під навантаження (часто 16K для загальних VM-дисків), уникайте qcow2-на-ZFS без потреби і вимірюйте затримку, а не лише пропускну здатність.

3) Симптом: «Пул має місце, але продуктивність жахлива»

Корінна причина: Пул занадто заповнений (80–95%), знімки ловлять простір, аллокатор під тиском; фрагментація зростає.

Виправлення: Скоротіть збереження знімків, мігруйте дані, розширюйте пул. Розглядайте вільний простір як резерв продуктивності, а не пораду.

4) Симптом: «Після увімкнення autotrim затримка погіршилась»

Корінна причина: Деякі SSD погано працюють при безперервних trim-операціях; trim конкурує з foreground-записами.

Виправлення: Вимкніть autotrim і виконуйте планові trims у тихі вікна. Розгляньте enterprise SSD з передбачуваною поведінкою trim.

5) Симптом: «Хост має багато RAM, але гості все одно своплять під навантаженням»

Корінна причина: ARC агресивно росте і відбирає пам’ять у гостей, або ви подвійно кешуєте дані хостом і гостем.

Виправлення: Розгляньте primarycache=metadata для zvol ВМ; обмежте ARC, якщо потрібно; валідуйте з arcstats і метриками пам’яті гостей.

6) Симптом: «Резервні копії роблять продакшн непридатним»

Корінна причина: I/O від знімків/бекапів конфліктує з продуктивним випадковим записом; бекапи підвищують read amplification і метадані-активність.

Виправлення: Плануйте бекапи, обмежуйте їх, ізолюйте сховище для бекапів і уникайте розміщення цілей резервного копіювання на тому самому навантаженому пулі.

7) Симптом: «Ми додали швидкий SSD-кеш і нічого не покращилось»

Корінна причина: L2ARC не допомагає з затримкою запису; він допомагає з читанням, і лише якщо робочий набір і патерни доступу підходять. Кеш-пристрої також можуть «красти» RAM і додавати накладні витрати.

Виправлення: Вирішуйте проблему затримки записів на рівні vdev/sync. Додавайте L2ARC лише після підтвердження, що читання — вузьке місце і ARC-хітрейт недостатній.

Три корпоративні міні-історії з практики зберігання

Міні-історія №1: Інцидент через невірне припущення

Вони мігрували невеликий парк прикладних ВМ на Proxmox з ZFS-міррорами на «хороших SSD». Це був сенсовний, бюджетно-затверджений дизайн: два диски, дзеркало, на папері — багато IOPS. Додатки були переважно безстанніми веб-сервісами з невеликою базою даних і брокером повідомлень.

Неправильне припущення було тонким: «Якщо це дзеркальний SSD, sync-записи практично безкоштовні». Ніхто цього не проговорив вголос, і такі припущення виживають. Вони запустили платформу, вона виглядала чудово, а потім почала давати короткі жорсткі стрибки затримки під піком трафіку.

Команда на виклику ганялася за привидами: мережеві перебої, «шумні сусіди», CPU steal, навіть «можливо, в Linux регрес планувальника». Тим часом база даних робила цілком адекватні коміти з fsync, а ZFS робив цілком адекватно — чекав стабільного зберігання.

Коли вони порівняли графіки затримки запису хоста з таймаутами додатків, історія написала себе сама. SSD були споживчими моделями з нестабільною латентністю flush. Коли база даних потрапляла у сплеск sync-записів, пристрої зависали. Дзеркало не врятувало; воно просто надало два пристрої, які могли зависати одночасно.

Виправлення не було екзотичним. Вони розгорнули дзеркальний SLOG на пристроях з захистом від втрати живлення і перестали робити вигляд, що латентність flush не має значення. Стрибки зникли. Команда також задокументувала, які dataset можуть терпіти sync=disabled (декілька) і які ні (база даних і брокер). Головний урок — операційний: ніколи не припускайте, що ваше сховище швидко виконує гарантії довговічності лише тому, що це «SSD».

Міні-історія №2: Оптимізація, що відкотилася

Інша організація хотіла «максимальної продуктивності» і агресивно налаштувала все. Вони вимкнули sync глобально. Встановили VM-диски в writeback cache. Увімкнули всі перемикачі продуктивності, які лише знайшли. Також обрали qcow2, бо переміщати диски було «зручніше».

Деякий час це працювало. Бенчмарки виглядали героїчними. Деплої були швидкі. Усі давали «п’ять» і поверталися до фіч. Потім відбувся ребут хоста — рутинне оновлення ядра — і кілька ВМ повернулися з пошкодженими файловими системами. База даних відновилася. Поштовий VM — ні. Постмортем був… пізнавальний.

Відкат не стався через те, що будь-яке окреме налаштування «погане» само по собі. Проблема була у комбінації: writeback cache + sync disabled + характеристика записів qcow2 створили систему, що оптимістично підтверджувала записи. Система була швидкою, бо фактично брехала щодо того, що є стійким.

Вони повернулися до безпечніших дефолтів, але не сліпо. Вони винесли політику тюнінгу: для витратних навантажень важливіше швидкість; для станкових — надійність; для останніх вони оптимізували апаратний шлях зберігання, а не вимикали коректність. Також перейшли з qcow2 на raw, де це було можливо, щоб зменшити насладання CoW і накладні витрати на метадані.

Справжня вартість була не в корупції як такій — а в тижні втраченої довіри. Користувачам байдуже, що ви можете пояснити семантику кешу. Їм важливо, що їхні дані повернулися.

Міні-історія №3: Нудна, але правильна практика, що врятувала день

Середня компанія експлуатувала кластери Proxmox для внутрішніх сервісів. Нічого яскравого: контролери домену, Git, моніторинг, кілька малих баз даних і дивовижна кількість синхронізації файлів. Їхнє зберігання — ZFS-міррори і трохи RAIDZ для бекапів. Вони мали одну практику, що здавалася болюче нудною: щотижневі scrubs, моніторинг SMART і суворі пороги заповнення пулів.

Вони також стандартизували dataset для ВМ з однаковими властивостями: lz4 увімкнено, atime вимкнено і явні рішення щодо sync. Найважливіше — правило: жоден пул ВМ понад 80% без затвердженого плану розширення. Люди скаржилися. Фінанси скаржилися. Усі скаржаться, коли їм кажуть «ні».

Одного кварталу набір SSD почав показувати зростаючі помилки середовища. Нічого не вибухнуло. Просто тренд в SMART і кілька повільних читань, що проявилися як невеликі підвищення затримки під час scrubs. Завдяки регулярним scrubs і алертам, прив’язаним до змін, вони виявили це рано.

Вони замінили диски в робочий час, по одному, з контрольованими resilver-ами. Жодного інцидент-бріджу. Жодного видимого для клієнтів простою. Нудна практика — дисципліна scrubs і ємності — зробила так, що пул ніколи не потрапив у «занадто повний для безпечного resilver» стан. Вони не отримали нагороду. Вони просто не мали поганого тижня.

Чеклісти / покроковий план

Чекліст A: Дефолти зберігання на перший день для нового Proxmox ZFS VM пулу

  1. Створіть пул з коректним ashift (зазвичай 12). Перевірте з zdb -C перед тим, як класти туди дані.
  2. Створіть окремий dataset для сховища ВМ (не кидайте все в кореневі datasets).
  3. Встановіть compression=lz4 на dataset ВМ.
  4. Встановіть atime=off на dataset ВМ.
  5. Вирішіть політику sync по кожному dataset: за замовчуванням — надійність; вимикайте лише для втратних навантажень.
  6. Якщо використовуєте zvol, стандартизуйте volblocksize (часто 16K для загальних VM-дисків). Вирішіть до створення дисків.
  7. Вирішіть поведінку primarycache для дисків VM (розгляньте metadata-only для пам’ятевого тиску).
  8. Встановіть і дотримуйтеся порогів заповненості (сповіщення при 70–75%, дія при 80%).

Чекліст B: Коли ВМ відчувається повільною (триаж за 15 хвилин)

  1. Перевірте zpool status (помилки? resilver? scrub?). Якщо так — зупиніться і стабілізуйте.
  2. Перевірте zpool iostat -rlv 1 3 (затримка запису?). Якщо висока — вузьке місце шлях зберігання.
  3. Перевірте iostat -x 1 3 (await пристрою, iowait). Підтвердіть, що це не лише сприйняття гостя.
  4. Перевірте заповненість пулу і frag (zpool list, zfs list, використання snapshot-ів). Якщо занадто повний — потрібна ємність, а не «відчуття».
  5. Перевірте режим кешу диска ВМ (qm config) і властивості dataset (zfs get).

Чекліст C: Контрольована міграція для виправлення поганого volblocksize

  1. Створіть новий zvol з бажаним volblocksize.
  2. Використайте Proxmox storage migration або контрольоване блочне копіювання під час вимкнення ВМ (бажано для коректності).
  3. Перевірте продуктивність і затримку з zpool iostat -rlv і перевірками застосунку.
  4. Видаліть старий zvol і спостерігайте за фрагментацією та простором.

Поширені питання

1) Чи варто використовувати ZFS або LVM-thin для зберігання ВМ у Proxmox?

Якщо вам потрібні прості знімки та реплікація і цілісність «від краю до краю», ZFS — сильний вибір. Якщо ви хочете простішу модель блокового сховища і менше взаємодії CoW, LVM-thin може бути легшим для розуміння. Для багатьох команд ZFS виграє операційно — за умови, що ви ставите sync, ємність і розміри блоків у першу чергу.

2) Чи безпечно використовувати compression=lz4 для дисків ВМ?

Так. Це прозоро і широко розгорнуто. «Ризик» переважно в додатковому навантаженні на CPU, що зазвичай менше, ніж I/O, який ви заощаджуєте. Справжній ризик — не використовувати стиснення і потім дивуватися, чому пул завжди зайнятий переміщенням зайвих байтів.

3) Який volblocksize слід використовувати для zvol ВМ?

Звичні значення для загальних VM-дисків — 16K (часто хороший баланс). Для спеціалізованих навантажень вимірюйте: бази даних іноді полюбляють 8K або 16K; великі послідовні навантаження — 64K+. Ключ — послідовність і намір: вибирайте за навантаженням, а не за суєтою.

4) Чи можу я змінити volblocksize після створення zvol?

Ви можете змінити властивість, але вже записані блоки залишаться старого розміру. Щоб справді отримати користь, зазвичай мігрують дані на новий zvol з правильним volblocksize.

5) Чи варто вимкнути sync, щоб прискорити Proxmox?

Лише якщо ви готові втратити нещодавні записи при відключенні живлення або падінні — і лише для датасетів, де це прийнятно. Для реальних систем зі справжніми даними краще побудувати шлях зберігання, який витримає sync=standard, а не вимикати коректність глобально.

6) Чи потрібен мені SLOG для ZFS на SSD-дзеркалах?

Не обов’язково. Якщо ваше навантаження переважно асинхронне — ви можете бути в порядку. Якщо у вас значні sync-записи і вам важлива затримка, належний SLOG може сильно допомогти. «Належний» означає низьколатентний та захищений від втрати живлення, бажано в дзеркалі.

7) Чи погана ідея qcow2 на ZFS?

Зазвичай так — бо ви складаєте CoW на CoW, що збільшує фрагментацію і накладні витрати на метадані. Якщо вам потрібні фічі qcow2 — використовуйте усвідомлено. Інакше raw на ZFS зазвичай спокійніший і передбачуваніший вибір.

8) Чому продуктивність руйнується, коли пул наповнюється?

ZFS потребує вільного простору для ефективної алокації. Коли вільного місця стає мало, алокації ускладнюються, фрагментація зростає, і write amplification збільшується — особливо при випадковому I/O ВМ. Тримати 20–30% вільним — це не марнотратство; це купівля стабільної затримки.

9) Чи варто ставити primarycache=metadata для всього сховища ВМ?

Це хороший дефолт при великіх гостях і пам’ятевому тиску, бо зменшує подвійне кешування. Якщо хост має багато RAM і гості малі/читають інтенсивно, кеш даних може допомогти. Не вгадуйте: перевіряйте ARC і стан пам’яті гостей.

10) Чи autotrim завжди допомагає на SSD пулах?

Воно часто допомагає у довгостроковій поведінці місця і може підтримувати продуктивність SSD, але деякі пристрої погано переносять безперервні trims. Увімкніть, спостерігайте латентність і будьте готові перейти на планові trims.

Висновок: практичні подальші кроки

Якщо ви експлуатуєте Proxmox на ZFS і ще не торкалися дефолтів зберігання, швидше за все у вас система, що чудова у вівторок і зрадницька в четвер. Виправлення — це не магія. Це політика.

  1. Увімкніть compression=lz4 і atime=off на dataset ВМ сьогодні. Це низький ризик, зазвичай велика віддача.
  2. Аудитуйте поведінку sync. Вирішіть, що має бути надійним, і спроектуйте під це. Не вимикайте sync випадково по всьому пулу.
  3. Стандартизуйте volblocksize для нових VM-дисків (часто 16K) і плануйте міграції для найгірших випадків.
  4. Перестаньте переповнювати пулив. Ємність — це функція продуктивності. Зробіть її моніторинговим SLO, а не нічною несподіванкою.
  5. Вимірюйте затримку, а не лише пропускну здатність. Використовуйте zpool iostat -rlv і iostat -x, щоб тримати себе чесним.

Зробіть ці п’ять речей, і більшість скарг «ZFS повільний» зникне. Ті, що залишаться, будуть чесними проблемами — апаратні обмеження, реалії навантаження і поодинокі свідомі рішення.

← Попередня
Debian 13: TCP-перенадсилання вбивають продуктивність — знайдіть, де насправді втрати
Наступна →
Debian 13: зміна порту SSH — виправити порядок sshd і фаєрволу без блокування доступу (випадок №87)

Залишити коментар