ZFS Raw Send: реплікація зашифрованих даних без передачі ключів

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

Шифрування в ZFS — одна з тих рідкісних функцій, що справді полегшує роботу інженера зі сховищами: дані шифруються на диску, ключі керуються на рівні набору даних, а реплікація може відбуватися без того, щоб ваш DR-сайт перетворився на сервіс зберігання ключів. Чарівний трюк за останнім пунктом — це raw send: спосіб реплікувати зашифровані байти «як є», щоб отримувач міг зберігати і обслуговувати набір даних, ніколи не дізнавшись ключів шифрування.

Це не теоретична «сіра безпекова стаття». Raw send — це те, як ви будуєте адекватні мультісайтні бекапи, коли законодавство, відповідність або простий здоровий глузд говорять «провайдер резервних копій не повинен мати ключі». Це також спосіб уникнути класичної помилки — розшифровувати на джерелі лише для того, щоб надіслати plaintext кудись «безпечне». Спойлер: «безпечне місце» з часом перетворюється на «місце з компрометованим ноутбуком адміністратора».

Що таке raw send насправді (і чого воно не є)

Будьмо точні, бо обговорення реплікації ZFS часто зводяться до розмитих фраз на кшталт «воно зашифровано, тож безпечно». Raw send — це не «використай ssh і считай, що воно зашифроване». Raw send — це не «надішліть набір даних, який випадково зашифрований». Raw send — це конкретний режим zfs send, у якому стрім містить зашифровані блоки й метадані так, як вони зберігаються на диску, замість того щоб ZFS розшифровував їх перед відправкою.

На практиці:

  • Звичайний send для зашифрованого набору даних зазвичай створює стрім розшифрованих даних (якщо ви явно не попросите інакше). Приймач відтворює вміст набору даних, але сам стрім не є шифротекстом, який лежав на диску.
  • Raw send створює стрім, що зберігає набір даних зашифрованим так, як ZFS його зберігає. Приймач зберігає зашифрований набір і може реплікувати його далі, робити знімки тощо — але не зможе його примонтувати/прочитати, поки ключ не буде пізніше наданий.

Одним реченням: raw send реплікує шифротекст і контекст шифрування, а не plaintext.

Дві операційні наслідки, що мають значення:

  • З raw send ваш DR-сайт може бути «простим сховищем» для зашифрованих наборів даних. Ви передаєте їм відповідальність за зберігання та реплікацію без передачі ключів.
  • З raw send на стороні отримувача все ще можна виконувати операції ZFS (знімки, утримання, подальша реплікація), але вона не може «вилікувати» ваші дані, зробивши їх читабельними, якщо ви втратите ключі. Шифрування — жорстокий вчитель: воно оцінює суворо.

Жарт №1 (коротко й доречно): Шифрування як ремінь безпеки: здається скуто, поки не побачиш, як хтось «просто тримається» у аварії.

Факти та історичний контекст

Інженерія сховищ сповнена емоцій «ми це вигадавши у 2005 і досі пояснюємо у 2025». Ось кілька конкретних фактів і контексту, які допомагають зрозуміти raw send:

  1. zfs send/receive з’явився раніше за рідне шифрування ZFS. Реплікація існувала задовго до того, як шифрування стало частиною ядра, тому модель реплікації довелося розширювати обережно, щоб не порушити існуючих припущень.
  2. Шифрування в ZFS — рідне для набору даних і на рівні блоків. Це не історія «файлова система поверх LUKS». ZFS шифрує блоки і зберігає метадані шифрування з набором даних, дозволяючи ключі на рівні набору та ротацію ключів.
  3. Raw send існує, бо «зашифрований набір даних» не означає автоматично «зашифрований стрім реплікації». Без режиму raw ZFS може надсилати логічне подання набору, яке фактично є plaintext у стрімі.
  4. Знімки — одиниця реплікації. ZFS send — це не «синхронізувати папку». Це «надіслати різницю між двома точками у часі». Саме тому політика знімків — це ваша політика реплікації.
  5. Токени відновлення змінили оперативну історію. На ненадійних зв’язках «почати спочатку» раніше було стандартом. Resume tokens дозволяють продовжити receive без пересилки всього заново.
  6. Raw send зберігає encryption root і властивості. Межа шифрування важлива: набори даних можуть наслідувати шифрування, але raw send потребує повного контексту шифрування для консистентності між сайтами.
  7. Dedup та стиснення не даються безкоштовно. Особливо з шифруванням, очікування щодо ефективності dedup часто колізують з реальністю (і вимогами до RAM).
  8. Потоки ZFS можуть включати вкладені дані, великі блоки і поведінку recordsize. Якщо ви звикли до інструментів рівня файлів, момент «чому це в 3 рази більше» настає швидко, коли recordsize, стиснення й частота знімків взаємодіють.

Модель загроз: що захищає raw send (і що ні)

Raw send — це інструмент безпеки, а не ковдра від усіх бід. Використовуйте його, щоб вирішувати правильну задачу.

Що захищає raw send

  • Адміністратори сховища на приймаючій стороні не можуть читати дані без ключів. Вони можуть реплікувати, знімати, знищувати або втратити їх — але не можуть переглянути вміст.
  • Проміжні системи не можуть прочитати вміст стріму, якщо raw stream транспортується через ненадійну інфраструктуру. (Вони все ще можуть його змінити — це окрема розмова.)
  • Розділення ключів між середовищами. Ви можете тримати продакшен-ключі в продакшені та все ще мати віддалені копії зашифрованих наборів даних.

Чого raw send не захищає

  • Цілісності сам по собі. Raw send захищає конфіденційність, а не автентичність. Контрольні суми ZFS допомагають виявити корупцію, але ви все одно маєте думати про цілісність транспорту, помилки дисків і ворожі модифікації.
  • Доступності. Якщо ви втратите ключі, ваш DR-сайт перетвориться на музейну експозицію під назвою «Зашифровані блоки, станом на вівторок».
  • Витоку метаданих поза охопленням шифрування. Залежно від реалізації, деякі метадані (імена наборів, імена знімків, розміри, час) можуть бути помітні через властивості ZFS і операційні логи.
  • Поганої гігієни знімків. Якщо ви робите знімки і реплікуєте секрети, які не слід було зберігати, raw send вірно відправить вашу помилку офсайт.

Ментальна модель: як уявляти шифрування і потоки send

Найкорисніша ментальна модель така: ZFS має два загальні способи представлення набору даних для реплікації.

  • Логічне представлення: «Ось файли/блоки, як вони мають виглядати». ZFS може відтворити це і записати блоки на приймачі. Саме тут plaintext може з’явитися у стрімі, навіть якщо дані на диску зашифровані — бо ZFS описує логічний вміст.
  • Raw-представлення: «Ось точні блоки на диску та метадані». Якщо набір даних зашифрований, ці блоки — шифротекст. Приймач зберігає їх як шифротекст. Ключі не потрібні для зберігання; ключі потрібні для інтерпретації.

Raw send також взаємодіє з поняттям encryption root. В ZFS набір даних може наслідувати шифрування від батьківського. Encryption root — це місце, де встановлюються налаштування шифрування. Коли ви реплікуєте, потрібно зберегти межу шифрування, інакше на приймаючій стороні не вдасться правильно відобразити наслідування ключів і властивості.

Саме тут люди спотикаються: вони припускають, що «зашифрований набір» означає «приймач зможе завантажити ключ і примонтувати». Це може бути правдою, але це опціонально. Raw send спеціально створено так, щоб приймач не потребував ключів для отримання. Чи зможе він пізніше примонтувати — залежить від того, чи завантажать ключ на приймачі й чи збігаються параметри шифрування з очікуваними.

Жарт №2 (коротко й доречно): У сховищах «в стаджингу все працювало» — це ввічливий спосіб сказати «у продакшені більше ентропії».

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

Нижче — реальні завдання, які ви виконуватимете при побудові й експлуатації реплікації raw send. Кожне завдання містить команди та показники, на які варто звертати увагу. Я припускаю інструменти OpenZFS на Linux, але концепції переносяться на інші платформи з незначними відмінностями прапорів.

Завдання 1: Підтвердити, що набір даних зашифрований і визначити encryption root

cr0x@source:~$ zfs get -H -o name,property,value encryption,keylocation,keystatus,encryptionroot tank/prod
tank/prod	encryption	aes-256-gcm
tank/prod	keylocation	prompt
tank/prod	keystatus	available
tank/prod	encryptionroot	tank/prod

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

Завдання 2: Створити знімок реплікації з іменуванням, яке не завадить пізніше

cr0x@source:~$ zfs snapshot -r tank/prod@rep-2025-12-25T0200Z
cr0x@source:~$ zfs list -t snapshot -o name,used,creation -r tank/prod | tail -5
tank/prod@rep-2025-12-25T0200Z	0B	Thu Dec 25 02:00 2025
tank/prod/db@rep-2025-12-25T0200Z	0B	Thu Dec 25 02:00 2025
tank/prod/app@rep-2025-12-25T0200Z	0B	Thu Dec 25 02:00 2025

Інтерпретація: Імена знімків стають операційними маркерами. Якщо іменування хаотичне, ваші скрипти інкрементальної реплікації стануть переслідуваними примарами.

Завдання 3: Виконати повний raw send у новий приймаючий датасет (не примонтований)

cr0x@source:~$ zfs send -w -R tank/prod@rep-2025-12-25T0200Z | ssh cr0x@dest "zfs receive -uF backup/prod"
cr0x@dest:~$ zfs list -o name,used,avail,keystatus,mounted backup/prod
NAME         USED  AVAIL  KEYSTATUS  MOUNTED
backup/prod  112G  38.2T  unavailable  no

Інтерпретація: -w — це переключач raw send. -R реплікує набір і його нащадків плюс властивості. На приймаючій стороні -u залишає його непремонтованим (добра практика, коли ключів немає). Побачити keystatus=unavailable на приймаючому — це суть: він отримав зашифровані дані без ключів.

Завдання 4: Перевірити, що ви справді отримали зашифрований набір (а не plaintext)

cr0x@dest:~$ zfs get -H -o name,property,value encryption,keystatus,encryptionroot backup/prod
backup/prod	encryption	aes-256-gcm
backup/prod	keystatus	unavailable
backup/prod	encryptionroot	backup/prod

Інтерпретація: Якщо тут encryption off, ви не зробили те, що думали. Зупиніться й розберіться, перш ніж реплікувати далі.

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

cr0x@source:~$ zfs snapshot -r tank/prod@rep-2025-12-25T0300Z
cr0x@source:~$ zfs send -w -R -I tank/prod@rep-2025-12-25T0200Z tank/prod@rep-2025-12-25T0300Z | ssh cr0x@dest "zfs receive -uF backup/prod"
cr0x@dest:~$ zfs list -t snapshot -o name,creation -r backup/prod | tail -3
backup/prod@rep-2025-12-25T0200Z	Thu Dec 25 02:00 2025
backup/prod@rep-2025-12-25T0300Z	Thu Dec 25 03:00 2025

Інтерпретація: -I відправляє всі проміжні знімки між двома точками (корисно, коли ви могли пропустити деякі). Якщо ваш граф знімків чистий, -i компактніший. Для простоти операцій часто виграє -I.

Завдання 6: Оцінити розмір send перед тим, як наситити лінк (або вікно змін)

cr0x@source:~$ zfs send -nP -w -R -I tank/prod@rep-2025-12-25T0200Z tank/prod@rep-2025-12-25T0300Z
size	21474836480
incremental	size	21474836480

Інтерпретація: -nP — сухий прогін з парсованим виводом. Це «size» — ваш плановий показник. Якщо це значно більше, ніж очікували, ймовірно у вас часті зміни знімків, невідповідність recordsize або додаток, що «перезаписує весь файл щохвилини».

Завдання 7: Прийняти у безпечну зону, використовуючи -u, і перевірити, що нічого не примонтується автоматично

cr0x@dest:~$ zfs receive -uF backup/prod < /dev/null
cannot receive: failed to read from stream

Інтерпретація: Команда падає через відсутність стріму, але суть культурна: завжди включайте -u в автоматизації для зашифрованих DR-копій, хіба що ви явно робите warm standby з завантаженими ключами.

Завдання 8: Використовувати resume tokens для виживання на ненадійних лінках

cr0x@dest:~$ zfs get -H -o value receive_resume_token backup/prod
1-8f9c2f1d7c-100000-7890abcdef-200000-10

Інтерпретація: Якщо receive перервано, це властивість може містити токен. Це не трофей; це ваш запасний вихід.

cr0x@source:~$ ssh cr0x@dest "zfs get -H -o value receive_resume_token backup/prod"
1-8f9c2f1d7c-100000-7890abcdef-200000-10
cr0x@source:~$ zfs send -w -t 1-8f9c2f1d7c-100000-7890abcdef-200000-10 | ssh cr0x@dest "zfs receive -uF backup/prod"

Інтерпретація: zfs send -t продовжує зі вказаного токена. Це може заощадити години (і ваші відносини з мережевою командою).

Завдання 9: Підтвердити, що приймач не може примонтувати без ключів (очікувана поведінка)

cr0x@dest:~$ zfs mount backup/prod
cannot mount 'backup/prod': encryption key not loaded

Інтерпретація: Це умова успіху для «режиму сховища». Якщо ви очікували примонтування, вам потрібен план управління ключами, а не інший прапор ZFS.

Завдання 10: Завантажити ключ на приймаючій стороні (тільки коли доречно)

cr0x@dest:~$ zfs load-key backup/prod
Enter passphrase for 'backup/prod': 
cr0x@dest:~$ zfs get -H -o value keystatus backup/prod
available
cr0x@dest:~$ zfs mount backup/prod
cr0x@dest:~$ zfs get -H -o value mounted backup/prod
yes

Інтерпретація: Тепер ви перейшли від «лише сховище DR» до «DR, здатного читати». Саме тут аудитори починають питати, хто може вводити ту фразу і де вона зберігається.

Завдання 11: Перевірити стан реплікації, порівнявши списки знімків

cr0x@source:~$ zfs list -t snapshot -o name -r tank/prod | grep '@rep-' | tail -5
tank/prod@rep-2025-12-25T0200Z
tank/prod@rep-2025-12-25T0300Z
tank/prod@rep-2025-12-25T0400Z
tank/prod@rep-2025-12-25T0500Z
tank/prod@rep-2025-12-25T0600Z

cr0x@dest:~$ zfs list -t snapshot -o name -r backup/prod | grep '@rep-' | tail -5
backup/prod@rep-2025-12-25T0200Z
backup/prod@rep-2025-12-25T0300Z
backup/prod@rep-2025-12-25T0400Z
backup/prod@rep-2025-12-25T0500Z
backup/prod@rep-2025-12-25T0600Z

Інтерпретація: Правильність реплікації починається з «чи маємо ті самі кінцеві знімки?» — не ускладнюйте це.

Завдання 12: Використовувати holds, щоб запобігти видаленню знімків під час реплікації

cr0x@source:~$ zfs hold -r keepforrep tank/prod@rep-2025-12-25T0600Z
cr0x@source:~$ zfs holds -r tank/prod@rep-2025-12-25T0600Z | head
NAME                          TAG         TIMESTAMP
tank/prod@rep-2025-12-25T0600Z  keepforrep  Thu Dec 25 06:01 2025

Інтерпретація: Holds недооцінені. Вони заважають благими намірами скриптам прибирання видаляти знімок, від якого залежить ваш ланцюг інкрементів.

Завдання 13: Перевірити пропускну здатність send/receive і знайти, куди йде час

cr0x@source:~$ zpool iostat -v 2
                              capacity     operations     bandwidth
pool                        alloc   free   read  write   read  write
--------------------------  -----  -----  -----  -----  -----  -----
tank                         9.21T  5.32T    210    980   185M   612M
  raidz2-0                   9.21T  5.32T    210    980   185M   612M
    sda                          -      -     26    120  23.1M  76.4M
    sdb                          -      -     25    122  22.9M  77.1M
...

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

Завдання 14: Прийняти безпечно, коли на приймачі вже є дані (форсований rollback з обережністю)

cr0x@dest:~$ zfs receive -uF backup/prod
cannot receive: failed to read from stream

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

Завдання 15: Перевірити, що ключ шифрування випадково не скопійовано в автоматизацію

cr0x@dest:~$ zfs get -H -o name,property,value keylocation backup/prod
backup/prod	keylocation	none

Інтерпретація: Для «режиму сховища» keylocation=none (або неавтоматичне джерело) зменшує ймовірність автоматичного завантаження ключів при перезавантаженні. Якщо ваше середовище очікує автозавантаження, задокументуйте це й проведіть аудит.

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

1) Інцидент через неправильне припущення: «зашифрований набір даних» рівнозначно «зашифрованій реплікації»

В одній великій організації (така, що має три системи тикетингу і нуль спільних календарів) команда перемістила чутливий набір даних на шифрування ZFS і оголосила перемогу. Compliance полюбив терміни «AES-256», керівництву сподобалося, що ніхто не просив бюджету, а команда сховища була рада, що не треба вчити розробників керуванню секретами.

Потім настав час DR-реплікації. Хтось поспіхом підключив zfs send і zfs receive, бо стара система бекапів виходила з підтримки і вендор почав говорити тільки про продовження контракту. Реплікація спрацювала, знімки з’явилися на віддаленому сайті, і всі повернулися до своїх справ.

Через місяці, під час перевірки безпеки, аудитор запитав просте: «Чи можуть адміністратори віддаленого сайту читати репліковані дані?» Очікувана відповідь: «ні». Результат тесту: «так», і це було так само ніяково, як ви уявляєте — тихо, професійно і з купою нотаток.

Постмортем не був про злобу. Це було про припущення: команда думала, що шифрування на диску означає шифрування в польоті й у стрімі. Але їхня реплікація посилала не-raw стрім, і приймач зберігав датасет, який можна було примонтувати локально без оригінальної межі шифрування. Вони побудували DR, який виглядав правильним у моніторингу, але порушував вимогу безпеки.

Фікс був простим: перебудувати реплікацію з raw send, перевірити keystatus=unavailable на приймачі й написати ранбуk з чітким рішенням: «ми будуємо сховище чи warm standby?» Урок, який ми завжди переучуємо: у ZFS властивість набору даних не є політикою, поки ви не протестували це наскрізь.

2) Оптимізація, що обернулася проти: «вмикаємо dedup для бекапів»

Інше місце, інтенція добра. Вони мали нічні знімки образів VM і томів баз даних. Реплікація на DR-сайт жерла пропускну здатність і хотілося зменшити обсяг. Хтось запропонував dedup: «У нас багато схожих блоків; ZFS dedup це скоротить». Ідея звучала правдоподібно, і фраза «розжати пропускну здатність» мала певну привабливість.

Вони включили dedup у пулі на приймачі, аргументуючи, що це «лише бекапи». Короткий час вони бачили покращення використання простору й трохи менші дельти. Потім система почала тягнутися. Спочатку це виглядало як мережеві стрибки. Потім як затримки диску. Зрештою все — повільні receives, повільні знімки і час від часу зависання, що породжували підозри на рівні гіпервізора.

Програш був передбачуваний постфактум: dedup потребує пам’яті для DDT, і зашифровані raw блоки не дедупляться так, як люди інтуїтивно очікують. Шифрування перетворює «схожі plaintext-блоки» на «випадково виглядаючі ciphertext-блоки», тож виграш у dedup може бути дрібним, а витрати DDT реальними. Вони відкотили dedup, прийняли, що стиснення й розумна частота знімків кращі інструменти, і додали метрику: «вартість реплікації за змінений GB». Висновок: якщо оптимізація змінює профіль пам’яті і метаданих, ви не оптимізували — ви змінили систему. Іноді це норм, але ніколи не безкоштовно.

3) Нудна, але правильна практика, що врятувала ситуацію: утримання знімків і дисципліна ланцюжка

Найгероїчніші інциденти часто найменш гламурні. Одна команда робила погодинні знімки і raw інкрементальну реплікацію на віддалений сайт. Вони також мали болісно нудне правило: знімки реплікації отримували тег hold, а джоби прибирання не мали права видаляти утримувані знімки. Це не було хитро. Це нікого не вражало в архітектурних нарадах. Це було просто… політика.

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

Однак він не зміг видалити опорні знімки реплікації, бо вони були утримані. Це означало, що інкрементальний ланцюжок зберігся, а операційна команда могла обмежити навантаження, підправити частоту знімків і дати реплікації час наздогнати. Без holds вони б втратили базовий знімок у найгірший момент і були змушені робити повну пересинхронізацію.

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

Швидкий план діагностики

Коли реплікація raw send повільна, падає або поводиться дивно, вам не потрібен 40-кроковий чеклист у першу чергу. Потрібна швидка воронка, що ідентифікує категорію вузького місця: CPU, диск, мережа або семантика ZFS (знімки/стріми/властивості). Ось план, який я використовую перед тим, як дозволити комусь «тюнити».

Перший крок: підтвердити, що ви робите насправді (raw vs non-raw, full vs incremental)

cr0x@source:~$ zfs send -nP -w -R -I tank/prod@rep-2025-12-25T0200Z tank/prod@rep-2025-12-25T0300Z
size	21474836480
incremental	size	21474836480

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

Другий крок: перевірити обмеження на приймачі (місця, readonly, несумісний стан)

cr0x@dest:~$ zpool list
NAME    SIZE  ALLOC   FREE  CKPOINT  EXPANDSZ   FRAG    CAP  DEDUP  HEALTH  ALTROOT
backup  40T   28.1T  11.9T        -         -    21%    70%  1.00x  ONLINE  -

cr0x@dest:~$ zfs get -H -o name,property,value readonly,available,receive_resume_token backup/prod
backup/prod	readonly	off
backup/prod	available	11.2T
backup/prod	receive_resume_token	-

Шукайте: мало вільного місця, readonly=on або resume token, що вказує на повторні переривання.

Третій крок: вирішити, чи вузьке місце — диск, CPU чи мережа

Диск:

cr0x@source:~$ zpool iostat -v 2
cr0x@dest:~$ zpool iostat -v 2

Шукайте: висока затримка очікування (await/latency на платформах, що показують), насичення окремого vdev або те, що приймач пише на повну, а CPU простає.

CPU / crypto:

cr0x@source:~$ top -b -n 1 | head -20
cr0x@dest:~$ top -b -n 1 | head -20

Шукайте: один потік завантажений процесом ssh або kernel crypto, що вказує на вибір шифру або відсутність апаратного прискорення.

Мережа:

cr0x@source:~$ ip -s link show dev eth0
cr0x@dest:~$ ip -s link show dev eth0

Шукайте: помилки/втрати. Якщо лінк чистий, але пропускна здатність низька, підозрюйте однопоточний етап (ssh cipher, буфер користувацького простору або поведінку sync на приймачі).

Четвертий крок: інспектувати поведінку zfs receive і сумісність стріму

cr0x@dest:~$ zfs events -v | tail -30

Шукайте: події про невдалі receives, помилки контрольних сум або проблеми на рівні пулу, що змушують реплікацію «повільніти», бо вона постійно перекидається.

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

Помилка 1: Забути raw режим і припустити, що шифрування автоматично переноситься

Симптом: приймаючий датасет примонтовується/читається без очікуваного завантаження ключа; або приймач має encryption=off.

Виправлення: перебудуйте реплікацію з raw send і перевірте на приймачі:

cr0x@source:~$ zfs send -w -R tank/prod@rep-2025-12-25T0200Z | ssh cr0x@dest "zfs receive -uF backup/prod"
cr0x@dest:~$ zfs get -H -o name,property,value encryption,keystatus backup/prod
backup/prod	encryption	aes-256-gcm
backup/prod	keystatus	unavailable

Помилка 2: Розрив ланцюга інкрементів через видалення знімків

Симптом: cannot send '...': incremental source ... does not exist або приймач відмовляється через відсутність бази.

Виправлення: додайте holds до опорних знімків і видаляйте лише ті знімки, що підтверджено репліковані.

cr0x@source:~$ zfs hold -r keepforrep tank/prod@rep-2025-12-25T0600Z
cr0x@source:~$ zfs release -r keepforrep tank/prod@rep-2025-12-25T0200Z

Помилка 3: Використовувати -F сліпо на цілі, що не лише для реплікації

Симптом: «таємне» зникнення локальних знімків або локальних змін на приймачі після запуску реплікації.

Виправлення: розділіть набори даних: один — строго для реплікації, інший — для локального використання. Або приберіть -F і обробляйте розбіжності явно.

Помилка 4: Дозволити приймачу автопримонт зашифрованих наборів

Симптом: несподівані примонтування під час завантаження, ключі якось завантажуються, збільшення зони ураження при компрометації аккаунта DR-адміна.

Виправлення: приймайте з -u, встановіть контрольований keylocation і проведіть аудит процедур завантаження ключів.

cr0x@dest:~$ zfs set canmount=off backup/prod
cr0x@dest:~$ zfs get -H -o name,property,value canmount,mounted backup/prod
backup/prod	canmount	off
backup/prod	mounted	no

Помилка 5: Плутанина «шифрований транспорт» і «конфіденційність raw send»

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

Виправлення: розглядайте ssh/TLS як захист транспорту; розглядайте raw send як захист формату даних. Використовуйте обидва для глибокої оборони.

Помилка 6: «Тюнінг продуктивності» шляхом додавання шарів (і затримки)

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

Виправлення: вимірюйте кожен етап; спрощуйте конвеєр; узгоджуйте CPU і диск. Якщо додаєте інструмент — обґрунтуйте його метриками.

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

План A: Побудувати vault-стиль DR репліку (приймач не читає дані)

  1. На джерелі підтвердити, що шифрування увімкнене, і зафіксувати encryption root.
  2. Створити рекурсивний знімок реплікації із стабільною схемою імен.
  3. Запустити dry-run для оцінки розміру початкової повної відправки.
  4. Зробити повний raw send з -w -R.
  5. Прийняти з -u і розглянути canmount=off на приймачі.
  6. Перевірити keystatus=unavailable і що датасет залишається не примонтованим.
  7. Автоматизувати погодинні/щоденні інкременти raw send із утриманнями знімків.
  8. Встановити правила обрізки, що поважають утримання, і перевіряти наявність реплікованих знімків перед видаленням.

План B: Побудувати warm standby (приймач може примонтувати з контрольованими ключами)

  1. Спочатку зробити все з Плану A.
  2. Визначити обробку ключів: хто завантажує ключі, де зберігаються паролі, як проходитиме аудит.
  3. Протестувати ручне завантаження ключа і примонтування в контрольованому вікні обслуговування.
  4. Вирішити, чи ключі мають автозавантажуватися на старті (більшість середовищ має відповідати «ні», якщо немає вагомої операційної причини).
  5. Провести репетицію відмови: підняти сервіси, перевірити узгодженість додатків, виміряти RTO.

Покроково: мінімальний відтворюваний цикл реплікації

Це версія «якщо ви втомлені і зараз 02:00». Припускає SSH-зв’язок і що приймач — сувора репліка.

cr0x@source:~$ export SRC=tank/prod
cr0x@source:~$ export DST=backup/prod
cr0x@source:~$ export SNAP=rep-$(date -u +%Y-%m-%dT%H%MZ)

cr0x@source:~$ zfs snapshot -r ${SRC}@${SNAP}
cr0x@source:~$ zfs hold -r keepforrep ${SRC}@${SNAP}

cr0x@source:~$ LAST=$(zfs list -t snapshot -o name -s creation -r ${SRC} | grep '@rep-' | tail -2 | head -1)
cr0x@source:~$ CURR=${SRC}@${SNAP}

cr0x@source:~$ zfs send -nP -w -R -I ${LAST} ${CURR}

cr0x@source:~$ zfs send -w -R -I ${LAST} ${CURR} | ssh cr0x@dest "zfs receive -uF ${DST}"

Інтерпретація: Це створює новий знімок, ставить на нього hold, знаходить попередній знімок реплікації, оцінює розмір і потім відправляє інкрементально в raw-режимі. У реальній автоматизації потрібно обробляти випадок «першого запуску» і знімати утримання, коли це безпечно.

Питання й відповіді (FAQ)

1) Чи означає raw send, що мені не потрібен SSH-шифр?

Ні. Raw send захищає конфіденційність корисного навантаження навіть при перехопленні, але SSH важливий для автентифікації, захисту від підміни в дорозі і зменшення операційного ризику. Використовуйте raw send для «жодних ключів на приймачі», а SSH для «ніхто не підкине сміття в мій receive».

2) Чи може приймач реплікувати зашифрований набір далі без ключів?

Так, це одна з найкращих властивостей. Приймач може виконувати raw send зашифрованого набору на іншу ціль, виступаючи реле або вторинним сховищем, ніколи не завантажуючи ключі.

3) Що фактично означає keystatus=unavailable?

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

4) Якщо я втратю ключі, чи можу відновити з raw репліки?

Ви можете відновити структуру набору даних і знімки, але не зможете розшифрувати вміст. Raw репліка не є рішенням для втрати ключів. Ставтеся до ключів як до корони: робіть резерви, контроль доступу і тестування відновлення.

5) Чому мій інкрементальний send величезний, коли зміни невеликі?

Поширені причини: додаток переписує великі файли замість додавання, образ VM має великий churn блоків, невідповідність recordsize підсилює зміни або ви відправляєте ширший діапазон знімків, ніж треба (наприклад, -I включає проміжні знімки з великою кількістю змін).

6) Чи можу я змінювати властивості на приймачі-репліці?

Можете, але обережно: реплікація з -R прагне зберегти властивості з джерела, і повторні receives можуть повертати зміни на приймачі. Якщо потрібні інші властивості на приймачі (mountpoints, квоти), плануйте це явно і тестуйте взаємодію прапорів receive.

7) У чому різниця між прийомом з -u і встановленням canmount=off?

-u запобігає монтуванню під час операції receive. canmount=off — це персистентна властивість, що забороняє монтування взагалі, поки її не змінять. Для vault-реплік я часто роблю і те, й інше: приймаю непремонтованим і утримую такою політикою.

8) Використовувати -i чи -I для інкременталів?

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

9) Як зрозуміти, що приймач випадково не отримує ключі?

Перевіряйте keystatus і keylocation, аудитуйте, хто може виконувати zfs load-key. Також перевіряйте юніти/скрипти завантаження при старті. Обіцянка «ключів тут немає» найчастіше ламається через додану пізніше зручну автоматизацію.

10) Чи повільніший raw send за нормальний send?

Залежить. Raw send може бути ефективним, бо відправляє збережені блоки, але загальна пропускна здатність залежить від всього конвеєра: читання джерела, обробка zfs send, транспорт, запис приймача і топологія пулу. Більший предиктор продуктивності — це зазвичай churn і I/O-характеристики, а не сам прапор raw.

Висновок

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

Операційна дисципліна — ось справжня вартість: гігієна знімків, цілісність ланцюжка, кордони управління ключами і перевірка того, що ви насправді реплікуєте. Робіть це добре — і raw send стане подарунком. Займайтеся цим поверхнево — і ви або зіллєте дані, або в найгірший момент виявите, що ваші «бекапи» — криптографічні експонати.

← Попередня
Семантика синхронізації ZFS через NFS: чому клієнти змінюють надійність записів
Наступна →
Ubuntu 24.04 «Clock skew detected» — виправити синхронізацію часу та зупинити збої збірки/деплою (випадок №46)

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