Ви успадкували пул. Віртуальні машини здаються «нормальними», допоки не настає ніч патчів, ніч резервного копіювання або якась аналітика.
Хтось каже: «Давайте просто змінемо volblocksize і отримаємо кращі IOPS.» Ви киваєте, бо звучить як параметр.
Потім ви виконуєте команду, вона приймає значення, і… нічого не покращується. Іноді стає гірше. Потім ви дізнаєтесь неприємну істину:
ви змінили властивість, а не фізику вже записаних блоків.
ZVOL-и оманливо прості: блочний пристрій під керуванням ZFS. Але їхня поведінка щодо розміру блоків не така, як у файлового датасету з recordsize.
Коли ви «мігруєте» volblocksize, ви в основному змінюєте те, як будуть розташовуватися майбутні записування.
Існуючі дані залишаються розташованими по-старому, якщо ви їх не перезапишете. У продакшені «перезаписати» зазвичай означає
«створити ZVOL заново й перенести дані навмисно».
volblocksize — це не машина часу
Головна теза: зміна volblocksize на існуючому ZVOL рідко суттєво міняє продуктивність, доки дані не перезаписано.
ZFS не повертається й не «перепаковує» ZVOL просто тому, що ви попросили. Ви можете встановити властивість сьогодні,
але блоки, які вже лежать на диску, зберігають свій оригінальний розмір, сегментацію та структуру непрямих блоків.
Це не примха ZFS. Це його послідовність. ZFS — copy-on-write: він записує нові блоки в інше місце, оновлює метадані і тільки тоді змінює вказівники.
Він не перезаписує старі блоки на місці. Якщо ви хочете, щоб існуючі дані були перезаписані з новим розміром блоку, потрібен робочий процес, який змусить логічно повністю перезаписати том:
реплікація на новий ZVOL, відновлення з бекапу або покопійний запис на тільки-но створену ціль.
Практичний висновок: більшість «міграцій volblocksize» насправді — це проекти «створити заново і перемістити». Решта — бажання й запис у заявці на зміну
з післяпроєктним звітом «без відчутного ефекту».
Що насправді контролює volblocksize (і чого не контролює)
volblocksize: одиниця алокації ZVOL
ZVOL — це датасет ZFS типу volume. Він експортує блочний пристрій (наприклад, /dev/zvol/pool/vm-101-disk-0),
з яким споживачі поводяться як з диском. Для ZVOL-ів volblocksize — це максимальний розмір блоку, який ZFS виділятиме для
даних, записаних у ZVOL.
Якщо встановити volblocksize=16K, ZFS виділятиме блоки до 16KiB для даних ZVOL. Якщо встановити 8K,
— до 8KiB, і так далі. «До» має значення: ZFS може виділяти менші блоки, коли запис менший або коли стиснення зменшує обсяг.
Але конфігурований розмір суттєво впливає на алокацію та результатний шаблон I/O.
recordsize — для файлових датасетів, не для ZVOL
У файловому датасеті recordsize контролює максимальний розмір запису для файлових даних. Це про файлові блоки.
Воно взаємодіє з розміром I/O додатка, стисненням і випадковим доступом. У ZVOL-ах немає файлових записів;
є віртуальний диск. Гостьова ОС сама вирішує розміри блоків і розклад файлів, а ZFS бачить записи по LBA.
Якщо винести одну думку: налаштування recordsize часто досить прощаюче, бо файлові системи природно перезаписують «гарячі» файли з часом.
ZVOL-и, що підтримують диски VM, можуть довго залишатися з старим розкладом блоків, оскільки багато робочих навантажень не перезаписують увесь віртуальний диск —
особливо бази даних і довгоживучі образи VM.
Звідки бере походження біль: write amplification і невідповідність I/O
Найпростіше уявити поганий volblocksize як невідповідність. Ваше навантаження виконує 4K випадкові записи, а ви встановили
volblocksize=128K. ZFS тепер схильний виділяти (а потім читати/модифікувати/перезаписувати) набагато більші шматки.
На синхронічних навантаженнях ця невідповідність може перетворитися на стрибки затримки, роздуті метадані і I/O-профіль, що нагадує слона на роликах.
Інша невідповідність — між volblocksize і параметром пулу ashift (вирівнювання фізичного розміру сектора).
З такою невідповідністю можна «працювати», але платою буде додатковий I/O, гірша фрагментація та посилене записування на пристрій.
Плата надходить у вигляді затримок.
Жарт №1: Змінювати volblocksize на завантаженому ZVOL і очікувати миттєвого покращення — як пофарбувати навантажувач і назвати його турбоапгрейдом.
Чому зміна рідко виправляє існуючі дані
Властивості ZFS не завжди діють ретроспективно
Властивості ZFS поділяються на категорії. Деякі впливають на поведінку під час виконання (наприклад, compression для майбутніх записів),
деякі впливають на рішення метаданих, а деякі — головним чином політика для нових алокацій. volblocksize належить до
категорії «нові алокації». Воно не викликає перезапис існуючих блоків, бо це була б масивна, ризикована фоновa операція.
Copy-on-write означає «перезапис відбувається тільки коли навантаження перезаписує»
ZFS виділяє нові блоки при модифікації. Він не заходить до старих блоків, щоб «нормалізувати» їх під новий бажаний розмір.
Тому при зміні volblocksize лише блоки, записані після цього моменту, ймовірно, відображатимуть новий розмір.
Якщо ваш диск VM має великий майже статичний образ ОС і невеликий активно змінюваний файл бази даних, ви можете побачити,
що зміниться лише невелика частина блоків, а більшість залишиться в старому розкладi.
Навіть якщо гість перезапише, снапшоти можуть зафіксувати старі блоки
Снапшоти — інша пастка. Якщо у вас є часті снапшоти (бекупи VM, точки реплікації, «про всяк випадок» снапшоти, які ніколи не видаляються),
старі блоки залишаються посиланнями й не можуть бути звільнені. Гість може перезаписувати дані, але старі блоки залишаються зафіксованими снапшотами,
що зберігає фрагментацію і використання простору без змін. Ваш новий розклад співіснує зі старим. Вітаємо, у вас тепер музей.
Пастка «він прийняв властивість»
ZFS охоче приймає zfs set volblocksize=... для багатьох систем, коли ZVOL не використовується активно, або іноді відмовить з повідомленням «in use»
залежно від платформи та реалізації ZFS. Прийняття не означає, що ви отримали бажану міграцію.
Це означає, що датасет тепер має значення властивості, яке керуватиме майбутніми алокаціями. Ось і все.
Чому створення заново зазвичай чисте рішення
Створення ZVOL заново змушує всі блоки виділятись наново за новою політикою. Це єдиний детерміністичний спосіб гарантувати,
що весь том отримає нову поведінку volblocksize. Все інше — ймовірнісне та повільне, і зривається снапшотами,
тонким провізуванням і частковими перезаписами.
Цікаві факти та історичний контекст
- ZFS зʼявився в Sun у середині 2000-х, спроєктований навколо цілісності даних end-to-end, copy-on-write і обʼєднаного сховища — ідей, що згодом стали стандартом.
- ZVOL-и були свідомим мостом «блочний пристрій»: вони дозволяли ZFS обслуговувати навантаження, що вимагають абстракції диска (VM, iSCSI) без примусу файлової системи в гості.
- Первинний акцент ZFS був на коректності, а не на мікрооптимізаціях; параметри на кшталт розмірів блоків були регуляторами політики, а не механізмом для «живого» переформатування.
- Диски Advanced Format (4K сектори) зробили питання вирівнювання дуже помітним;
ashiftстав критичним рішенням при проєктуванні пулу. - Зростання популярності VM сприяло поширенню ZVOL, бо гіпервізори та SAN-інструменти «говорять» з блочними пристроями простіше, навіть якщо образи на файлах були б простішими.
- Раннє прийняття ZFS-on-Linux прискорило операційні практики на кшталт
zfs send/receive, роблячи «створити заново й стрімити дані» звичною операцією. - Стиснення стало масовим не тільки для економії ємності, а й для продуктивності: менше I/O часто перемагає більше CPU, особливо на SSD-пулах.
- Снапшоти змінили операційну культуру: команди почали робити снапшоти всього, бо це дешево — поки не стало дорогим через забиті зафіксовані блоки й довгі ланцюги утримання.
- Коли затримка NVMe впала, програмні витрати й I/O-ампліфікація стали помітнішими; поганий вибір розміру блоків може марнувати переваги швидких накопичувачів.
Швидкий план діагностики
Коли хтось скаржиться «ZVOL повільний», не починайте зі зміни volblocksize. Почніть із зʼясування, який рівень бреше.
Ось стислий порядок, який швидко знаходить вузьке місце.
1) По-перше: це затримка чи пропускна здатність?
- Якщо користувачі скаржаться на «пригальмовування VM» і «таймаути DB», вважайте, що це затримка.
- Якщо повільні бекапи або масові копії, думайте про пропускну здатність — якщо тільки це не синхронні записи.
2) По-друге: чи навантаження обмежене синхронністю?
- Перевірте поведінку
syncі чи є у вас адекватний SLOG (або його немає — і це теж нормально). - Синхронно-важкі випадки випадкових записів підсилюють будь-яку погану позицію: розмір блоку, фрагментацію і черги пристрою.
3) По-третє: підтвердіть реальний розмір I/O, який бачить пул
- Спостерігайте розміри I/O на рівні ZFS. Якщо ви бачите 128K записи, а додаток каже 4K, щось або об’єднує, або бреше.
4) По-четверте: перевірте фрагментацію й фіксацію снапшотами
- Висока фрагментація плюс довгі ланцюги снапшотів можуть вбити випадковий I/O навіть на SSD.
- Якщо блоки не можуть бути звільнені, «налаштування» стає плацебо.
5) По-п’яте: тільки тоді вирішіть, чи volblocksize — важіль
- Якщо навантаження — 4K/8K випадкові I/O (бази даних, завантаження VM), менший
volblocksizeчасто допомагає. - Якщо це великі послідовні записи/зчитування (відео, бекапи в гості), більші блоки можуть допомогти — за умови, що гість дійсно посилає великі I/O.
Практичні завдання: команди, виводи та рішення
Мета команд — не виглядати зайнятим. Мета — перетворити «я думаю» на «я знаю», а потім прийняти рішення, яке можна відстояти на ревʼю.
Нижче — практичні кроки, які я реально використовую при діагностиці чи плануванні міграції volblocksize для ZVOL.
Завдання 1: Визначити ZVOL і перевірити поточний volblocksize
cr0x@server:~$ zfs list -t volume -o name,volsize,volblocksize,compression,sync pool/vm-101-disk-0
NAME VOLSIZE VOLBLOCKSIZE COMPRESS SYNC
pool/vm-101-disk-0 200G 128K lz4 standard
Що це означає: Цей ZVOL налаштований виділяти блоки до 128K для майбутніх записів. Також він стискає дані lz4.
Sync — standard (виконує запити додатків).
Рішення: Якщо навантаження гостя в основному 4K/8K випадкові записи, 128K викликає підозру. Не змінюйте одразу. Спочатку виміряйте.
Завдання 2: Перевірити, успадкована чи явно встановлена властивість
cr0x@server:~$ zfs get -H -o property,value,source volblocksize pool/vm-101-disk-0
volblocksize 128K local
Що це означає: Властивість встановлена локально. Хтось це обирав.
Рішення: Розглядайте це як навмисну спробу налаштування. Запитайте, яке навантаження і навіщо. Припустіть, що пояснення втрачено з часом.
Завдання 3: Підтвердити ashift пулу й розміщення vdev (перевірка вирівнювання)
cr0x@server:~$ zdb -C pool | sed -n '1,120p'
MOS Configuration:
version: 5000
name: 'pool'
state: 0
txg: 1234567
pool_guid: 1234567890123456789
hostid: 1122334455
hostname: 'server'
vdev_tree:
type: 'root'
id: 0
guid: 9876543210987654321
children[0]:
type: 'mirror'
id: 0
guid: 1111111111111111111
ashift: 12
Що це означає: ashift: 12 означає 4K сектори (2^12). Добрий базовий рівень для сучасних SSD/HDD.
Рішення: Якби ashift був 9 (512B) на 4K носіях, у вас були б проблеми більші за volblocksize. Плануйте міграцію пулу, а не дрібне налаштування ZVOL.
Завдання 4: Перевірити стан «використовується» ZVOL і чи дозволено змінювати на льоту
cr0x@server:~$ zfs set volblocksize=16K pool/vm-101-disk-0
cannot set property for 'pool/vm-101-disk-0': volume is busy
Що це означає: Ядро використовує блочний пристрій (відображено, експортовано через iSCSI, приєднано до VM тощо).
Рішення: Не боріться з цим. Плануйте міграцію на новий ZVOL з бажаним розміром блоку, а потім переключення.
Завдання 5: Визначити, хто споживає ZVOL (VM, iSCSI, multipath)
cr0x@server:~$ ls -l /dev/zvol/pool/vm-101-disk-0
lrwxrwxrwx 1 root root 13 Dec 26 02:10 /dev/zvol/pool/vm-101-disk-0 -> ../../zd0
cr0x@server:~$ lsblk -o NAME,TYPE,SIZE,MOUNTPOINT,FSTYPE /dev/zd0
NAME TYPE SIZE MOUNTPOINT FSTYPE
zd0 disk 200G
Що це означає: ZVOL — це raw-диск zd0. Якщо ви бачите його змонтованим, відображеним у DM або використаним через iSCSI,
це пояснює «busy».
Рішення: Відстежте ланцюжок залежностей перед плануванням вікна міграції. Люди засмучуються, коли ви відключаєте «просто диск».
Завдання 6: Перевірити кількість снапшотів і ризик утримання (прикріплені блоки)
cr0x@server:~$ zfs list -t snapshot -o name,used,refer -s creation | grep '^pool/vm-101-disk-0@' | tail -n 5
pool/vm-101-disk-0@auto-2025-12-26_0000 1.2G 180G
pool/vm-101-disk-0@auto-2025-12-26_0100 600M 180G
pool/vm-101-disk-0@auto-2025-12-26_0200 400M 180G
pool/vm-101-disk-0@auto-2025-12-26_0300 250M 180G
pool/vm-101-disk-0@auto-2025-12-26_0400 200M 180G
Що це означає: У вас часті снапшоти. Стовпець used свідчить про активну зміну блоків. Старі блоки, ймовірно, зафіксовані.
Рішення: Якщо ви сподівалися, що «навантаження само перезапише дані під новий volblocksize», снапшоти вам завадять.
Міграція на новий ZVOL з чистою політикою снапшотів — розумний шлях.
Завдання 7: Виміряти I/O і затримку на рівні пулу
cr0x@server:~$ zpool iostat -v pool 1 5
capacity operations bandwidth
pool alloc free read write read write
---------- ----- ----- ----- ----- ----- -----
pool 4.20T 3.10T 820 2400 45.2M 110M
mirror 4.20T 3.10T 820 2400 45.2M 110M
nvme0n1 - - 410 1200 22.6M 55M
nvme1n1 - - 410 1200 22.6M 55M
Що це означає: Ви маєте багато записів. Це час запитати: чи ці записи синхронні? Чи вони дрібні випадкові? Чи послідовні?
Рішення: Якщо пропускна здатність висока, але скарги на затримку лишаються, проблема ймовірно в синхронній затримці, чергах або write amplification,
а не в сирій пропускній здатності.
Завдання 8: Перевірити I/O по датасетах (чи дійсно ZVOL — гаряча точка?)
cr0x@server:~$ zfs iostat -v pool 1 3
capacity operations bandwidth
dataset alloc free read write read write
----------------------------- ----- ----- ----- ----- ----- -----
pool 4.20T 3.10T 0 0 0 0
pool/vm-101-disk-0 200G 3.10T 120 1600 3.2M 62M
pool/vm-102-disk-0 120G 3.10T 40 300 1.1M 10M
Що це означає: vm-101 домінує у записах.
Рішення: Не починайте глобальне налаштування пулу, якщо винен один ZVOL. Виправте порушника.
Завдання 9: Перевірити коефіцієнт стиснення і ризик вибуху метаданих при меншому блоці
cr0x@server:~$ zfs get -H -o property,value compressratio pool/vm-101-disk-0
compressratio 1.45x
Що це означає: Стиснення працює. Менші volblocksize можуть зменшити read-modify-write на дрібних записах,
але можуть збільшити навантаження на метадані й знизити ефективність стиснення в деяких сценаріях.
Рішення: Якщо навантаження схоже на БД, віддавайте перевагу коректності й затримці над теоретичними вигодами стиснення.
Завдання 10: Підтвердити поведінку TRIM (перевірка тонкої провізії)
cr0x@server:~$ zfs get -H -o property,value autotrim pool
autotrim on
Що це означає: Пул автоматично виконує TRIM (поведінка залежить від реалізації). Для ZVOL-ів, що використовуються гостем,
також потрібна підтримка discard у стеку гостя, щоб ефективно звільняти простір.
Рішення: Якщо використання простору росте після видалення в гості, перевірте guest discard і політику снапшотів, перш ніж звинувачувати volblocksize.
Завдання 11: Оцінити можливість перезапису швидким логічним тестом копіювання (оффлайн або на клоні)
cr0x@server:~$ zfs snapshot pool/vm-101-disk-0@pre-migrate
cr0x@server:~$ zfs clone pool/vm-101-disk-0@pre-migrate pool/vm-101-disk-0-clone
Що це означає: У вас тепер клон, який розділяє блоки. Він чудово підходить для тестування робочих процесів, але не для примусового перезапису.
Рішення: Використовуйте клон для валідації кроків експорту/підключення, а не для «виправлення» розкладки блоків. Спільні блоки залишаються спільними, поки не перезаписані.
Завдання 12: Створити новий ZVOL із потрібним volblocksize (реальний крок міграції)
cr0x@server:~$ zfs create -V 200G -b 16K -o compression=lz4 -o sync=standard pool/vm-101-disk-0-new
cr0x@server:~$ zfs list -t volume -o name,volsize,volblocksize pool/vm-101-disk-0-new
NAME VOLSIZE VOLBLOCKSIZE
pool/vm-101-disk-0-new 200G 16K
Що це означає: У вас чиста цільова ZVOL з новим розміром блоку. Це єдиний спосіб гарантувати політику виділення.
Рішення: Погодьте план переключення. Решта — це рух даних і операційна дисципліна.
Завдання 13: Поблокове копіювання з індикацією (оффлайн-міграція)
cr0x@server:~$ dd if=/dev/zvol/pool/vm-101-disk-0 of=/dev/zvol/pool/vm-101-disk-0-new bs=16M status=progress conv=sync,noerror
21474836480 bytes (21 GB, 20 GiB) copied, 42 s, 511 MB/s
Що це означає: Ви виконуєте логічний перезапис на новий ZVOL. Приймач буде виділятися згідно своєї політики volblocksize,
коли потік даних ляже.
Рішення: Використовуйте це тільки коли джерело призупинено (VM вимкнено, файлову систему приведено в консистентний стан), якщо ви не робите навмисно copy в стані crash-consistent.
Зазвичай — вимкніть VM.
Завдання 14: Перевірити, чи гість бачить ті самі очікування щодо ідентичності диска (UUID, розділи)
cr0x@server:~$ sgdisk -p /dev/zvol/pool/vm-101-disk-0-new
Disk /dev/zvol/pool/vm-101-disk-0-new: 419430400 sectors, 200.0 GiB
Sector size (logical/physical): 512/4096 bytes
Disk identifier (GUID): 5A1B2C3D-4E5F-6789-ABCD-0123456789AB
Partition table holds up to 128 entries
Number Start (sector) End (sector) Size Code Name
1 2048 2099199 1024.0 MiB EF00 EFI System
2 2099200 419428351 199.0 GiB 8300 Linux filesystem
Що це означає: Таблиця розділів скопіювалася і виглядає консистентною. Вивід «Sector size» корисний: якщо гість очікує 4K,
переконайтеся, що ви його не здивуєте.
Рішення: Якщо бачите несподівані розміри секторів або відсутні розділи, зупиніться. Не переходьте до cutover, поки не зрозумієте причину.
Завдання 15: Переключення шляхом атомарної зміни імен ZVOL (з обережним порядком)
cr0x@server:~$ zfs rename pool/vm-101-disk-0 pool/vm-101-disk-0-old
cr0x@server:~$ zfs rename pool/vm-101-disk-0-new pool/vm-101-disk-0
cr0x@server:~$ zfs list -t volume -o name,volblocksize pool/vm-101-disk-0
NAME VOLBLOCKSIZE
pool/vm-101-disk-0 16K
Що це означає: Канонічне імʼя тепер вказує на новий ZVOL, тому будь-яка автоматизація, що посилається на шлях датасету, продовжує працювати.
Рішення: Тримайте старий ZVOL до завершення валідації. Потім видаліть його свідомо, а не на імпульсі.
Стратегії міграції, які справді працюють
Стратегія A: Створити заново + блочне копіювання (просто, грубо, ефективно)
Це підхід з dd або іміджуванням. Працює добре, коли можна взяти простій і хочете детерміністичний перезапис.
Також це найпростіше пояснити change management: «створили новий том з коректною геометрією і скопіювали диск».
Тріад:
- Плюси: Гарантує перезапис, поважає новий
volblocksize, мінімальна «магія» ZFS. - Мінуси: Потребує простою для консистентності; копіює й незайнятий простір; повільно, якщо диск переважно порожній.
Стратегія B: Створити заново + міграція на файловому рівні всередині гостя (чистіші дані, але більше частин)
Якщо ви можете приєднати другий диск до VM, можна мігрувати на рівні файлової системи: створити новий ZVOL, приєднати до гостя, відформатувати,
скопіювати дані (rsync, дамп/відновлення БД), а потім перемкнути конфігурацію завантаження. Це перезаписує лише використані дані і часто дає менше фрагментації.
Це повільніше в людському вимірі, але швидше в термінах використаного сховища.
- Плюси: Не копіює невикористані блоки; може покращити розклад файлової системи гостя; часто менший downtime.
- Мінуси: Потребує змін у гості; більше точок відмови; потребує уважного забезпечення консистентності додатка.
Стратегія C: ZFS send/receive — для датасетів, а не для «конвертації volblocksize»
Люди тягнуться до zfs send/receive, бо це молоток ZFS. Воно чудове для переміщення датасетів і збереження снапшотів.
Але для зміни volblocksize це не магічна кнопка. Реплікація зберігає структуру блоків, представлену в потоці.
У багатьох практичних випадках receive не «переблокує» ваші дані під новий volblocksize.
Використовуйте send/receive для:
- Переміщення ZVOL на інший пул або хост.
- Збереження снапшотів/історії.
- ДР-сценарії, де важлива ідентичність і відкат по точці часу.
Використовуйте recreate-and-copy коли:
- Потрібна детерміністична зміна політики алокації.
- Хочете відірватися від спадщини довгих ланцюгів снапшотів і фрагментації.
- Потрібен реальний скидання продуктивності, який можна виміряти.
Стратегія D: «Нехай самі перезапишуться» (зазвичай пастка)
Іноді команди змінюють volblocksize і сподіваються, що навантаження з часом перепише достатньо даних і новий розмір почне діяти.
Це може спрацювати в вузьких випадках: ефермерні навантаження, CI-ранери, кеші або шаблони VM, які часто перевстановлюються.
Це не вдасться коли:
- Снапшоти фіксують старі блоки.
- Диск переважно статичний (OS + встановлені додатки) і зміна мала відносно обсягу.
- Навантаження «гаряче в маленькій області» (бази даних), що перезаписує ту саму ділянку і збільшує фрагментацію, не змінюючи решту.
Цитата про надійність, щоб тримати вас на місці
Відомий вислів Браяна Кернігана добре підходить до змін у сховищі: «Налагодження вдвічі складніше, ніж написання коду.»
(парафраз)
Міграції сховища складні не тому, що команди важкі. Вони складні через те, що припущення множаться швидше, ніж IOPS на тесті.
Три міні-історії з корпоративного життя
Міні-історія 1: Інцидент через неправильне припущення
Середня компанія мала кластер віртуалізації з дисками на ZVOL. Новий інженер помітив, що за замовчуванням volblocksize
десь 8K на старих ZVOL, а десь 128K на нових. Він припустив «більші блоки = краща пропускна здатність», і що «ZFS все вирішить».
Було подано заявку на зміну всього до 128K.
Перше несподівання — деякі томи відмовлялися змінюватися, бо були «busy». Інженер обійшов це, перезавантажуючи VMs пакетно і міняючи властивість при відключених дисках.
Друге, більш тонке, — деякі БД VM почали показувати періодичні стрибки затримки.
Припущення, яке їх підкосило: зміна властивості «перетворить» існуючий розклад блоків. Не перетворила. Вони мали змішаний розклад: старі ~8K блоки, нові 128K алокації,
і довга історія снапшотів, що фіксували старі блоки. Графіки виглядали як звичайна завантажена система — поки не подивишся на tail latency і час синхронних записів.
Виправлення було нудним: створили нові 16K ZVOL для БД VM, зробили контрольовані оффлайн покочі копії, переключилися і скоротили утримання снапшотів для тих томів.
Продуктивність стабілізувалась, і кластер перестав мати «таємничі вівторки».
Урок: зміна властивості — не план міграції. Якщо потрібна міграція — мігруйте.
Міні-історія 2: Оптимізація, що повернулась бумерангом
Команда підприємства тримала iSCSI-цілі на ZVOL. На папері робоче навантаження виглядало послідовним: нічні ETL-дампи та великі передачі файлів.
Вони поставили volblocksize=256K для «максимальної стрімінгової продуктивності», і на бенчмарку було чудово.
Потім прийшла продакшн. Навантаження виявилося не лише дампами; також був фоновий агент, що робив дрібні випадкові записи для «відстеження прогресу»,
плюс інструмент безпеки постійно оновлював крихітні файли. Ініціатори iSCSI надсилали мікс 4K синхронних записів і більших асинхронних записів.
Затримка зросла, потім зʼявилися бурстові паузи. ETL-програми почали пропускати вікна.
Що сталося: з великим volblocksize дрібні синхронні записи викликали більше read-modify-write і метаданевого шуму.
Послідовна частина прискорилась; tail latency погіршився. Tail latency помічають користувачі і саме він примножується в розподілених системах.
Відкат був незручним, бо «просто повернути volblocksize назад» не переклав уже змінені алокації; воно лише зупинило подальший дрейф.
Зрештою вони пересоздали ZVOL на 16K, відновлювали з бекапів на рівні додатків (не блочних), і прийняли, що перемога на бенчмарку не відображала продакшн.
Урок: оптимізувати під середнє — це купувати аварії. Оптимізуйте під «потворне», змішане навантаження, що реально працює о 2 ранку.
Міні-історія 3: Нудна, але правильна практика, що врятувала день
У регульованій організації була стандартна практика: кожен ZVOL для диска VM створювався через тонкий скрипт-обгортку, який встановлював
volblocksize залежно від класу навантаження (загальна VM, БД, лог-важке), і додавав людський тег до датасету.
Нікому скрипт не подобався. Усі хотіли «просто створити том».
Роки потому оновлення сховища змусило їх мігрувати пули. Під час планування виявилися розкидані ZVOL-и з дивними розмірами і проблемами продуктивності.
Теги зі скрипта одразу показали, які томи мали бути DB-класу, які — загальні, а які — унікальні «сніжинки», створені вручну під час інциденту.
Коли одна чутлива БД почала показувати затримки після переміщення, команда мала чітку документовану базу: вона мала бути 16K. І була.
Вони не втрачали тиждень на сперечання про розміри блоків. Перевірили синхронну затримку, SLOG, знайшли неправильно налаштований ініціатор, що примушував флеші кеша, і виправили реальну проблему.
Нудна практика — не в скрипті. Вона в наполегливості забезпечувати повторюваність і метадані: система описувала, якою має бути.
Це запобігло спекулятивним налаштуванням під тиском.
Урок: найкращий інструмент міграції — це стандарт, введений вами поза кризою.
Поширені помилки: симптом → причина → виправлення
1) Симптом: «Ми змінили volblocksize і нічого не сталося»
Причина: Існуючі блоки не були перезаписані; політика утримання снапшотів зафіксувала старі алокації.
Виправлення: Створіть ZVOL заново з потрібним параметром -b і виконайте логічний перезапис (оффлайн блочна копія або відновлення на рівні гостя).
Перегляньте снапшоти і політику зберігання; не тягніть десятирічний музей снапшотів у міграцію продуктивності, якщо це не дійсно необхідно.
2) Симптом: «Затримка випадкових записів зросла після збільшення volblocksize»
Причина: Read-modify-write ампліфікація і метаданеве навантаження на дрібних синхронних записах.
Виправлення: Для навантажень типу баз даних частіше обирайте volblocksize 8K–16K. Перевіряйте на робочому навантаженні,
а не на загальних послідовних бенчмарках. Якщо потрібна консистентна розкладка, пересоздайте і перезапишіть.
3) Симптом: «Використання простору не зменшилось після видалення даних у VM»
Причина: Видалення в гості без discard/TRIM, снапшоти фіксують старі блоки або навантаження перезаписує без звільнення через ланцюги снапшотів.
Виправлення: Переконайтесь у налаштуваннях guest discard/TRIM, видаліть непотрібні снапшоти і перевірте, що інструменти резервного копіювання не роблять снапшоти що годину назавжди.
4) Симптом: «zfs set volblocksize fails with ‘volume is busy’»
Причина: Блочний пристрій приєднано, відкрито, відображено або експортовано. Багато платформ не дозволяють змінювати це в використанні.
Виправлення: Не плануйте ризиковане live-твікання. Створіть новий ZVOL з правильним розміром і мігруйте. Якщо потрібен майже нульовий downtime,
використовуйте реплікацію на рівні додатка або дзеркалювання в гості, а потім переключайте.
5) Симптом: «Читання швидке, записи повільні, CPU низький»
Причина: Синхронні записи потрапляють на повільний шлях (немає відповідного SLOG, неправильно налаштований sync або сховище не може фіксувати швидко).
Виправлення: Перевірте поведінку sync на рівні додатка й ZFS. Якщо встановлюєте SLOG — робіть це правильно (носій з захистом від втрати живлення), або не ставте.
Не використовуйте sync=disabled як фічу продуктивності, якщо ви не готові прийняти втрату підтверджених записів.
6) Симптом: «Після міграції продуктивність спочатку покращилась, а потім погіршилась»
Причина: Фрагментація зросла через постійні дрібні випадкові записи; політика снапшотів блокувала прибирання; файлову систему гостя можливо здорово фрагментовано.
Виправлення: Перегляньте політику снапшотів, розгляньте періодичне технічне обслуговування в гості (наприклад, обслуговування БД, trim файлової системи) і моніторьте індикатори фрагментації.
Не сприймайте volblocksize як одноразовий диво-регулятор.
Жарт №2: Снапшоти — як корпоративний політик збереження пошти: всі їх люблять, поки не дізнаються, що вони зберігають кожне погане рішення назавжди.
Перевірочні списки / покроковий план
Контрольний список рішення: чи варто створювати ZVOL заново?
- Чи домінує навантаження дрібний випадковий I/O (4K–16K)? Якщо так, ймовірно, потрібен менший
volblocksize. - Чи є довгий ланцюг снапшотів? Якщо так, «природний перезапис» не конвертує старі блоки.
- Чи том зайнятий і не можна змінити властивість? Це ваша відповідь: створити заново і переключити.
- Чи потрібна передбачувана, вимірювана зміна у вікні обслуговування? Створюйте заново.
- Чи том ефермерний і часто повністю перезаписується? Можливо, вистачить встановити властивість для майбутніх записів.
Покроково: безпечне створення заново й переключення (оффлайн, мінімальна драма)
- Базові метрики. Захопіть iostat пулу й датасету під час проблемного вікна. Підтвердіть, як виглядає «погано», щоб можна було перевірити «краще».
-
Інвентар властивостей. Запишіть
volsize,volblocksize,compression,sync,
reservation/refreservationі політику снапшотів. - Гарантія відкату. Зробіть фінальний снапшот і перевірте, що бекапи валідні (не тільки «налаштовані»).
- Заплануйте простій або метод забезпечення консистентності. Вимкніть VM або підготуйте quiesce додатка. Визначте, що означає «консистентно».
-
Створіть цільовий ZVOL. Використайте
zfs create -V ... -b ...з явними властивостями. Без несподіваного успадкування. - Скопіюйте дані. Використовуйте блочну копію для простоти або копію на рівні гостя для ефективності. Перевірте результат.
- Переключіться шляхом перейменування чи перепідключення. Бажано перейменування датасету для сумісності з автоматизацією. Перевірте шляхи пристроїв.
- Завантажте й перевірте. Перевірте файлову систему гостя, стан додатків і затримки сховища.
- Моніторьте 24–72 години. Слідкуйте за tail latency, синхронними записами і ростом снапшотів.
- Виведіть старий ZVOL. Тримайте його в визначений період відкату, потім свідомо видаліть. Документуйте зміну.
Покроково: якщо ви наполягаєте на «змінити на місці»
Іноді негайна міграція неможлива. Якщо ви збираєтеся встановити volblocksize без створення заново, робіть це відкрито:
- Підтвердьте, що немає снапшотів, які назавжди триматимуть старі блоки (або прийміть наслідки).
- Встановіть властивість у тихий період; очікуйте нульового негайного покращення.
- Сплануйте пізнішу «подію перезапису» (відновлення з бекапу, перевстановлення, повна копія диска), що реально змінить розклад.
Питання та відповіді
1) Чи можу я змінити volblocksize на існуючому ZVOL?
Іноді ви можете встановити властивість, іноді відмовить, якщо том зайнятий. Навіть якщо операція вдалась, вона зазвичай впливає лише на майбутні алокації.
Надійно це не конвертує існуючу розкладку даних.
2) Чому створення ZVOL заново працює, коли зміна властивості ні?
Створення заново змушує всі блоки виділятись наново згідно нової політики. Копіювання даних на свіжий ZVOL виконує повний логічний перезапис,
що саме і потрібно для «міграції» поведінки розміру блоків.
3) Чи змінює zfs send/receive volblocksize?
Не робіть з нього інструмент конвертації. Send/receive чудово підходить для реплікації і переміщення датасетів, але не гарантує трансформації розблокування існуючих алокацій.
Якщо потрібна детерміністична зміна розміру блоків — створюйте заново і перезаписуйте.
4) Який volblocksize вибрати для дисків VM?
Для загальних VM зазвичай практичний діапазон 8K–16K. Бази даних часто віддають перевагу меншим. Великі послідовні навантаження можуть виправдати більші значення.
Обирайте, спираючись на реальні розміри I/O і поведінку sync, а не на ідеологію.
5) Чи менший volblocksize завжди швидший для випадкового I/O?
Часто так, але не завжди. Менші блоки можуть зменшити read-modify-write на дрібних записах, але можуть підвищити навантаження на метадані і знизити ефективність стиснення.
Якщо у вас вузьке місце в CPU через стиснення або метадані, менший розмір може нашкодити. Міряйте на реальному навантаженні.
6) Як снапшоти заважають міграції volblocksize?
Снапшоти зберігають посилання на старі блоки. Навіть якщо гість перезапише дані, старі блоки залишаються алокованими і фрагментація зберігається.
Ви отримаєте змішаний розклад і менше вигід, ніж очікували.
7) Чи вирішить проблему встановлення sync=disabled?
Це не вирішення. Це бізнес-рішення прийняти можливість втрати підтверджених записів при аварії або відключенні живлення. Якщо ви готові ризикувати — задокументуйте це.
Інакше вирішуйте реальний шлях синхронізації (затримка пристрою, дизайн SLOG, поведінка ініціатора).
8) Чи можна безпечно використовувати тонку провізіювання ZVOL під час міграції?
Так, але розумійте механізм звільнення простору. Переконайтесь, що discard/TRIM працює end-to-end (гість → гіпервізор → ZVOL → пул → SSD).
Памʼятайте, що снапшоти можуть блокувати reclaim. Міграція через відновлення на рівні гостя часто краще повертає простір, ніж блочне копіювання.
9) Як довести, що новий volblocksize допоміг?
Порівняйте затримки до/після (особливо tail latency), час синхронних записів і метрики додатка. Пропускна здатність пулу сама по собі — слабкий сигнал.
Використовуйте zpool iostat, zfs iostat і специфічні метрики навантаження.
10) Якщо я вже змінив volblocksize, чи слід повернути назад?
Якщо ви змінили і побачили регресію, повернення назад може не скасувати вже змінені алокації. Воно може лише зупинити подальший дрейф,
але чисте виправлення все ще — створити заново і перезаписати уражений том.
Наступні кроки, які можна зробити цього тижня
Якщо у вас є скарги на продуктивність ZVOL і купа напівзабутих спроб налаштувань, зробіть це в такому порядку:
- Виберіть один проблемний ZVOL і зберіть 10-хвилинну базу під реальним навантаженням:
zpool iostat -v 1іzfs iostat -v 1. - Перелічіть снапшоти й політику утримання для цього ZVOL. Якщо у вас музей снапшотів — визнайте це й плануйте очищення або міграцію без перенесення музею.
- Створіть тестовий ZVOL з цільовим
volblocksizeі проведіть контрольовану міграцію у вікні обслуговування. Виміряйте tail latency і поведінку додатка. - Стандартизируйте процес створення: задокументуйте, написавши скрипт, тегуйте датасети. Майбутній ви буде вдячний.
Суть не в поклонінні числу 8K чи 16K. Суть — зробити розклад блоків свідомим вибором і забезпечити, щоб його виконували шляхом створення заново, коли потрібна реальна зміна.
ZFS дає гострі інструменти. Користуйтеся ними, ніби ви будете на чергуванні, коли їх відключать.