Є два види міграцій: ті, що ви плануєте, і ті, які ваше сховище змушує виконувати о 2-й ночі після «невеликого» оновлення прошивки. Якщо ви використовуєте дзеркальні ZFS-пули, zpool split — один із небагатьох інструментів, який може перетворити міграцію на контрольовану, здебільшого нудну операцію: ви буквально від’єднуєте одну сторону ваших дзеркал і забираєте з собою другий пул.
Це не маркетингові казки про «миттєвий клон». Розділення пулу — це серйозний крок: ви змінюєте рівень надмірності, створюєте другу ідентичність для сховища і даєте обіцянки собі в майбутньому щодо імпорту, точок монтування, ключів шифрування та стану останньої групи транзакцій (TXG) у момент від’єднання. Якщо зроблено правильно — чисте посівне DR або швидкий старт міграції. Якщо робити недбало — квиток у світ «чому у продакшна змонтувалася копія DR і почала писати?».
Що насправді робить zpool split (і чого не робить)
zpool split бере пул, який містить дзеркальні vdev-и, і створює новий пул, розділяючи члени дзеркал. Концептуально: кожен дзеркальний vdev — це пара (або більше) дисків; split дозволяє відокремити один диск з кожного дзеркала, щоб сформувати новий пул з тією ж структурою датасетів і метаданими. Це не копіювання блоків; це переназначення власності на існуючі диски.
Ось чому це швидко. Це також пояснює перше правило split: ви отримаєте «повний пул» лише якщо у вас є достатньо дзеркал, щоб віддати по одному члену з кожного топ-рівня vdev-а. Якщо ваш пул — це одне дзеркало з двох дисків, split все ще може створити новий пул — але ви фактично перетворюєте один диск у пул з однорідним топ-рівнем. Це може бути прийнятним для тимчасового етапу міграції, і може бути неприйнятним, якщо ви плануєте поруч із ним спати.
Для чого це добре
- Підготовка до міграції: Split, відправити диски (або перемістити в новий шасі), імпортувати — і ви перенесли ідентичність пулу без мережевого перенесення.
- Створення «seed» для DR: Split для швидкого створення початкового DR-пулу, потім використовувати інкрементальні
zfs sendдля підтримки його в актуальному стані. - Швидке дублювання оточення: Клонувати дерево датасетів продукції для одноразової аналітики, потім видалити split-пул після завершення.
Чого це не є
- Не резервне копіювання. Якщо ваші дані пошкоджені, на щастя, ви отримаєте дві копії корупції.
- Не механізм знімків. Split-пул відображає стан пулу на межі TXG у момент split, а не знімок датасету, який ви можете оглядати.
- Не заміна стратегії реплікації. Це інструмент у наборі інструментів, а не весь набір інструментів.
Жарт №1: Розділення дзеркального пулу — це як сфотокопіювати ключ від дому, розпиляючи його навпіл — у вас дійсно буде два ключі, але ваш замок може мати власну думку.
Факти & історичний контекст (чому ця опція з’явилася)
ZFS має довгу пам’ять, як і інженери, що будували навколо нього операційні робочі процеси. Ось кілька фактів і контексту, які пояснюють, чому zpool split існує і як він опинився в реальних рукбуках:
- ZFS було побудовано навколо пуліного сховища, а не пристроїв на файлову систему. Тому операції на зразок split діють на топологію пулу, а не на «файлову систему», як старі інструменти.
- Дзеркала завжди були «операційно дружні» vdev-и. У продакшні дзеркала популярні, бо вони швидко відновлюються, деградують передбачувано і толерують змішану заміну дисків краще за паритетні vdev-и.
- Формат на диску портативний між системами з однаковими feature flags. Імпорт пулу на іншому хості нормальний, але тільки якщо feature flags сумісні і ОС їх підтримує.
- Split — це трансформація топології, а не переміщення даних. Ось чому це миттєво у порівнянні з
zfs send, і тому це негайно змінює вашу надмірність. - Історично «sneakernet» міграції були звичними. До повсюдного доступу до дешевих 10/25/40/100GbE (і до того, як їм довіряли на 95% завантаженості на 12 годин), фізичне переміщення дисків було легітимним шляхом міграції.
- Контрольні суми ZFS зробили «перенести диски» безпечнішим, ніж старі ФС. При імпорті на іншому боці ви маєте перевірку від кінця до кінця через scrub і контрольні суми блоків.
- GUID пулів і шляхи пристроїв свідомо абстраговані. ZFS відслідковує GUID vdev-ів; імена пристроїв ОС можуть змінюватися й пул все одно імпортується — якщо ви спочатку використовували стабільні шляхи by-id.
- Feature flags перетворили «імпортується скрізь» у «імпортується там, де має бути». Увімкнення нових фіч може блокувати імпорт на старіших платформах; split цього не змінює, але змушує зіштовхнутися з цим питанням.
- Boot-environments і root-on-ZFS зробили split цікавішим. Розділення пулу, що містить ОС, можливе, але ви опиняєтесь у сфері сумісності завантажувача й host ID.
Коли використовувати split проти send/receive або реплікації
Якщо у вас дзеркальний пул і фізичний доступ до дисків, split — найшвидший спосіб створити другий пул з тією ж деревовою структурою датасетів. Але «швидко» ≠ «краще». Ось як я приймаю рішення.
Використовуйте zpool split, коли
- У вас дзеркальні vdev-и і ви можете тимчасово пожертвувати однією стороною.
- Вам потрібний швидкий seed для DR і вікно мережевої реплікації неприйнятне.
- Ви хочете мігрувати великий пул на нове обладнання без насичення лінків на дні.
- Ви можете терпіти тимчасове зниження надмірності на джерелі (після split джерело матиме менше членів дзеркала).
Віддавайте перевагу zfs send | zfs receive, коли
- Вам потрібна семантика по точці в часі: знімки, інкременти, опції відкату.
- Ви не можете тимчасово знижувати надмірність у продакшні.
- Ваші vdev-и не дзеркала (RAIDZ не можна так розділити).
- Вам потрібно трансформувати властивості під час міграції (recordsize, encryption, макет датасетів) і бажаєте контроль.
Віддавайте перевагу повній реплікації, коли
- Вам потрібен безперервний, аудований DR з цілями RPO та RTO.
- Потрібно зберігати історичні точки (політики утримання знімків).
- У вас кілька кінцевих цілей або необхідно реплікувати через межі довіри.
Жарт №2: Найшвидший спосіб передачі даних досі людина, що несе диски — поки хтось не покладе їх у рюкзак з магнітом, і тепер ви винайшли перформанс-арт.
Передпольотна перевірка: що підтвердити перед split
Розділити пул просто. Розділити пул і бути впевненим у тому, що станеться далі — от тут дорослі заробляють свою каву.
Підтвердіть топологію: тільки дзеркала
Вам потрібні дзеркальні vdev-и. Якщо у вашому пулі є RAIDZ vdev-и, zpool split не зробить те, що вам треба. Змішані топології поширені в середовищах «ми ростили це з часом» — підтвердіть, що у вас реально є.
Підтвердіть feature flags і підтримку цільової ОС
Якщо ви робите split на хості з новішими фічами ZFS, а потім намагаєтесь імпортувати на старіший пристрій, імпорт може відмовитись. Це найпоширеніша причина «в лабораторії працювало» провалів у корпоративних міграціях.
Підтвердіть роботу з ключами шифрування
Нативне шифрування ZFS (на рівні датасету) переміщується разом з даними на диску. Split-пул міститиме зашифровані датасети; імпорт ≠ монтування. Переконайтесь, що цільовий хост має доступ до ключів і ви знаєте, чи ключі завантажуються автоматично чи вручну.
Підтвердіть наявність стабільних ідентифікаторів пристроїв
У Linux /dev/sdX — радше підказка, ніж контракт. Використовуйте /dev/disk/by-id для логіки. На приймачі пристрої будуть перелічуватись інакше; ZFS зазвичай їх знаходить, але ваш час на відлагодження зростає, якщо ви не можете зіставити «цей серійний номер» з «цим членом vdev».
Плануйте стратегічно точки монтування
Після split та імпорту датасети можуть автомонтуватись. Це нормально, поки вони не змонтуються на неправильному хості з неправильними шляхами, і раптом у вас два сервери пишуть у різні копії, думаючи, що вони авторитарні. Заплануйте mountpoint та політику canmount перед імпортом.
Практичні завдання: команди і як читати вивід
Нижчеподані завдання написані так, ніби ви на Linux-хості з OpenZFS. Налаштуйте імена сервісів і шляхи під вашу платформу. Кожне завдання — те, що я або запускав у боротьбі з проблемою, або бажав запустити перед тим, як Pager представився.
Завдання 1: Інвентаризація пулу і підтвердження дзеркал
cr0x@server:~$ sudo zpool status -v tank
pool: tank
state: ONLINE
config:
NAME STATE READ WRITE CKSUM
tank ONLINE 0 0 0
mirror-0 ONLINE 0 0 0
ata-SAMSUNG_SSD_1TB_AAA ONLINE 0 0 0
ata-SAMSUNG_SSD_1TB_BBB ONLINE 0 0 0
mirror-1 ONLINE 0 0 0
ata-SAMSUNG_SSD_1TB_CCC ONLINE 0 0 0
ata-SAMSUNG_SSD_1TB_DDD ONLINE 0 0 0
errors: No known data errors
Інтерпретація: Ви хочете, щоб кожен топ-рівневий vdev мав позначку mirror-N. Якщо ви бачите raidz або одиночні диски, split буде частковим або неможливим. Також перевірте наявність помилок; розділення деградованого дзеркала створює новий пул, який може бути «народжений хворим».
Завдання 2: Перевірте поточне навантаження вводу/виводу перед будь-якими руйнівними діями
cr0x@server:~$ iostat -x 2 3
Linux 6.8.0 (server) 12/25/2025 _x86_64_ (32 CPU)
avg-cpu: %user %nice %system %iowait %steal %idle
6.12 0.00 1.88 0.74 0.00 91.26
Device r/s w/s rkB/s wkB/s await svctm %util
nvme0n1 5.0 40.0 640.0 5120.0 2.10 0.15 0.70
Інтерпретація: Split швидкий, але операційний ризик походить від дій навколо нього (scrub, export, import). Якщо пул вже насичений (%util близько 100% і високий await), заплануйте більш спокійне вікно.
Завдання 3: Перевірте feature flags і сумісність
cr0x@server:~$ sudo zpool get all tank | egrep 'feature@|compatibility|version'
tank compatibility - default
tank feature@async_destroy enabled local
tank feature@bookmarks enabled local
tank feature@encryption enabled local
tank feature@edonr enabled local
Інтерпретація: Split-пул буде нести ці фічі. Якщо цільовий хост їх не підтримує, імпорт може не вдатись. Розглядайте «feature enabled» як жорстку вимогу для цільового стеку.
Завдання 4: Зафіксуйте список датасетів і критичні властивості (mountpoints, canmount)
cr0x@server:~$ sudo zfs list -r -o name,used,avail,mountpoint,canmount,encryption,keylocation tank
NAME USED AVAIL MOUNTPOINT CANMOUNT ENCRYPTION KEYLOCATION
tank 220G 700G /tank on off -
tank/apps 80G 700G /tank/apps on aes-256-gcm file:///root/keys/apps.key
tank/home 40G 700G /tank/home on off -
tank/vm 100G 700G /tank/vm on aes-256-gcm prompt
Інтерпретація: Це ваша «що змонтується де» карта. На DR-хості ви можете захотіти canmount=off, поки не будете готові. Також зверніть увагу на keylocation і чи ключі у файлі або вимагають введення.
Завдання 5: Створіть набір «страхових» знімків (опціонально, але зазвичай розумно)
cr0x@server:~$ sudo zfs snapshot -r tank@pre-split-2025-12-25
cr0x@server:~$ sudo zfs list -t snapshot -r tank | tail -5
tank/apps@pre-split-2025-12-25 0B -
tank/home@pre-split-2025-12-25 0B -
tank/vm@pre-split-2025-12-25 0B -
Інтерпретація: Split не вимагає знімків, але вони дають вам можливість відкату і варіанти send/receive, якщо план «перенести диски» піде не так. Це дешева страховка.
Завдання 6: Заглушіть ризикових записувачів (бази даних, образи VM) і перевірте
cr0x@server:~$ sudo systemctl stop postgresql
cr0x@server:~$ sudo systemctl stop libvirtd
cr0x@server:~$ sudo lsof +D /tank/vm | head
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
Інтерпретація: Для міграції/seed DR вам потрібна мінімум crash-consistent; для баз даних бажано application-consistent, якщо можливо. Якщо lsof ще показує зайняті файли під критичними датасетами — ви не заглушили їх.
Завдання 7: Швидка перевірка здоров’я і розгляд розкладу scrub
cr0x@server:~$ sudo zpool status tank
pool: tank
state: ONLINE
scan: scrub repaired 0B in 00:21:33 with 0 errors on Sun Dec 22 02:14:01 2025
config:
...
errors: No known data errors
Інтерпретація: Якщо останній scrub старий або є помилки — вирішіть це спочатку. Split не найкращий час, щоб виявити, що один член дзеркала тихо викидає помилки контрольних сум.
Завдання 8: Виконайте split для створення нового імені пулу
cr0x@server:~$ sudo zpool split tank tank_dr
cr0x@server:~$ sudo zpool status -v tank
pool: tank
state: ONLINE
config:
NAME STATE READ WRITE CKSUM
tank ONLINE 0 0 0
mirror-0 ONLINE 0 0 0
ata-SAMSUNG_SSD_1TB_AAA ONLINE 0 0 0
mirror-1 ONLINE 0 0 0
ata-SAMSUNG_SSD_1TB_CCC ONLINE 0 0 0
errors: No known data errors
cr0x@server:~$ sudo zpool status -v tank_dr
pool: tank_dr
state: ONLINE
config:
NAME STATE READ WRITE CKSUM
tank_dr ONLINE 0 0 0
ata-SAMSUNG_SSD_1TB_BBB ONLINE 0 0 0
ata-SAMSUNG_SSD_1TB_DDD ONLINE 0 0 0
errors: No known data errors
Інтерпретація: На багатьох налаштуваннях новий пул створюється з «іншої сторони» кожного дзеркала. Зверніть увагу, що tank_dr тут позначений як однорівневі диски (не дзеркала), бо кожне дзеркало віддало по диску. Люди забувають про це: ви часто обмінюєте надмірність на портативність. Якщо ви хочете, щоб split-пул теж був дзеркальним, потрібні додаткові диски для приєднання на приймачі.
Завдання 9: Негайно змініть політику автомонту на split-пулі (рекомендовано)
cr0x@server:~$ sudo zfs set canmount=off tank_dr
cr0x@server:~$ sudo zfs set mountpoint=/tank_dr tank_dr
cr0x@server:~$ sudo zfs list -o name,mountpoint,canmount tank_dr
NAME MOUNTPOINT CANMOUNT
tank_dr /tank_dr off
Інтерпретація: Це запобігає випадковим монтуванням на вихідному хості (або на цільовому хості, що імпортує автоматично). Ви зможете пізніше ввімкнути монтування для окремих датасетів.
Завдання 10: Експортуйте split-пул для фізичного пересування
cr0x@server:~$ sudo zpool export tank_dr
cr0x@server:~$ sudo zpool list
NAME SIZE ALLOC FREE CKPOINT EXPANDSZ FRAG CAP DEDUP HEALTH ALTROOT
tank 1.81T 220G 1.60T - - 3% 11% 1.00x ONLINE -
Інтерпретація: Експортуйте чисто, щоб імпорт на призначенні не виглядав як «вкрадений пул» з ще живого хоста. Це зменшує тертя при імпорті і запобігає випадковим конфліктам мультиімпорту.
Завдання 11: На цільовому хості знайдіть диски за стабільним ID і імпортуйте спочатку у режимі read-only
cr0x@drhost:~$ sudo ls -l /dev/disk/by-id/ | egrep 'SAMSUNG_SSD_1TB_(BBB|DDD)'
lrwxrwxrwx 1 root root 9 Dec 25 09:02 ata-SAMSUNG_SSD_1TB_BBB -> ../../sdb
lrwxrwxrwx 1 root root 9 Dec 25 09:02 ata-SAMSUNG_SSD_1TB_DDD -> ../../sdc
cr0x@drhost:~$ sudo zpool import
pool: tank_dr
id: 15277416958755799222
state: ONLINE
action: The pool can be imported using its name or numeric identifier.
config:
tank_dr ONLINE
ata-SAMSUNG_SSD_1TB_BBB ONLINE
ata-SAMSUNG_SSD_1TB_DDD ONLINE
cr0x@drhost:~$ sudo zpool import -o readonly=on -o cachefile=none tank_dr
cr0x@drhost:~$ sudo zpool get readonly tank_dr
NAME PROPERTY VALUE SOURCE
tank_dr readonly on local
Інтерпретація: Read-only імпорт — відмінна початкова точка. Це дозволяє оглянути датасети, перевірити структуру і підтвердити, що ви не привезли не ті диски — без змін на диску.
Завдання 12: Завантажте ключі шифрування і монтуйте вибірково
cr0x@drhost:~$ sudo zfs load-key -r tank_dr/apps
Enter passphrase for 'tank_dr/apps':
cr0x@drhost:~$ sudo zfs mount -a
cannot mount 'tank_dr': legacy mountpoint, use mount(8)
cr0x@drhost:~$ sudo zfs get -o name,property,value tank_dr | egrep 'mountpoint|canmount'
tank_dr mountpoint /tank_dr
tank_dr canmount off
Інтерпретація: Якщо ви встановили canmount=off, масове монтування не змонтує верхній датасет. Це навмисно. Монтуйте конкретні піддатасети, які вам потрібні, після завантаження ключів і перевірки колізій шляхів монтування з локальними шляхами.
Завдання 13: Перетворіть split-пул назад у дзеркала на приймачі (під’єднайте нові диски)
cr0x@drhost:~$ sudo zpool status tank_dr
pool: tank_dr
state: ONLINE
config:
NAME STATE READ WRITE CKSUM
tank_dr ONLINE 0 0 0
ata-SAMSUNG_SSD_1TB_BBB ONLINE 0 0 0
ata-SAMSUNG_SSD_1TB_DDD ONLINE 0 0 0
errors: No known data errors
cr0x@drhost:~$ sudo zpool attach tank_dr ata-SAMSUNG_SSD_1TB_BBB /dev/disk/by-id/ata-SAMSUNG_SSD_1TB_EEE
cr0x@drhost:~$ sudo zpool attach tank_dr ata-SAMSUNG_SSD_1TB_DDD /dev/disk/by-id/ata-SAMSUNG_SSD_1TB_FFF
cr0x@drhost:~$ sudo zpool status tank_dr
pool: tank_dr
state: ONLINE
scan: resilver in progress since Thu Dec 25 09:24:11 2025
52.1G scanned at 1.20G/s, 12.4G issued at 290M/s, 220G total
12.4G resilvered, 5.64% done, 00:12:31 to go
config:
NAME STATE READ WRITE CKSUM
tank_dr ONLINE 0 0 0
mirror-0 ONLINE 0 0 0
ata-SAMSUNG_SSD_1TB_BBB ONLINE 0 0 0
ata-SAMSUNG_SSD_1TB_EEE ONLINE 0 0 0
mirror-1 ONLINE 0 0 0
ata-SAMSUNG_SSD_1TB_DDD ONLINE 0 0 0
ata-SAMSUNG_SSD_1TB_FFF ONLINE 0 0 0
Інтерпретація: Ось як ви відновлюєте надмірність після відправки single-disk-per-vdev split-пулу. Швидкість resilver залежить від ashift, recordsize, поведінки дисків і навантаження. Плануйте час відповідно.
Завдання 14: Зробіть пул записуваним і встановіть cachefile для персистентності
cr0x@drhost:~$ sudo zpool export tank_dr
cr0x@drhost:~$ sudo zpool import -o readonly=off tank_dr
cr0x@drhost:~$ sudo zpool set cachefile=/etc/zfs/zpool.cache tank_dr
cr0x@drhost:~$ sudo zpool get cachefile tank_dr
NAME PROPERTY VALUE SOURCE
tank_dr cachefile /etc/zfs/zpool.cache local
Інтерпретація: Read-only імпорт був для валідації; тепер переходите до нормальної роботи. Встановлення cachefile гарантує, що пул запам’ятають після перезавантажень (залежить від платформи).
Завдання 15: Перевірте цілісність даних scrub-ом після імпорту
cr0x@drhost:~$ sudo zpool scrub tank_dr
cr0x@drhost:~$ sudo zpool status tank_dr
pool: tank_dr
state: ONLINE
scan: scrub in progress since Thu Dec 25 10:02:18 2025
88.3G scanned at 1.10G/s, 88.3G issued at 1.10G/s, 220G total
0B repaired, 40.15% done, 00:01:52 to go
config:
...
errors: No known data errors
Інтерпретація: Scrub після переміщення — дорослий крок. Він виявляє проблеми транспортування, погані кабелі, маргінальні HBA і «той диск, що відмовляє лише на холоді».
Чеклісти / покроковий план
Чекліст A: Seed для DR через split (мінімальний простій, мінімум сюрпризів)
- Підтвердіть, що пул складається лише з дзеркал:
zpool status. - Переконайтесь, що останній scrub чистий і досить недавній для вашого ризикового апетиту.
- Занотуйте властивості датасетів: mountpoints, canmount, статус шифрування.
- Створіть рекурсивні знімки як резерв і для майбутніх інкрементальних копій.
- Заглушіть високонавантажені додатки, якщо потрібно забезпечити консистентність додатка.
- Запустіть
zpool splitдля створенняtank_dr. - Встановіть
canmount=offта/або скоригуйте mountpoints наtank_dr, щоб уникнути випадкових монтувань. - Експортуйте
tank_dr. - Перемістіть диски, імпортуйте в режимі read-only на призначенні, підтвердьте датасети і властивості.
- Завантажте ключі шифрування і монтуйте вибірково.
- Додайте нові диски і приєднайте їх для відновлення дзеркал, дочекайтесь завершення resilver.
- Скрубіть, потім переведіть у режим реплікації (інкрементальні send) для підтримки актуальності.
Чекліст B: Міграція на новий хост (збереження імен сервісів і шляхів)
- Визначте момент, коли призначення стане авторитарним: коли воно стане записуваним?
- Перед split: встановіть
canmount=offна критичних датасетах, якщо хочете мануального монтування після імпорту. - Split та експортуйте новий пул.
- На новому хості: імпортуйте з
-o altroot=/mntдля огляду, якщо хочете нульовий ризик монтажу в виробничі шляхи. - Перевірте:
zfs list,zpool status, чи завантажуються ключі шифрування. - Коли готові: експортуйте/імпортуйте нормально, встановіть правильні mountpoints, вмикайте монтування.
- Запустіть сервіси і перевірте стан на рівні додатків.
Три корпоративні міні-історії (помилки і та, що врятувала ситуацію)
1) Інцидент через неправильне припущення: «Split-пул — це бекап»
У компанії середнього розміру з потужно дзеркальним ZFS-бекендом команда створила seed DR, розділивши продукційний пул і відправивши диски на другий майданчик. Вони зробили механіку правильно: split, export, import, mount. Вони відчували себе добре. Занадто добре.
Через два місяці розробник запустив міграцію схеми, яка видалила набір таблиць у спосіб, який додаток одразу не помітив. Пошкодження було тихим: записувались операції, а моніторинг дивився лише на кількість запитів, а не на коректність даних. Коли проблему виявили, команда пішла до «копії DR». Там теж були ті самі відсутні дані. Звісно: вони не робили реплікацію з утриманням знімків; вони просто створили другу живу копію і періодично перерозділяли її як «оновлення».
Неправильне припущення було тонким: «У нас є ще один пул, отже в нас є відновлення». Але відновлення потребує виміру часу — історії, точок у часі, утримання — а split-пул цього не мав. Це був клон, не резервна копія.
Операційне виправлення було простим, але болючим: вони ввели дисципліновані знімки (з іменуванням і політиками утримання), потім інкрементальну реплікацію. Вони все ще використовували split для початкового seed DR швидко, але тільки як перший крок у реальному конвеєрі DR.
Культурне виправлення принесло більший виграш: вони перестали називати split-пул «бекап» у тікетах і дашбордах. Слова мають значення. Якщо ви назвете це «бекапом», хтось рано чи пізно поставить на це бізнес.
2) Оптимізація, що зіграла злий жарт: «Розділимо в піковий час; це миттєво»
Інша організація мала дзеркальний пул, що підтримував кластер віртуалізації. Хтось запропонував хитру ідею: зробити split у робочий час, бо сам split миттєвий, а експорт і переміщення дисків зробити після вечірнього вікна змін. Звучало ефективно. Перша половина була правдою. Друга — де реальність з’явилася з чеками.
Розділення пулу одразу зменшило кількість членів дзеркала у продакшні. Пул залишився ONLINE, але профіль продуктивності змінився. Декілька навантажень, що користувалися «випадковим» паралелізмом читання від дзеркал (та теплом кешу), опинилися в жорсткій конкуренції за IOPS. Латентність зросла, не катастрофічно, але достатньо, щоб спричинити таймаути в розмовному внутрішньому сервісі. Сервіс підскакував, ретраї збільшились, і підсилювач навантаження перетворив невелике підвищення латентності в невеликий інцидент.
Вони винесли дві практичні уроки. По-перше: в реальних системах «миттєві» операції можуть мати другорядні ефекти. Видалення членів дзеркала може змінити планування і поведінку черг так, як ваші бенчмарки по щасливому шляху ніколи не перевіряли. По-друге: міграції — це не лише операції зі зберігання; це події продуктивності. Якщо ваш сервіс налаштований на межі, топологічні зміни відчуваються.
Відновлення було простим: робити split у тихе вікно, або для денного безпечного варіанту робити seed реплікацією знімків. Вони також додали перед split перешкоду по продуктивності: якщо 95-й процентиль латентності вже підвищений, топологічні зміни не відбуваються.
3) Нудна, але правильна практика, що врятувала день: стабільні device ID і дисциплінований export
Одна з найуспішніших split-міграцій, яку я бачив, була майже агресивно нецікавою. Команда мала правило: пули створюються з використанням стабільних шляхів /dev/disk/by-id завжди, без винятків. Вони також мали звичку експортувати пули перед фізичним переміщенням — навіть якщо «ми просто перезавантажуємося для нової прошивки».
Під час переїзду дата-центру вони розділили дзеркальний пул у міграційний пул, експортували його і перемістили диски на нові хости. На приймачі перерахунок пристроїв був іншим, HBA були інші, і пару дисків опинилося на іншому бекплейні, ніж планували. Нічого з того не мало значення. zpool import знайшов пул за мітками, а by-id найменування робило очевидним, які серійні номери відсутні, коли один кабель був не підключений.
Нудна практика знову виявилася важливою, коли хтось спробував імпортувати пул на «стейджінг» хості для огляду, поки приймач збирали в стійку. Оскільки пул було експортовано чисто, не було плутанини «пул раніше використовувався», жодного примусового імпорту, ніякого ризику, що дві системи одночасно подумають, що вони володіють ним.
Нічого драматичного не сталося, і в цьому суть. У продакшні «нічого драматичного не сталося» — це функція, яку заробляють через звички, що виглядають педантичними, поки ними не потрібно скористатися.
Швидка діагностика (що перевірити спочатку, потім, і ще)
Коли split-міграція тягнеться або поводиться дивно, часу на філософствування немає. Ось швидкий порядок, який я використовую для знаходження вузького місця і вирішення — зупинитися, продовжити чи відкотитись.
Перший: Це проблема ZFS чи ОС/обладнання?
cr0x@server:~$ sudo zpool status -x
all pools are healthy
cr0x@server:~$ dmesg | tail -30
[...]
[ 8921.221] ata9.00: exception Emask 0x0 SAct 0x0 SErr 0x0 action 0x6 frozen
[ 8921.223] blk_update_request: I/O error, dev sdc, sector 12345678 op 0x0:(READ)
Рішення: Якщо dmesg показує помилки I/O/timeout-и — зупиніться і стабілізуйте обладнання перед тим, як звинувачувати ZFS. ZFS витримає багато, але не може домовитись із SATA-лінком, що виконує інтерпретативний танець.
Другий: Чи домінує вхід/вихід процес resilver/scrub?
cr0x@drhost:~$ sudo zpool status tank_dr
pool: tank_dr
state: ONLINE
scan: resilver in progress since Thu Dec 25 09:24:11 2025
180G scanned, 95G issued, 220G total
95G resilvered, 43.18% done, 00:08:41 to go
Рішення: Якщо resilver активний — продуктивність часто «працює як задумано». Або чекайте, або знижуйте очікування. Якщо бізнес потребує продуктивності негайно — розгляньте відтермінування частини навантажень до завершення resilver.
Третій: Ви обмежені CPU, ARC чи диском?
cr0x@drhost:~$ sudo arcstat 2 5
time read miss miss% dmis dm% pmis pm% mmis mm% arcsz c
09:40:01 812 121 14 0 0 31 4 90 11 42G 64G
09:40:03 905 188 20 0 0 45 5 143 15 42G 64G
Рішення: Високі показники пропусків при тестуванні міграції можуть виглядати як «сховище повільне», коли це просто холодний кеш. Розігрійте робочі навантаження або тестуйте з реалістичними умовами кешу. Якщо CPU високий і ви використовуєте шифрування/зжаття — перевірте, чи не обмежує вас CPU.
Четвертий: Монти та властивості роблять щось несподіване?
cr0x@drhost:~$ sudo zfs get -r -o name,property,value canmount,mountpoint tank_dr | head -20
NAME PROPERTY VALUE
tank_dr canmount off
tank_dr mountpoint /tank_dr
tank_dr/apps canmount on
tank_dr/apps mountpoint /tank/apps
Рішення: Якщо дочірній датасет все ще вказує на продукційний mountpoint (наприклад /tank/apps), ви можете змонтуватися поверх існуючих директорій на DR-хості. Так ви випадково починаєте «тестувати DR», перезаписуючи те, що вам подобалося.
Типові помилки (симптоми і виправлення)
Помилка 1: Розділення без розуміння втрати надмірності
Симптом: Після split новий пул показує однорівневі top-level vdev-и; старий пул тепер має менше членів; змінюється продуктивність; змінюється профіль ризику.
Виправлення: Заплануйте zpool attach нових дисків на приймачі для відновлення дзеркал, або свідомо прийміть ризик для короткочасного міграційного пулу. Задокументуйте це в записі зміни; майбутній ви це забуде.
Помилка 2: Імпорт і автомонтування в виробничі шляхи
Симптом: Після імпорту датасети монтуються під шляхами, що конфліктують з існуючими директоріями; сервіси починають читати/писати в невірну копію.
Виправлення: Імпортуйте з -o altroot=/mnt для огляду, або встановіть canmount=off перед експортом. Вмикайте монтування лише коли будете готові.
Помилка 3: Забуті робочі процеси з ключами шифрування на приймачі
Симптом: Пул імпортується, але датасети не монтуються; додатки бачать порожні директорії; zfs mount не вдається з помилками, пов’язаними з ключами.
Виправлення: Перевірте zfs get encryption,keylocation,keystatus. Перемістіть ключі безпечно, протестуйте zfs load-key і не припускайте, що «імпорт» = «готово до використання».
Помилка 4: Несумісність feature flags між джерелом і призначенням
Симптом: zpool import відмовляється з повідомленням «unsupported feature(s)» або подібним.
Виправлення: Оновіть стек ZFS на приймачі до підтримки потрібних feature flags. Якщо потрібно підтримувати старі системи — планувати це треба було до увімкнення фіч на джерелі — ZFS не робить «пониження версій».
Помилка 5: Використання нестабільних імен пристроїв і втрата зв’язку з дисками
Симптом: Після переміщення імпорт плутаний; ви не можете зіставити /dev/sdX з реальними дисками; ймовірні помилкові операції над невірними дисками.
Виправлення: Будуйте і працюйте, використовуючи /dev/disk/by-id. Під час відлагодження використовуйте серійні номера як істину.
Помилка 6: Розділення пулу з наявними помилками або деградованим дзеркалом
Симптом: Split-пул імпортується, але scrubs показують помилки контрольних сум; resilver тривалий; один диск починає викидати I/O помилки.
Виправлення: Стабілізуйте спочатку: замініть диски, очистіть помилки з zpool status -v, зробіть scrub, потім split. Якщо мусите split під тиском — імпортуйте в режимі read-only на приймачі і одразу scrub-те, щоб оцінити пошкодження.
Помилка 7: Припущення, що split дає чисту «точку в часі» для додатків
Симптом: Бази даних відновлюються, але з відсутніми або непослідовними останніми транзакціями; файлові системи VM показують відновлення журналу.
Виправлення: Заглушуйте додатки або використовуйте знімки, координовані з хуками додатків. Split фіксує стан пулу, не погодженість додатків.
FAQ
1) Чи копіює zpool split дані?
Ні. Воно переназначає членів дзеркала для формування нового пулу. Воно швидке, бо не переміщує блоки; воно змінює власність на існуючі диски.
2) Чи можна розділити RAIDZ пул?
Ні, не в сенсі «клону пулу». zpool split призначений для дзеркал. RAIDZ vdev-и не мають незалежних членів, які можна б перетворити на окремі когерентні vdev-и.
3) Чи матиме split-пул ті ж датасети і знімки?
Так: датасети, властивості і знімки, наявні в момент split, перейдуть разом, оскільки дані на диску ті самі. Але пам’ятайте: це не бекап. Якщо на джерелі була логічна корупція — тепер у вас дві копії її.
4) Що відбувається з GUID і іменами пулів?
Новий пул отримує свою ідентичність (нове ім’я пулу, окремий GUID). Це добре: зменшує випадкову плутанину «той же пул імпортовано двічі», але вам все одно треба бути обережним з mountpoints і автоматизацією хостів.
5) Чи можу я імпортувати split-пул на іншому хості, поки оригінал ще працює?
Так, часто в цьому суть. Але експортуйте split-пул чисто і ставтесь до нього як до окремої системи: уникайте монтування в спільні шляхи і переконайтесь, що жодна програма не пише в обидві копії, якщо це явно не спроектовано (зазвичай не так).
6) Як тримати DR-пул в актуальному стані після початкового seed?
Зазвичай через інкрементальні знімки: робіть знімки на джерелі і використовуйте zfs send/zfs receive на DR-пул. Split відмінний для першої копії; реплікація тримає її в актуальному стані.
7) Що з нативним шифруванням — split «ламить» його?
Ні. Метадані шифрування — частина датасетів. Але операційно вам потрібні ключі на приймачі, щоб монтувати зашифровані датасети. Плануйте розповсюдження ключів і тестуйте завантаження ключів перед оголошенням перемоги.
8) Чи безпечно запускати zpool split, поки пул онлайн і використовується?
Можна виконати онлайн, але «безпечно» залежить від вашого навантаження і толерантності до ризику. Сам split швидкий, але видалення членів дзеркала змінює надмірність і може вплинути на латентність під навантаженням. Для баз даних і образів VM я віддаю перевагу заглушенню або робити це в низько-накладному вікні.
9) Чи можна «скасувати» split?
Ні одного магічного команди для відміни. Можна приєднати диски назад і переміррувати, або знищити один пул і знову приєднати його диски, але це топологічна зміна з наслідками. Якщо вам потрібна відкатність, розгляньте реплікацію через знімки.
10) Чому імпорт спочатку в режимі read-only?
Бо це найбезпечніший спосіб підтвердити, що ви привезли правильні диски і пул здоровий, без просування стану на диску. Це дешева перевірка здорового глузду перед тим, як дозволити сервісам до нього підходити.
Висновок
zpool split — одна з тих фіч ZFS, що здається шахрайством при першому використанні: миттєвий клон пулу, без мережевої копії, без очікування. У продакшні це потужний інструмент саме тому, що він грубий. Ви не створюєте «копію» в сенсі бекапу — ви створюєте другий пул, пожертвувавши членами дзеркала, і берете відповідальність за надмірність, поведінку монтування, сумісність фіч і ключі.
Якщо запам’ятати три речі, то ці: перевірте, що у вас дзеркала; імпортуйте спочатку в режимі read-only; контролюйте монтування, ніби від цього залежить ваш вікенд (бо так і є). Split — відмінний спосіб почати міграцію або DR-план. Решта плану — нудний ритм знімків, дисципліна реплікації, scrubs та аудити — те, що перетворює цю швидку перемогу на систему, якій можна довіряти.