ZFS zfs send: Найшвидший спосіб перемістити терабайти (якщо робити правильно)

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

Є два типи міграцій даних: ті, що ви плануєте, і ті, що робите, поки всі дивляться. ZFS zfs send/zfs receive — один із небагатьох інструментів, який справляється з обома: переміщує терабайти з цілісністю, відтворюваністю і чіткою моделлю того, що змінилося. Але це також один із найпростіших способів виконати «успішний» перенос, який на ділі виявиться помилковим, болісно повільним або неможливим для поновлення.

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

Чому zfs send відрізняється (і чому це важливо)

Більшість «інструментів копіювання» переміщують файли. ZFS переміщує правду: узгоджений погляд на датасет у певний момент часу, представлену знімком. Потік zfs send — це не «те, що було в директорії під час запуску rsync». Це «точно ті блоки, на які посилається знімок X», опційно плюс «точно змінені блоки від X до Y». Ця різниця пояснює, чому реплікація ZFS може бути і швидшою, і правильнішою за міграцію на рівні файлів.

Компроміс у тому, що ви повинні поважати модель ZFS. Якщо не робити цього, ви опинитеся в ситуації, коли реплікуєте рухому ціль, реплікуєте від неправильного базового знімка або реплікуєте зашифровані дані так, що все здається гаразд до дня відновлення. В світі ZFS міграція — це ланцюжок знімків і припущень. Ваше завдання — зберегти цей ланцюжок цілим і зробити припущення явними.

Жарт для тону: реплікація ZFS схожа на переїзд будинку шляхом відправки фундаменту — ефективно і послідовно, але краще все ж виміряти під’їзд заздалегідь.

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

  • ZFS спроєктовано для наскрізної цілісності: контрольні суми перевіряються при читанні, отже реплікація плюс scrub дають історію виявлення корупції, яку більшість файлових інструментів не можуть повторити.
  • Знімки дешеві навмисне: знімки ZFS — це посилання copy-on-write, а не повні копії, що робить інкрементальну реплікацію практичною в масштабі.
  • Потоки send детерміновані: для того ж датасету/знімка потік стабільний настільки, щоб підтримувати відновлення та надійний receive.
  • Інкрементальний send — це функція першого класу: це не «порівняння файлів», це відправка тільки змінених блоків між знімками.
  • Зашифровані датасети змінили гру реплікації: «raw» send дозволяє реплікувати зашифровані дані, не розкриваючи відкритого тексту по мережі або на приймачі.
  • Обробка властивостей на приймачі — це продумано: ZFS дає керування, щоб перевизначати mountpoint, запобігати несподіваним монтам і керувати властивостями окремо від даних.
  • Токени відновлення додані, бо мережі брешуть: довгі потоки через ненадійні зв’язки потребували офіційного механізму відновлення, а не «почнімо з початку і пощастить».
  • Реплікація ZFS використовується як дешевий DR (і часто — хороший DR): її можна планувати, робити інкрементально й перевіряти, тому багато організацій будують DR на ній до купівлі дорогих рішень.

Ментальна модель: знімки, потоки і довіра

1) Ви не реплікуєте «датасет», ви реплікуєте «граф знімків»

Стан датасетів ZFS постійно змінюється. Знімки заморожують цей стан. Потік send посилає посилання на знімки. Інкрементальні send посилаються на пари знімків: базу і ціль.

Практичний наслідок: якщо базовий знімок відсутній на приймачі, інкрементальний receive не застосується. Якщо хтось видаляє «старі, непотрібні знімки» на кінці, ви щойно зламали реплікацію на завтра. Це не теоретичний крайній випадок; це повторювана інцидентна картина.

2) «Повний» vs «інкрементальний» — не про розмір, а про походження

Повний send (zfs send pool/ds@snap) дає весь стан датасету на момент знімка. Інкрементальний send (-i або -I) покладається на те, що приймач уже має пов’язаний знімок.

  • -i відправляє зміни від одного конкретного знімка до іншого («з A до B»).
  • -I відправляє інкрементальний ланцюг, включаючи проміжні знімки («з A через B, включно з проміжками»).

3) Ваш справжній ворог — не швидкість, а тихе розходження

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

4) Потоки включають більше, ніж вміст файлів

Потоки ZFS можуть містити властивості, знімки, клони (з потрібними прапорами) і — у raw-режимі — метадані шифрування. Це сила. Це також шкідливий інструмент, якщо ви не вирішите навмисно, що саме зберігати.

Практичні завдання (команди + як їх інтерпретувати)

Команди нижче припускають хост джерело (src) і хост призначення (dst) з уже створеними пулами ZFS. Замініть імена пулів і датасетів відповідно. Виводи є прикладними; у вас будуть інші.

Завдання 1: Перевірте стан пулу перед реплікацією

cr0x@src:~$ zpool status
  pool: tank
 state: ONLINE
status: Some supported features are not enabled on the pool.
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.
config:

        NAME        STATE     READ WRITE CKSUM
        tank        ONLINE       0     0     0
          mirror-0  ONLINE       0     0     0
            sda     ONLINE       0     0     0
            sdb     ONLINE       0     0     0

errors: No known data errors

Інтерпретація: Якщо ви бачите DEGRADED, resilvering або помилки контрольних сум, виправте це спочатку. Реплікація також переміщує корупцію; контрольні суми ZFS виявляють її, але не лікують джерело самі по собі.

Завдання 2: Оцініть розмір датасету та слід знімків

cr0x@src:~$ zfs list -o name,used,avail,refer,mountpoint -r tank/prod
NAME           USED  AVAIL  REFER  MOUNTPOINT
tank/prod      8.2T  12.1T   128K  /tank/prod
tank/prod/db   6.9T  12.1T   6.9T  /tank/prod/db
tank/prod/log  1.3T  12.1T   1.3T  /tank/prod/log

Інтерпретація: USED включає знімки і нащадків. REFER — дані, на які посилається сам датасет. Якщо USED значно більше за REFER, у вас значне збереження знімків; інкрементальна реплікація буде корисною.

Завдання 3: Створіть знімок для реплікації з конвенцією імен

cr0x@src:~$ zfs snapshot -r tank/prod@replica-2025-12-25-0001

Інтерпретація: Використовуйте передбачуваний префікс знімків (replica-), щоб автоматизувати вибір та видалення, не торкаючись ручних знімків.

Завдання 4: Dry-run оцінка розміру send (щоб спланувати)

cr0x@src:~$ zfs send -nP -R tank/prod@replica-2025-12-25-0001
size	9.11T

Інтерпретація: -nP оцінює розмір без відправки. -R реплікує датасет плюс нащадків і властивості. Оцінка допомагає вирішити, чи потрібні інкременти, стиснення чи вікно технічного обслуговування.

Завдання 5: Виконайте першу повну реплікацію (безпечні налаштування)

cr0x@src:~$ zfs send -R tank/prod@replica-2025-12-25-0001 | ssh dst sudo zfs receive -u -o mountpoint=/tank/restore tank/recv

Інтерпретація: -u запобігає миттєвому монтуванню на приймачі, уникаючи несподіваних монтів на зайнятих системах. Перевизначення mountpoint гарантує, що ви випадково не змонтуєте в продакшн-шляхах. Прийом у tank/recv створює чистий простір імен; пізніше ви можете просунути або перейменувати.

Завдання 6: Перевірте наявність отриманих знімків і відповідність імен

cr0x@dst:~$ zfs list -t snapshot -r tank/recv | head
NAME                                              USED  AVAIL  REFER  MOUNTPOINT
tank/recv/prod@replica-2025-12-25-0001             0B      -   6.9T  -
tank/recv/prod/db@replica-2025-12-25-0001          0B      -   6.9T  -
tank/recv/prod/log@replica-2025-12-25-0001         0B      -   1.3T  -

Інтерпретація: Наявність знімка — ваше підтвердження походження. Якщо ви не бачите очікуваного знімка, не переходьте до інкрементів, поки не зрозумієте причину.

Завдання 7: Виконайте інкрементальний send (один крок)

cr0x@src:~$ zfs snapshot -r tank/prod@replica-2025-12-25-0600
cr0x@src:~$ zfs send -R -i tank/prod@replica-2025-12-25-0001 tank/prod@replica-2025-12-25-0600 | ssh dst sudo zfs receive -u tank/recv

Інтерпретація: Це відправляє тільки змінені блоки між цими двома знімками, але все ще використовує -R для охоплення нащадків. Воно зазнає невдачі, якщо на приймачі відсутній базовий знімок.

Завдання 8: Інкрементальний з проміжками (-I) для пропущених запусків

cr0x@src:~$ zfs send -R -I tank/prod@replica-2025-12-25-0001 tank/prod@replica-2025-12-25-1800 | ssh dst sudo zfs receive -u tank/recv

Інтерпретація: Якщо ваша задача реплікації пропустила кілька знімків, -I може відправити ланцюг з проміжними знімками — часто це полегшує збереження і відкат на приймачі.

Завдання 9: Відправка зі стисканням «на дроті» (практично)

cr0x@src:~$ zfs send -R tank/prod@replica-2025-12-25-0001 | gzip -1 | ssh dst "gunzip | sudo zfs receive -u tank/recv"

Інтерпретація: Це просто і часто ефективно на датасетах з великою кількістю логів або тексту. На уже стислих даних (бекапи, медіа) це може витрачати CPU без користі. Вимірюйте, а не вгадуйте.

Завдання 10: Сейфна реплікація зашифрованого датасету (raw send)

cr0x@src:~$ zfs get -o name,property,value -s local encryptionroot,keystatus -r tank/secure
NAME         PROPERTY      VALUE
tank/secure  encryptionroot  tank/secure
tank/secure  keystatus       available

cr0x@src:~$ zfs snapshot -r tank/secure@replica-0001
cr0x@src:~$ zfs send -w -R tank/secure@replica-0001 | ssh dst sudo zfs receive -u tank/recv-secure

Інтерпретація: -w відправляє raw зашифрований потік. Приймач отримує зашифровані блоки; ви не розкриваєте відкритий текст під час передачі. Часто саме цього і хочуть команди з безпеки, за умови, що ви також маєте план керування ключами на приймачі.

Завдання 11: Обробка переривань за допомогою resume tokens (не починайте заново)

cr0x@dst:~$ zfs get -H -o value receive_resume_token tank/recv/prod
1-ED8f3a9c0c-...

cr0x@src:~$ zfs send -t 1-ED8f3a9c0c-... | ssh dst sudo zfs receive -u tank/recv

Інтерпретація: Якщо receive перервався, ZFS може зберегти resume token на приймачі. Відправка з -t продовжить звідти, де зупинилися, за умови, що токен дійсний і потік збігається. Ця функція відрізняє «втратили лінк на 30 секунд» від «пересилаємо 40 ТБ заново».

Завдання 12: Уникайте випадкового хаосу з mountpoint під час receive

cr0x@dst:~$ sudo zfs receive -u -o mountpoint=/mnt/quarantine -o canmount=off tank/recv < /tmp/stream.zfs

Інтерпретація: Якщо ви отримуєте з файлу або зі стадійної області, примусове canmount=off і quarantine mountpoint запобігають несподіваним монтам, особливо коли -R приносить кілька нащадків з успадкованими властивостями.

Завдання 13: Підтвердьте, що на приймачі дані читаються здоровими

cr0x@dst:~$ zpool scrub tank
cr0x@dst:~$ zpool status tank
  pool: tank
 state: ONLINE
status: Scrub in progress since Thu Dec 25 09:10:52 2025
        1.23T scanned at 6.10G/s, 180G issued at 900M/s, 9.11T total
        0B repaired, 1.98% done, 0:28:10 to go
config:

        NAME        STATE     READ WRITE CKSUM
        tank        ONLINE       0     0     0
errors: No known data errors

Інтерпретація: Scrub після великого receive — не параноя, а валідація. Якщо ваша DR-копія пошкоджена, ви хочете дізнатися зараз, а не під час аварії.

Завдання 14: Виміряйте продуктивність send/receive без гадань

cr0x@src:~$ zfs send -nP tank/prod@replica-2025-12-25-0001
size	9.11T

cr0x@src:~$ time zfs send -R tank/prod@replica-2025-12-25-0001 | ssh dst sudo zfs receive -u tank/recv
real	154m12.331s
user	2m10.912s
sys	12m48.776s

Інтерпретація: Вивід time плюс оцінений розмір дозволяє обчислити ефективну пропускну здатність. Не оптимізуйте всліпу: якщо CPU мало завантажено, але час стіни величезний, ви чекаєте мережі або дисків.

Продуктивність: як зробити це дійсно швидко

«Найшвидший спосіб перемістити терабайти» — правда, але за умов. ZFS може передавати дані на швидкості лінії, коли зорі співпадають: послідовні читання, мінімальні витрати CPU, пул приймача, що може вливати записи, і мережева траса, яка не падає від найменшого чиху. У реальному житті щось одне завжди є вузьким місцем.

Почніть з нудного обмеження: реплікація — це конвеєр

Send/receive — це конвеєр: читання з пулу джерела → створення потоку send → транспорт (часто SSH) → парсинг потоку на приймачі → запис у пул приймача → опціональне монтування та постпроцесинг. Конвеєр працює зі швидкістю найповільнішого етапу. Ваше завдання — швидко виявити цей етап і або прибрати його, або прийняти його як даність.

SSH: зручно, безпечно і іноді вузьке місце

SSH — стандартний транспорт, бо він скрізь і безпечний за замовчуванням. Але шифрування може стати стелею на швидких каналах. Якщо ви переміщаєте десятки терабайтів по 10/25/40/100GbE, протестуйте CPU на шифрування SSH. Якщо CPU завантажені, у вас є опції:

  • Вибирайте шифри, що апаратно прискорюються на ваших CPU (часто AES-GCM на сучасних x86).
  • Розпаралелюйте, розбиваючи датасети (кілька незалежних send), якщо ваше сховище може це витримати.
  • Використовуйте raw sends для зашифрованих датасетів (дані все одно будуть зашифровані на рівні ZFS), але SSH все ще шифруватиме транспорт, якщо ви його не зміните.

Другий жарт і повернення до роботи: єдина річ швидша за насичений 100Gb лінк — інженер, що каже «мабуть, DNS», коли явно це CPU.

Стиснення: важіль, а не релігія

Стиснення в транзиті може творити дива для датасетів з великою кількістю нульових чи повторюваних шаблонів, і бути марною тратою CPU для JPEG чи Parquet. Користуйтеся zfs send -nP для розміру, потім зробіть короткий таймований тест (менший датасет або недавній інкремент) зі стисненням і без. Вибирайте за виміряними показниками пропускної здатності та витратами CPU, а не за відчуттями.

Recordsize, volblocksize і чому бази даних поводяться інакше

Параметр recordsize датасету ZFS впливає на організацію даних і може непрямо впливати на поведінку send. Бази даних із багатьма дрібними випадковими записами часто виграють від менших блоків (або окремих датасетів), але реплікація все одно працює на рівні блоків. Для zvol (блокові пристрої) volblocksize фіксується при створенні; якщо ви реплікуєте великі zvol з крихітним volblocksize, ви підписуєтесь на більший об’єм метаданих і потенційно гіршу пропускну здатність.

Прийом у пул: мовчазний вбивця

У вас може бути супершвидке джерело і мережа, і все одно все повільно через те, що пул приймача не може закомітити записи. Поширені причини:

  • Малий або неправильно налаштований SLOG (для синхронних записів у певних навантаженнях; сам receive не є чисто sync, але може страждати від поведінки пулу).
  • Магнітні диски з недостатньою шириною vdev для стійкого запису.
  • Ashift mismatch, відмови дисків або пул, вже завантажений іншими навантаженнями.
  • Тиск на RAM, що викликає погану поведінку ARC і додаткові IO.

Використовуйте стадійні receives, коли потрібно захистити продакшн

Поширений підхід: отримати в pool/recv з canmount=off і безпечним mountpoint, а потім робити контрольований cutover: перейменувати датасети, встановити mountpoints, завантажити ключі, змонтувати й запустити сервіси. Це не зробить передачу швидшою, але зробить її живучою.

Три корпоративні міні-історії

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

План міграції виглядав чистим: повна реплікація в п’ятницю ввечері, інкременти щогодини, cutover у неділю. Команда припустила, що «інкрементальний» означає «на приймачі потрібен лише ім’я датасету». Так не було. Потрібен був точний базовий знімок.

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

О 10:00 годині ранку щогодинний інкремент почав падати з повідомленням, що виглядало як тимчасова проблема receive. У runbook було «повторіть», отож повторили. Потім знову. Тим часом на джерелі йшли нові записи, розширюючи розрив.

Коли помітили стійку помилку, команді довелося вибирати: пересіяти багатотерабайтову повну відправку в робочий час або погодитися на довший час відключення. Вони пересіяли вночі і вирізали пізно. Ніхто не був звільнений, але в pipeline з’явилося нове правило: базовий знімок — святе, а політика збереження має бути автоматизована і обробляти префікси.

Урок: Інкрементальна реплікація — про походження знімків, а не про «останній стан». Якщо приймач втрачає базу, у вас не реплікація — у вас часова бомба.

Міні-історія №2: Оптимізація, що обернулася проти

Інша команда хотіла швидкості. У них був 40Gb лінк і накопичення датасетів для DR. Хтось порадив стискати все «бо це завжди швидше». Вони загорнули zfs send в агресивне стиснення і оголосили перемогу після одного тесту на текстовому датасеті.

Потім направили це на медіа-архіви і образи VM. CPU взяв стелю на обох кінцях, потоки SSH конкурували за цикли, і пропускна здатність впала нижче того, що дав би простий нестиснений потік. Гірше: receive почав відставати настільки, що з’явилися таймаути, алерти і ланцюжок «DR-вузол впав?» повідомлень.

Виправлення було простим. Вони запустили короткий бенчмарк за класами датасетів і встановили політику: стискати по дроті для логів і дампів БД; не стискати для вже стиснутих blob; віддавати перевагу raw sends для зашифрованих датасетів; та обмежувати паралелізм згідно зі здатністю запису пулу приймача, а не з мережею. Pipeline став стабільним і прогнозовано швидким — менш драматично, але ефективніше.

Урок: Оптимізація одного етапу може виснажити інший. Стиснення — це компроміс пропускної здатності: мережа зекономлена, CPU витрачено. Трачте CPU тільки там, де це реально економить час.

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

Краща історія реплікації — та, де нічого не сталося. Команда зберігання мала рутину: перед будь-яким великим receive вони використовували -u, щоб запобігти монтам, примусово встановлювали quarantine mountpoint і запускали scrub протягом 24 годин. Вони також тегували реплікаційні знімки строгим префіксом і забороняли «ручне чищення знімків» на приймачі.

Одного кварталу DR-сайт пережив проблемний стрибок живлення. Більшість систем повернулись, але один дисковий шафа мав проблему контролера, що викликала переривчасті IO-помилки. Пул залишився ONLINE, але був не в порядку. Реплікація продовжувала працювати і «успішно» закінчувала для деяких датасетів — аж поки scrub не виявив помилки контрольних сум на нещодавно отриманих блоках.

Оскільки вони регулярно робили scrub, проблему виявили до реальної катастрофи. Вони призупинили реплікацію, полагодили залізо, перевіслали уражені інкременти, використовуючи збережену лінійку знімків, і знову перевірили. Коли через тижні сталася окрема інцидентна проблема в продакшні, DR-копія була придатна до використання — бо команда вважала «валідацію» частиною реплікації, а не розкішшю.

Урок: Нудні практики — відсутність несподіваних монтів, конвенція імен знімків, періодичні scrubs — це не церемонія. Це різниця між DR у презентації і DR як робочою системою.

План швидкої діагностики

Коли реплікація повільна або падає, у вас немає часу на танці. Ось найшвидший шлях до вузького місця у порядку, який зазвичай дає результат.

По-перше: підтвердіть, що прогрес йде (а не постійно повторюється)

cr0x@dst:~$ ps aux | egrep 'zfs receive|ssh' | grep -v egrep
root     21844  2.1  0.1  24548  9120 ?        Ss   09:20   0:01 zfs receive -u tank/recv
root     21843  0.9  0.0  16720  6340 ?        Ss   09:20   0:00 ssh -oBatchMode=yes src zfs send -R tank/prod@replica-2025-12-25-0600

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

По-друге: перевірте, чи приймач є затримкою (пул зайнятий або хворий)

cr0x@dst:~$ zpool iostat -v tank 2 3
                                              capacity     operations     bandwidth
pool                                        alloc   free   read  write   read  write
------------------------------------------  -----  -----  -----  -----  -----  -----
tank                                        9.40T  8.90T     10    980   12M   820M
  mirror-0                                  9.40T  8.90T     10    980   12M   820M
    sda                                         -      -      5    490    6M   410M
    sdb                                         -      -      5    490    6M   410M
------------------------------------------  -----  -----  -----  -----  -----  -----

Інтерпретація: Якщо записи близькі до фізичного максимуму пулу — це ваш вузький етап. Якщо записи низькі, але send повільний, дивіться в інші напрямки (SSH CPU, читання джерела, мережа).

По-третє: перевірте насичення CPU SSH

cr0x@src:~$ top -b -n 1 | head -n 15
top - 09:24:11 up 31 days,  6:02,  2 users,  load average: 18.22, 16.91, 14.77
Tasks: 312 total,   2 running, 310 sleeping,   0 stopped,   0 zombie
%Cpu(s):  3.2 us,  1.1 sy,  0.0 ni,  7.4 id, 88.0 wa,  0.0 hi,  0.3 si,  0.0 st
MiB Mem : 257982.3 total,  11230.5 free,  78112.9 used, 170638.9 buff/cache

Інтерпретація: Високий wa означає очікування IO (ймовірно, читання джерела). Високі user/system з ssh-процесами у верхівці вказують на накладні витрати на криптографію.

По-четверте: перевірте помилки походження знімків («впало миттєво»)

cr0x@dst:~$ sudo zfs receive -u tank/recv
cannot receive incremental stream: destination tank/recv/prod has been modified

Інтерпретація: Зазвичай це означає, що датасет приймача розійшовся (відбулися записи, rollback або видалено знімки). Виправляйте походження, не намагайтеся грубо повторити.

По-п’яте: перевірте, чи не блокує вас невідповідність режиму шифрування

cr0x@dst:~$ zfs get -o name,property,value -r tank/recv-secure | egrep 'encryptionroot|keystatus'
tank/recv-secure/secure  encryptionroot  tank/recv-secure/secure
tank/recv-secure/secure  keystatus       unavailable

Інтерпретація: keystatus unavailable — нормальна ситуація, якщо ключі не завантажені. Це стає проблемою, якщо ваш робочий процес очікує миттєвого монтування. Вирішіть, чи хочете ви raw-реплікацію (керування ключами окремо), чи розшифровану реплікацію (ключі завантажені на джерелі і дані відправляються у відкритому вигляді в потоці ZFS).

Поширені помилки (симптоми + виправлення)

Помилка 1: Прийом у неправильний шлях датасету

Симптом: Receive завершується, але датасети з’являються у несподіваній ієрархії (або перезаписують тестовий датасет).

Виправлення: Завжди приймайте у проміжний простір імен (наприклад, tank/recv) і використовуйте -u. Перевіряйте за допомогою zfs list -r перед монтуванням або перейменуванням.

Помилка 2: Видалення знімків на приймачі «щоб заощадити місце»

Симптом: Інкрементальні receives падають з повідомленням «missing snapshot» або «destination has been modified».

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

Помилка 3: Не використовувати -u і отримувати несподівані монтнення

Симптом: Після receive нові файлові системи автоматично монтовані, іноді на шляхах, що використовуються продакшн-сервісами.

Виправлення: Використовуйте zfs receive -u і перевизначайте mountpoint та/або встановлюйте canmount=off під час receive. Монуйте свідомо пізніше.

Помилка 4: Припускати, що стиснення завжди допомагає

Симптом: CPU завантажено, пропускна здатність гірша за очікувану, receive відстає.

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

Помилка 5: Ігнорувати прапори функцій пулу та сумісність версій

Симптом: Receive падає на старих системах або реплікований пул не імпортується там, де потрібно.

Виправлення: Вирівняйте версії/функції ZFS між сайтами перед побудовою DR-припущень. Якщо потрібно взаємодіяти зі старішим ZFS, уникайте ввімкнення функцій, що порушують сумісність.

Помилка 6: Забути, що -R приносить властивості і нащадків

Симптом: Mountpoints, quotas, reservations або інші властивості з’являються несподівано на приймачі.

Виправлення: Використовуйте overrides на стороні receive (-o) де потрібно, і аудітуйте критичні властивості після receive за допомогою zfs get. Майте «контракт властивостей» для реплікованих датасетів.

Помилка 7: Не планувати відновлення

Симптом: Тимчасове падіння мережі змушує повністю переслати й вибиває вікно.

Виправлення: Використовуйте resume tokens там, де вони підтримуються. Проєктуйте задачі так, щоб виявляти токени і автоматично відновлювати, а не починати з нуля.

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

Чекліст A: Одноразове засеювання (повна реплікація), що не нашкодить пізніше

  1. Перевірте стан пулу на обох кінцях (zpool status), спочатку виправте помилки.
  2. Виберіть конвенцію імен для реплікаційних знімків (replica-YYYY-MM-DD-HHMM).
  3. Створіть рекурсивний знімок на джерелі для початкового seed.
  4. Оцініть розмір за допомогою zfs send -nP -R, щоб зрозуміти час і пропускну здатність.
  5. Приймайте у staging-простір з -u і безпечними властивостями (mountpoint/canmount).
  6. Перевірте наявність знімків на приймачі і відповідність дерева датасетів очікуванням.
  7. Запустіть scrub пулу приймача протягом 24 годин після seed для впевненості.

Чекліст B: Постійна інкрементальна реплікація (основний режим)

  1. Створюйте нові знімки за графіком (годинні/щоденні), завжди з префіксом реплікації.
  2. Відправляйте інкременти, використовуючи відому базу; віддавайте перевагу -I, якщо хочете включати проміжні знімки.
  3. Використовуйте -u, щоб прийоми були недеструктивними; монтуйте лише під час контрольованих cutover або тестів.
  4. Моніторьте receive resume tokens і автоматично відновлюйте при перериванні.
  5. Застосовуйте політики збереження до реплікаційних знімків на обох кінцях, зберігаючи походження для наступного інкременту.

Чекліст C: План cutover (бо «просто переключимось» — це не план)

  1. Загасіть запис додатків (maintenance mode, flush бази даних або зупинка сервісу — що потрібно для вашого навантаження).
  2. Зробіть фінальні знімки і виконайте останній інкремент.
  3. На приймачі: встановіть фінальні mountpoints, завантажте ключі шифрування, якщо потрібно, і перевірте наявність датасетів.
  4. Змонтуйте датасети і запустіть сервіси; перевірте на рівні додатків, а не лише файлової системи.
  5. Залиште джерело в режимі тільки для читання і збережіть знімки, поки не впевнені в новому стані.

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

1) Чи завжди zfs send | zfs receive швидше за rsync?

Ні, але часто швидше в масштабі і зазвичай стабільніше. Воно блищить, коли можна використовувати інкременти і коли важливі семантики файлової системи (права доступу, hardlinks, xattrs). Якщо вам потрібна лише невелика підмножина файлів або ви не можете використовувати знімки, rsync може бути простішим.

2) Чи завжди слід використовувати -R?

Не завжди. -R чудово підходить для реплікації дерева датасетів з властивостями і знімками. Якщо вам потрібен лише один датасет без нащадків або ви хочете суворіше контролювати, які властивості подорожують, безрекурсивний send може бути безпечнішим.

3) Яка різниця між -i та -I знову?

-i відправляє від одного знімка до іншого (один дельта). -I відправляє інкрементальний ланцюг і включає проміжні знімки між базою і ціллю. Використовуйте -I, коли ви хочете, щоб приймач зберіг ту ж історію знімків.

4) Як зрозуміти, який знімок використати як базовий для інкременту?

Використовуйте найсвіжіший реплікаційний знімок, що існує на обох сторонах. Операційно це означає: останній успішно отриманий знімок з вашим префіксом реплікації. Не вгадуйте — перелікуйте знімки на обох сторонах і зіставляйте імена.

5) Чи можна безпечно відновити перервану передачу?

Так, якщо ваш ZFS підтримує resume tokens і ви не видалили частковий стан receive. Перевірте receive_resume_token на датасеті приймача; якщо є — відправляйте з zfs send -t <token> і приймайте знову.

6) Чи означає raw send (-w), що дані залишаються зашифрованими в транзиті?

Raw send означає, що ZFS відправляє зашифровані блоки і метадані шифрування, тож потік ZFS не містить відкритого тексту. Багато хто все одно використовує SSH, яке теж шифрує транспорт — ок, але для конфіденційності стрім сам по собі в raw-режимі достатній.

7) Чому мій інкрементальний receive впав з «destination has been modified»?

Бо він був змінений. Це може означати реальні записи в датасеті приймача, rollback, зміну властивостей, яка створює розходження в деяких контекстах, або відсутність очікуваних знімків. Виправлення — відновити спільну базу знімків, іноді через rollback або новий повний send.

8) Як запобігти автоматичному монтуванню реплікованих датасетів?

Використовуйте zfs receive -u. Для додаткової безпеки ставте canmount=off і quarantine mountpoint під час receive, потім змінюйте властивості і монуйте свідомо пізніше.

9) Чи безпечно реплікувати продакшн-бази даних зі знімками ZFS?

Це безпечно для файлової узгодженості, але не автоматично для узгодженості додатка. Для баз даних координуйте знімки з внутрішніми механізмами консистентності бази (flush/checkpoint/backup mode), якщо потрібні гарантії консистентності на рівні додатка.

10) Як перевірити, що DR-копія придатна?

Як мінімум: переконайтеся, що знімки присутні, запускайте періодичні scrubs і виконуйте тестові відновлення або монтвання в ізольованому середовище. План DR без тренувань з відновлення — лише красива історія.

Висновок

zfs send/zfs receive — один із небагатьох інструментів, що може швидко переміщати терабайти, не перетворюючи правильність на вправляння в надії й молитві. Але ZFS суворий так само, як суворі хороші системи: походження знімків важливе, властивості важливі, і приймач — не смітник, у який можна виливати потоки.

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

← Попередня
OpenVPN на Windows: проблеми драйвера TAP і як їх виправити
Наступна →
Tailscale: VPN без болю та помилки доступу, які все ще шкодять

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