Флаги функцій ZFS — це та інженерна ідея, яка виглядає пристойно на слайді, але стає дуже особистою о 03:17, коли ви намагаєтеся імпортувати пул на «іншому» хості, а він просто відмовляється. Вони — як маркери ДНК вашого пулу: як тільки деякі ознаки проявляться, притворятися, що їх немає, не вийде. І пул не буде поступатися вашій ностальгії за старішими ядрами, старими завантажувачами або тим єдиним запасним сервером, який ніхто не оновлював, бо «це лише резерв».
Цей матеріал про переносимість: як переміщувати пули між хостами, як оновлення змінюють вимоги пулу і як безпечно реплікувати між версіями. Він написаний з погляду людини, яка бачила, як упевнене «просто оновіть» перетворювалося на повноцінний виклик інциденту, і також бачила, як нудна дисципліна сумісності тихо рятувала вихідні дні.
Що таке флаги функцій (і навіщо вони існують)
У старому підході ZFS був «номер версії пулу». Ви оновлювали пул з версії N до N+1, і це число інформувало про можливості пулу та його вимоги. Це працювало, поки не стало не працювати: різні постачальники впроваджували різні функції під одним і тим же номером версії, і люди отримували пули, які «мають» імпортуватися, але не могли — або, що гірше, імпортувалися й поводилися дивно.
Флаги функцій замінили монолітний номер версії на чеснішу модель: пул декларує набір функцій, кожна має своє ім’я (наприклад, feature@async_destroy або feature@encryption) і стан. Хости декларують, які функції вони розуміють. Сумісність стає задачею перетину множин, а не однієї цифри, що брешуть.
Операційно флаги функцій важливі, бо вони «липкі». Деякі функції лише «enabled» і безпечні, поки не використані; інші стають «active» і змінюють структури на диску так, що старі реалізації не зможуть їх розібрати. Коли це відбувається, пул не можна імпортувати на хості без цієї функції — незалежно від ваших обіцянок бути обережним.
Жарт №1: флаги функцій ZFS як татуювання: легко зробити, важко видалити, а ваше майбутнє «я» може сумніватися в тих рішеннях.
Модель сумісності: enabled vs active vs supported
Коли люди говорять «флаги функцій», вони часто мають на увазі «список, який я бачив у zpool get all». Цей список — початок, але не вся історія. Історія — це станова машина за кожним прапором і те, що цей стан означає для імпорту та реплікації.
Стан функції: disabled, enabled, active
З точки зору OpenZFS, флаги функцій зазвичай мають такі стани:
- disabled: пул не має увімкненої цієї функції; нічого про неї не важливо.
- enabled: пул знає про функцію і може використовувати її в майбутньому, але ще не обов’язково записував специфічні структури.
- active: пул використав функцію; на диску є структури, які вимагають підтримки для читання (і зазвичай для самого імпорту).
Не кожна функція поводиться однаково, але практичне правило: active-функції — це ті, які залишають вас на старіших хостах. Enabled, але не active функції все ще можуть створити проблему, якщо цільовий хост відмовляється від пулів з невідомими enabled-функціями, але більшість проблем сумісності виникає, коли функція стає active.
Можливості хоста: «supported» не означає «enabled»
Хост (модуль ядра + утиліти userland) підтримує набір функцій. Це не означає, що ці функції ввімкнено на кожному пулі. Це означає, що хост може імпортувати пули, які мають ці функції active.
Поширена пастка: «Ми оновили ОС, отже тепер сумісні». Ви сумісні з пулами, які потребують щонайбільше того, що підтримує ваш хост. Якщо ви імпортуєте пул на новішому хості, ви не обов’язково змінили пул. Але якщо ви виконаєте zpool upgrade або ввімкнете деякі властивості датасету (наприклад, native encryption), ви можете безповоротно зробити пул несумісним зі старішими хостами.
Читання в режимі лише для читання і міф «я не чіпатиму»
Люди намагаються врятуватися імпортом у режимі лише для читання. Це допомагає у вузьких випадках (наприклад, щоб витягти дані з пулу з невеликою пошкодженістю), але це не універсальний вихід. Якщо хост не розуміє active-функцію, він не зможе надійно розпарсити метадані пулу — навіть для читання. Несумісність функцій — це не проблема запису; це проблема «чи можу я зрозуміти, що бачу».
Правила переносимості: є лише три результати, що мають значення
Коли ви переміщаєте пули або реплікуєте між хостами, ви хочете передбачити, який із цих трьох результатів отримаєте:
Результат 1: Чистий імпорт (нудно, бажано)
Цільовий хост підтримує кожну active-функцію пулу. Пул імпортується нормально. Ви можете монтувати датасети, запускати scrub, resilver і виконувати всі звичні операції. Це єдиний результат, який вам потрібен для продукційних cutover.
Результат 2: Імпорт відхилено (гучна помилка, часто відновлювана)
Цільовий хост бачить одну або кілька неподтримуваних active-функцій і відмовляється імпортувати. Це порушує роботу, але чесно: ви не пошкодили дані потай; вас зупинили до того, як щось стало небезпечним.
На практиці це відбувається, коли ви намагаєтеся імпортувати пул, оновлений на новішому OpenZFS, у старше середовище (старше ядро дистрибутива, старіша прошивка апарату, старий rescue-образ). Виправлення зазвичай: «оновіть цільовий хост» або «не оновлюйте пул». Останнє можливо лише якщо ви зупинилися до активації функцій.
Результат 3: Імпортується, але інші операції ламаються (підступно, дорого в експлуатації)
Це рідше з флагами функцій, ніж з хаосом старих версій пулів, але все ще відбувається: потоки реплікації, завантажувачі, initramfs-інструменти або програмне забезпечення управління можуть не розуміти нові властивості або поведінку за замовчуванням навіть якщо модуль ядра може імпортувати пул.
Приклади: середовища завантаження, що припускають стару поведінку монтування, rescue-образи без підтримки криптографії для зашифрованого root, або цілі прийому реплікації, які приймають стріми, але не можуть коректно обробити великі блоки або вбудовані дані. Пул імпортується, але екосистема навколо нього стає інцидентом.
Жарт №2: Єдина річ більш постійна, ніж оновлення пулу ZFS — це запрошення на постмортем у календарі.
Цікаві факти та історичний контекст
Ось кілька фрагментів, які пояснюють, чому флаги функцій мають сенс — і чому два бокси з «ZFS» можуть поводитися як далекі родичі.
- ZFS починався в Sun і поставлявся в Solaris; початкова архітектура заклала наскрізні контрольні суми та copy-on-write задовго до того, як це стало модним у комодиті Linux сховищах.
- Номери версій пулів стали безладом, оскільки численні дистрибуції впроваджували функції у різному порядку або під конфліктними інкрементами версій, через що сумісність по версії була ненадійною між постачальниками.
- Флаги функцій були введені, щоб замінити версії пулів, щоб пул міг точно самодекларувати можливості замість одного цілого числа.
- OpenZFS уніфікував різні кодові бази (Illumos, FreeBSD, порти для Linux) навколо спільної моделі флагів функцій, але терміни релізів все ще відрізняються між платформами.
- Native encryption — це переломна функція: це не просто властивість датасету; вона змінює робочі процеси управління ключами, поведінку send/receive і припущення про відновлення після катастроф.
- Деякі функції активуються неявно — ви не завжди явно виконуєте «enable feature». Встановлення властивості (наприклад, використання спеціальних vdev-класів розподілу, large_dnode через певні інструменти) може перевести функцію в active.
- Boot-пули особливі: ядро може імпортувати пул без проблем, але завантажувач може не розуміти нові on-disk-функції. Це різна вісь сумісності, яку більшість вивчає важким шляхом.
- Потоки реплікації кодують вимоги до функцій. Навіть якщо джерельний пул імпортується скрізь, send-стрім може вимагати підтримки на боці приймача залежно від прапорів і властивостей.
- Флаги функцій мають простір імен (часто з префіксом постачальника чи проєкту історично), що було практичним компромісом для уникнення колізій під час фрагментації розробки ZFS.
Три міні-історії з корпоративного світу
Міні-історія 1: Інцидент через неправильне припущення
У них було два дата-центри і простий план: первинний працював на новішому Linux, DR — на трохи старішому «стабільному» збірці, бо «він майже нічого не робить». Реплікація була через ZFS send/receive. Коробка DR відносили як вогнегасник: час від часу оглядався, переважно ігнорувався.
Під час планового вікна обслуговування інженер оновив функції пулу на primary, щоб отримати нову можливість для продуктивності та обробки снапшотів. Зміна виглядала нешкідливо: zpool upgrade пройшов чисто, нічого не вибухнуло, графіки додатків були спокійні. Команда похлопала одне одному по спині і пішла далі.
Через два місяці вони провели тест DR і виявили, що receive на боці DR тихо падав вже кілька днів. Send-стріми тепер вимагали функцій, яких хост DR не підтримував. Моніторинг не сповіщав, бо відстежував лише наявність снапшотів, а не успішність інкрементальних receive. Коли вони нарешті спробували імпортувати реплікований пул на DR, він відмовився: неподтримувані функції. Репліка була не просто застарілою; вона була непридатною.
Відновлення було не гламурним: екстрені оновлення в DR, вирівнювання ядра та модуля ZFS, відбудова базової реплікації повним send. Це спрацювало, але коштувало вихідних і підірвало довіру. Корінь проблеми не в «ZFS складний». Корінь — неправильне припущення: що оновлення пулу — це локальна оптимізація, а не глобальна подія сумісності.
Постмортем-дія, яка насправді допомогла: вони ввели «контракт сумісності» між сайтами — задокументований мінімальний набір підтримуваних функцій, зафіксовані версії OpenZFS в обох місцях і тест, який пробує сухий запуск receive на DR перед будь-яким оновленням пулу в проді.
Міні-історія 2: Оптимізація, що відгукнулася бумерангом
Інша компанія хотіла швидші операції з метаданими для парку build-серверів. Хтось прочитав про special vdevs, класи розподілу для метаданих і нові формати вказівників блоків. Обіцянка була приваблива: «Ми прискоримо file stats і навантаження з дрібними файлами». Вони впровадили нові NVMe, створили special vdev і ввімкнули набір функцій, які «рекомендовані» новішою збіркою OpenZFS, яку вони використовували.
Продуктивність покращилася одразу. Потім почалося: цикл оновлення апаратного забезпечення перемістив деякі пули на старіші запасні хости під час технічного обслуговування. Ті запасні працювали зі старішим OpenZFS, бо ядро вендора відставало. Раптом пули з новими active-функціями не можна було імпортувати на запасних. Вікна обслуговування подовжилися, бо «просто переключитися на запасний» стало «спочатку оновити запасний, потім перебудувати initramfs, потім перезавантажити, потім молитися».
Гірше, інструменти boot environment на цьому дистрибутиві не сприймали новий набір функцій для root-пулу, і кілька машин стали важко відновлюваними. Нічого не було втрачене безповоротно, але час ремонту виріс. Оптимізація була реальна; операційні витрати також реальні, і ніхто їх не врахував у рішенні.
Що вони змінили: розділили обов’язки. Вони перестали трактувати «оновлення функцій пулу» як частину налаштування продуктивності. Вони зафіксували boot-пули на мінімальному наборі функцій, підтримуваному інструментами завантаження, і ізолювали агресивне використання функцій у дата-пулах, які не потребують завантаження в дивних rescue-середовищах. Build-сервери зберегли швидкість; on-call ротація — сон.
Міні-історія 3: Нудна, але правильна практика, що врятувала день
Ця команда мала змішані хости: частина на FreeBSD для мережевих сервісів, частина на Linux для обчислень, всі використовували ZFS-орієнтовану стратегію бекапів. Середовище не блищало, але було дисциплінованим. Щокварталу вони робили «дрес-код переносимості пулу»: експортували некритичний пул і імпортували його на резервний хост, що працював на найстарішій підтримуваній стеку ZFS у флоті.
Це здавалося рутиной, поки одного дня не окупилося. У продукційного хоста вийшла материнська плата, і найшвидший вихід — підключити диски до запасної машини. Запасна була старішою і не оновлювалася місяцями. У багатьох організаціях це було б початком поганого дня.
Натомість пул імпортувався чисто, бо команда мала правило: ніяких оновлень пулу, якщо кожен хост у матриці підтримки не може імпортувати пул, і жодна нова функція не активується без тесту переносимості. Вони також зберігали невеликий набір «відомих робочих» recovery-образів з відповідною підтримкою ZFS.
Інцидент все одно болісний — обладнання завжди бентежить — але він залишився в межах «поміняти деталь, імпортувати пул, відновити сервіс». Ніяких несподіваних флагів функцій, ніякої випадкової блокування, ніяких панічних оновлень ОС під тиском. Їхня перемога була нудною, а це найвища похвала для практики SRE.
Практичні завдання: команди, які ви справді будете виконувати
Ціль тут — надати операційну пам’ять тіла: як інспектувати флаги, прогнозувати імпорти та керувати оновленнями без перетворення їх на рулетку. Команди показані з типовими фрагментами виводу й інтерпретацією. Налаштуйте імена пулів і датасетів за потреби.
Завдання 1: Визначити версії ZFS і zpool на хості
cr0x@server:~$ zfs version
zfs-2.2.4-1
zfs-kmod-2.2.4-1
Інтерпретація: У цього хоста userland OpenZFS і модуль ядра узгоджені. Невідповідність (userland новіший за модуль) може спричиняти дивну поведінку; для планування переносимості вас цікавить підтримка функцій саме модулем ядра.
Завдання 2: Перелік пулів і перевірка здоров’я перед будь-якими діями
cr0x@server:~$ zpool list
NAME SIZE ALLOC FREE CKPOINT EXPANDSZ FRAG CAP DEDUP HEALTH ALTROOT
tank 3.62T 1.88T 1.74T - - 18% 51% 1.00x ONLINE -
Інтерпретація: Не займайтеся роботою з функціями на пулі, який деградований, робить resilver або показує помилки I/O, якщо ваша мета — не відновлення. Оновлення зазвичай не шкодять здоровим пулам, але звужують ваші шляхи відступу.
Завдання 3: Побачити, які флаги функцій існують на пулі і їх стани
cr0x@server:~$ zpool get all tank | grep '^tank feature@' | head
tank feature@async_destroy enabled local
tank feature@bookmarks enabled local
tank feature@embedded_data active local
tank feature@enabled_txg active local
tank feature@extensible_dataset active local
Інтерпретація: Будь-який рядок з active — це жорстка вимога: імпорт цього пулу вимагає хоста, що підтримує цю функцію. enabled-рядки можуть стати вимогами пізніше, коли функція активується.
Завдання 4: Показати неподтримувані функції на цьому хості (попередня перевірка імпорту)
cr0x@server:~$ zpool get -H -o value unsupported@features tank
-
Інтерпретація: Дефіс зазвичай означає «немає». Якщо ви бачите список — у вас вже невідповідність (наприклад, ви імпортували пул на хості, який може його читати, але не має деяких можливостей, що очікуються інструментами, або ви перевіряєте на частково сумісному стеку).
Завдання 5: Передбачити, що зробить zpool upgrade (ще не виконувати)
cr0x@server:~$ zpool upgrade -v
This system supports ZFS pool feature flags.
The following features are supported:
FEAT DESCRIPTION
async_destroy Destroy filesystems asynchronously.
embedded_data Blocks which compress very well are stored embedded in metadata.
encryption Dataset level encryption.
Інтерпретація: Це показує, що поточний хост підтримує, а не те, що потрібно вашому пулу. Ризик — оновити пул на хості, який підтримує більше, ніж решта вашого флоту.
Завдання 6: Перевірити, чи пул має доступні для включення функції
cr0x@server:~$ zpool status
pool: tank
state: ONLINE
status: Some supported features are not enabled on the pool. The pool can
still be used, but some features are unavailable.
action: Enable all features using 'zpool upgrade'. Once this is done,
the pool may no longer be accessible by software that does not support
the features. See zpool-features(7) for details.
config:
NAME STATE READ WRITE CKSUM
tank ONLINE 0 0 0
sda ONLINE 0 0 0
Інтерпретація: Це повідомлення від ZFS одночасно корисне і небезпечне. «Деякі підтримувані функції не ввімкнені» — це не проблема; це компроміс. Рядок action — та частина, що може залишити пул на старіших хостах.
Завдання 7: Безпечно перевірити імпортоздатність на цільовому хості (без імпорту)
cr0x@drhost:~$ sudo zpool import
pool: tank
id: 1234567890123456789
state: ONLINE
action: The pool can be imported using its name or numeric identifier.
config:
tank ONLINE
sda ONLINE
Інтерпретація: Якщо пул з’являється з нормальним повідомленням «can be imported», цільовий хост ймовірно підтримує active-функції. Якщо скаржиться на неподтримувані функції — зупиніться й виправте невідповідність версій перед cutover.
Завдання 8: Спробувати імпорт в режимі лише для читання для інспекції (коли ви обережні)
cr0x@drhost:~$ sudo zpool import -o readonly=on -N tank
cr0x@drhost:~$ zpool status tank
pool: tank
state: ONLINE
Інтерпретація: -N імпортує без монтування датасетів. Це безпечний спосіб інспектувати флаги і властивості на цільовому хості під час репетиції міграції. Це не вирішує відсутності підтримки функцій; лише зменшує шанс змінити дані під час інспекції.
Завдання 9: Підтвердити стани функцій після імпорту на цільовому
cr0x@drhost:~$ zpool get all tank | grep '^tank feature@' | grep -E 'active|enabled' | head
tank feature@async_destroy enabled local
tank feature@embedded_data active local
tank feature@extensible_dataset active local
Інтерпретація: Порівняйте цей вивід між хостами. Якщо хост може імпортувати, але показує дивності (відсутні функції у інструментах), можливо невідповідність userland/module або старий userland не може коректно відобразити всі стани.
Завдання 10: Визначити використання шифрування і стан ключів (мінне поле сумісності)
cr0x@server:~$ zfs get -r -o name,property,value -s local,received encryption,keylocation,keystatus tank | head -n 12
NAME PROPERTY VALUE SOURCE
tank encryption off default
tank/secure encryption aes-256-gcm local
tank/secure keylocation prompt local
tank/secure keystatus unavailable -
Інтерпретація: Зашифровані датасети вимагають підтримки шифрування на приймачі та робочі процеси управління ключами. Якщо DR не може завантажити ключі (або не підтримує шифрування), у вас немає DR — лише дорогий шифротекст.
Завдання 11: Протестувати receive реплікації в безпечному ізольованому датасеті
cr0x@source:~$ sudo zfs snapshot -r tank/app@replica-test
cr0x@source:~$ sudo zfs send -R tank/app@replica-test | ssh drhost sudo zfs receive -uF tank/replica-sandbox
Інтерпретація: Це практичний тест сумісності: якщо receive падає із помилками, пов’язаними з функціями, ви виявите це зараз, а не під час відмови. -u запобігає автоматичному монтуванню; -F примусово відкочує на цільовому шляху, якщо потрібно (використовуйте обережно).
Завдання 12: Дослідити, чому receive зазнав невдачі (шукати вимоги функцій)
cr0x@drhost:~$ sudo zfs receive -uF tank/replica-sandbox < /tmp/stream.zfs
cannot receive: stream has unsupported feature(s)
Інтерпретація: Стрім вимагає того, що ціль не може виконати. Це може бути нова функція в send-стрімі або властивість, що потребує флагу. Виправлення зазвичай: «оновити OpenZFS на цілі» або «змінити режим/властивості реплікації, щоб уникнути цієї вимоги», залежно від вмісту стріму.
Завдання 13: Заморозити переносимість пулу, відмовившись від оновлення функцій (політика, не техніка)
cr0x@server:~$ sudo zpool status tank | sed -n '1,12p'
pool: tank
state: ONLINE
status: Some supported features are not enabled on the pool. The pool can
still be used, but some features are unavailable.
Інтерпретація: «Нудний» крок — лишити все як є. Якщо вам потрібно підтримувати старі rescue-хости або крос-платформні імпорти, неоновлення функцій — це свідомий вибір сумісності.
Завдання 14: Виконати контрольоване оновлення функцій пулу (коли ви заслужили)
cr0x@server:~$ sudo zpool upgrade tank
This system supports ZFS pool feature flags.
Successfully upgraded 'tank'.
Інтерпретація: Це вмикає всі функції, які підтримує цей хост. Вони можуть не активуватися негайно, але ви змінили декларацію можливостей пулу. Ставтеся до цього як до дверей в один бік для переносимості на старіші хости.
Завдання 15: Перевірити обмеження boot-пула (щоб не зіпсувати завантаження)
cr0x@server:~$ zpool list -o name,size,health,altroot
NAME SIZE HEALTH ALTROOT
rpool 238G ONLINE -
tank 3.62T ONLINE -
Інтерпретація: Якщо rpool — ваш boot-пул, будьте консервативні. Дані-пул, що залишився на старих хостах — це неприємно; boot-пул, відрізаний від завантажувача — катастрофа у дуже конкретному, часозатратному сенсі.
Завдання 16: Експортувати пул чисто перед переміщенням дисків між хостами
cr0x@server:~$ sudo zpool export tank
cr0x@server:~$ zpool list
no pools available
Інтерпретація: Чистий export зменшує тертя при імпорті і уникає плутанини «пул у використанні». Це не змінює флаги функцій, але запобігає старим кешованим станам хоста і робить наступний імпорт чистішим.
Швидкий план діагностики
Це «у мене десять хвилин до того, як зустріч переросте в інцидент» план. Мета — з’ясувати, чи маєте ви справу з несумісністю функцій, розбіжністю версій або з проблемою продуктивності, що виглядає як несумісність.
Крок 1: Це жорстка відмова сумісності чи загальний провал імпорту?
cr0x@target:~$ sudo zpool import
pool: tank
id: 1234567890123456789
state: UNAVAIL
status: The pool uses the following feature(s) not supported by this system:
com.datto:encryption
action: The pool cannot be imported. Access the pool on a system that supports
the required feature(s), or restore the pool from backup.
Інтерпретація: Якщо ви бачите явне «feature(s) not supported», припиніть налагоджувати диски і почніть налагоджувати версії. Це не I/O проблема; це розбіжність можливостей софту.
Крок 2: Підтвердити, що підтримує цільовий хост
cr0x@target:~$ zfs version
zfs-2.1.11
zfs-kmod-2.1.11
Інтерпретація: Якщо джерело на 2.2.x, а ціль на 2.1.x, очікуйте можливих невідповідностей. Узгодьте версії навмисно; не сподівайтеся, що перетин множин виходить випадково.
Крок 3: Якщо імпорт відбувається, але продуктивність жахлива, перевірте навантаження пулу
cr0x@target:~$ zpool iostat -v tank 1 5
capacity operations bandwidth
pool alloc free read write read write
---------- ----- ----- ----- ----- ----- -----
tank 1.88T 1.74T 120 980 8.2M 112M
sda - - 60 490 4.1M 56M
sdb - - 60 490 4.1M 56M
Інтерпретація: Якщо ви обмежені пропускною здатністю або IOPS під час імпорту/receive/scrub, ви можете помилково приписувати «зависання» сумісності. Несумісність функцій провалюється швидко і гучно; проблеми продуктивності — повільно і неоднозначно.
Крок 4: Перевірити, чи resilver або scrub не займає систему
cr0x@target:~$ zpool status tank | sed -n '1,25p'
pool: tank
state: ONLINE
scan: resilver in progress since Tue Dec 24 22:10:01 2025
312G scanned at 1.20G/s, 58.4G issued at 230M/s, 312G total
58.4G resilvered, 18.72% done, 0 days 00:18:22 to go
Інтерпретація: Resilver може зробити receives і імпорти «відчутно» зіпсувавшимися. Це не флаги функцій; це фізика. Якщо потрібна швидкість — відкладіть receives або обмежте інші навантаження.
Крок 5: Якщо реплікація падає, відтворіть з маленьким стрімом
cr0x@source:~$ sudo zfs create -o mountpoint=none tank/_compat_test
cr0x@source:~$ sudo zfs snapshot tank/_compat_test@x
cr0x@source:~$ sudo zfs send tank/_compat_test@x | ssh target sudo zfs receive -u tank/_compat_rx
Інтерпретація: Мінімальний стрім допомагає ізолювати, чи помилка стосується властивостей/функцій датасету, чи конвеєра (ssh, буферизація, квоти, місце на приймачі).
Поширені помилки, симптоми та виправлення
Помилка 1: Оновлення пулу на одному хості і припущення, що решта впорається
Симптом: DR-хост відмовляється імпортувати з «unsupported feature(s)» або receive реплікації починають падати після, здавалося б, не пов’язаного обслуговування.
Виправлення: Вирівняйте версії OpenZFS на всіх хостах, які можуть імпортувати пул. Якщо це неможливо, не виконувати zpool upgrade на цьому пулі. Трактуйте оновлення пулів як зміну для всього флоту.
Помилка 2: Трактування boot-пулів як data-пули
Симптом: Система імпортує пул у rescue-середовищі, але не завантажується нормально; або завантажується нестабільно після ввімкнення нових функцій.
Виправлення: Тримайте boot-пули на консервативному наборі функцій. Перевіряйте підтримку завантажувача перед ввімкненням функцій. Тестуйте реальні перезавантаження, а не тільки імпорти.
Помилка 3: Плутанина «enabled» проти «active» щодо переносимості
Симптом: Пул імпортувався на старішому хості минулого місяця, а тепер відмовляється після зміни властивості або нового навантаження.
Виправлення: Відстежуйте, які функції можуть стати active через операційні зміни. Коли ви вмикаєте властивість, що залежить від функції, вважайте, що вона може активуватися негайно і змінити переносимість.
Помилка 4: Реплікація без тестування receives на найстарішому таргеті
Симптом: Інкрементальна реплікація починає падати, але моніторинг лише перевіряє наявність снапшотів або коди виходу send завалюються непоміченими.
Виправлення: Впровадьте явну перевірку receive і оповіщення про ненульові коди виходу. Періодично виконуйте невеликий end-to-end send/receive тест сумісності.
Помилка 5: Думка, що імпорт у режимі тільки для читання вирішує unsupported feature flags
Симптом: Ви пробуєте -o readonly=on і все одно не можете імпортувати; фрустрація зростає.
Виправлення: Якщо хост не підтримує active-функцію, потрібен хост, що її підтримує. Read-only змінює лише поведінку запису, а не розуміння метаданих.
Помилка 6: Невідповідність userland і модуля ядра
Симптом: Дивні звіти про функції, відсутні властивості або інструменти поводяться по-різному на хостах з «однаковими версіями» пакетів.
Виправлення: Перевірте, що zfs version показує узгоджені userland і модуль. На Linux переконайтеся, що DKMS/kmod і пакети userland співпадають. Перегенеруйте initramfs після оновлень, якщо потрібно.
Помилка 7: Імпорт пулів з випадкових rescue-образів
Симптом: Пул не імпортується під час відновлення, але нормально імпортується на продукційному хості.
Виправлення: Підтримуйте відомо робоче recovery-середовище, яке відповідає вашому production ZFS feature set. Тестуйте його щокварталу. Розглядайте recovery-інструменти як частину системи.
Контрольні списки / покроковий план
Контрольний список A: Перед увімкненням нових функцій або запуском zpool upgrade
- Зробіть інвентаризацію кожного хоста, який може знадобитися для імпорту пулу (прод, DR, стендбай, бекапи, rescue-образи).
- Запишіть версії OpenZFS на кожному хості через
zfs version. - На пулі перелічіть active-функції:
zpool get all POOL | grep '^POOL feature@' | grep active. - На кожному цільовому хості запустіть
zpool import(коли диски видимі), щоб підтвердити, що він принаймні бачить пул і не скаржиться на функції. - Запустіть send/receive тест у пісочниці на найстарішому хості матриці.
- Для boot-пулів перевірте шлях перезавантаження: завантажувач, initramfs, завантаження ключів (якщо зашифровано) і процедуру відкату.
- Тільки після цього вирішуйте, чи варто нова функція звужувати переносимість.
Контрольний список B: Міграція між хостами (export/import) без сюрпризів
- На джерелі: підтвердьте здоров’я пулу (
zpool status), статус scrub і лічильники помилок. - На джерелі: зробіть знімок властивостей пулу для запису:
zpool get all POOL | grep feature@zfs get -r all POOL > /var/tmp/pool-properties.txt(уважайте на чутливу інформацію)
- Чисто експортуйте:
zpool export POOL. - На цілі: перевірте версії; переконайтеся, що модуль ядра завантажено.
- На цілі: запустіть
zpool import, щоб перевірити скарги на функції. - Імпортуйте з
-Nдля інспекції, потім змонтуйте свідомо.
Контрольний список C: Сумісність реплікації між версіями
- Визначте найстарішу версію отримувача, яку потрібно підтримувати.
- Тестуйте receives з мінімальним датасетом (Завдання 11 у плані).
- Для зашифрованих датасетів перевірте робочі процеси завантаження ключів на приймачі, перш ніж вважати його «реплікою».
- Оповіщайте про помилки receive явно; не робіть висновків про здоров’я реплікації лише по наявності снапшотів.
- Після оновлення функцій пулу негайно повторіть тести реплікації.
Часті запитання
1) Якщо я оновлю OpenZFS на хості, чи це оновить мої пули?
Ні. Оновлення софту збільшує те, що хост може підтримувати. Ваші пули зберігають поточні стани функцій, поки ви явно не ввімкнете функції (через zpool upgrade) або не активуєте їх неявно (через властивості/навантаження, що їх потребують).
2) Чи зворотне zpool upgrade?
Практично — ні. Іноді можна «уникнути активації» певних функцій, якщо ви їх не використовуєте, але як тільки функція стала active і пул записав структури, що її вимагають, ви не можете відкотити пул до сумісності зі старішими хостами.
3) У чому різниця між «enabled» і «active» щодо переносимості?
Active означає, що пул використовує функцію, і старі хости, що її не підтримують, відмовляться імпортувати. Enabled означає, що пул може використовувати її пізніше. Enabled-функції можуть мати значення, але active-функції — це зазвичай жорстка стіна.
4) Чи можу я імпортувати пул на старішому хості, якщо обіцяю не монтувати або не писати в нього?
Якщо хост не підтримує active-функцію, він зазвичай взагалі не може імпортувати пул — ні для читання, ні для запису — бо не може інтерпретувати необхідні метадані безпечно.
5) Чому реплікація почала падати після місяців роботи?
Або джерельний пул активував функцію (можливо через зміну властивості), або send-стрім тепер містить вимоги, яких приймач не може задовольнити. Інша поширена причина — приймач був ненавмисно оновлений/понижений і втратив підтримку або узгодженість інструментів.
6) Чи змінюють правила крос-платформні ZFS (Linux ↔ FreeBSD)?
Основна логіка флагів функцій однакова, але терміни випусків різні. Функція, яка поширена на одній платформі, може відставати на іншій. Трактуйте «різницю платформ» як «різницю версій» і тестуйте імпорти та receives на точних білдах, які ви використовуєте.
7) Чи завжди слід виконувати zpool upgrade, щоб позбутися попередження статусу?
Ні. Це попередження інформаційне, а не тривога надійності. Залишити пул не оновленим — дійсна стратегія, коли переносимість важлива — особливо для знімних пулів, DR-імпортів або середовищ з різнорідними хостами.
8) Як спроєктувати безпечну політику сумісності для флоту?
Виберіть мінімальну версію OpenZFS, яку має виконувати кожен релевантний хост. Увімкнуйте функції пулу лише ті, які підтримує ця мінімальна версія. Коли потрібна нова функція, ставте її як міграцію схеми: спочатку оновіть хости, потім — пули, і на кожному кроці тестуйте DR/реплікацію.
9) А зашифровані датасети — чи сумісні вони з send/receive скрізь?
Шифрування додає додаткові вимоги: приймач має підтримувати функцію шифрування, і режим реплікації має узгоджуватися з вашою політикою управління ключами. Навіть коли пул імпортується, операційна придатність залежить від того, чи можна завантажити ключі і як ви керуєте keylocation та keystatus у випадку DR.
10) Яка найбезпечніша звичка щодо флагів функцій?
Припустіть, що будь-яке оновлення функцій пулу — це пониження переносимості. Якщо ви готові на такий компроміс, діяти свідомо; якщо ні — не дозволяйте статусному повідомленню соромити вас натиснути кнопку.
Висновок
Флаги функцій ZFS — це не дрібниці; це контракт вашого пулу з кожною машиною, яка може знадобитися зчитати його під тиском. Вони роблять сумісність явнішою, ніж стара система версій пулу, але також роблять оновлення більш вагомими: ви не можете випадково залишитися переносимими після переходу порогу функції.
Якщо ви запам’ятаєте лише одне, запам’ятайте це: оновлюйте хости спочатку, перевіряйте імпорти й receives на найстарішому середовищі, і оновлюйте пули останніми. Команди, які так роблять, виглядають нудними під час перевірки змін. Вони також виглядають блискуче в день, коли запасний бокс стає продукційним.