ZFS для резервних копій: снапшоти + send/receive без сліз

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

Ваша резервна копія не справжня, поки ви її не відновили. І ваша реплікація ZFS не справжня, поки вона не пережила буденні проблеми: ненадійні лінки, заповнені пули, неправильно впорядковані снапшоти та той один співробітник, який «швидко перейменував dataset».

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

Ментальна модель: снапшоти — це час, send/receive — це транспорт

Резервні копії ZFS — це два механізми, скріплені разом:

  • Снапшоти фіксують стан dataset у певний момент часу. Вони дешеві (спочатку), швидкі та консистентні.
  • Send/receive серіалізує дельти снапшотів і переміщує їх кудись ще, щоб ви могли втратити сервер і все одно зберегти роботу.

Усе інше — збереження, іменування, інкрементальна реплікація, resume token-и, шифрування, обмеження пропускної здатності — існує, щоб ці два механізми працювали під навантаженням.

Снапшоти — не копії. Це посилання.

Снапшот ZFS — це лише read-only погляд на блоки. Коли ви робите снапшот dataset, ZFS не дублює дані. Він «запечатує» блоки, які належать до цього моментального вигляду. Коли жива файловa система змінюється, виділяються нові блоки, а старі зберігаються доти, доки хтось на них посилається через снапшот.

Це означає:

  • Створення снапшотів — швидке.
  • Тримати багато снапшотів може бути дорого, якщо ваша робота інтенсивно змінює дані (образи ВМ, бази даних, артефакти CI).
  • Видалення снапшотів може бути повільним, якщо вони посилаються на велику кількість унікальних блоків.

Send/receive детерміноване — ваші політики ні

zfs send генерує потік, що представляє вміст снапшоту (повний) або різниці (інкремент), а zfs receive застосовує цей потік до цільового dataset.

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

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

Жарт №1 (короткий, доречний): снапшоти ZFS — як подорож у часі: легко створити, дорого пояснювати, коли у вас 9 000 з них.

Іменування снапшотів — це не естетика; це ваша plane керування

Визначте заздалегідь схему іменування, яка кодує:

  • хто створив (система чи людина),
  • призначення (hourly/daily/weekly, перед оновленням, перед деплоєм),
  • час (UTC, завжди).

Якщо ви цього не зробите, збереження і реплікація стануть грою в здогадки. Гра в здогадки приємна, поки не приходять аудитори.

Тверда думка: відділяйте «backup snapshots» від «operational snapshots»

Операційні снапшоти (перед оновленням, перед ризиковою міграцією) — чудові. Але змішування їх у ваш ланцюг реплікації без правил зрештою зламає інкрементальні send. Використовуйте окремі префікси.

Приклади префіксів снапшотів:

  • bk-hh / bk-dd / bk-ww для запланованих рівнів бекапу
  • ops- для операційних/ручних снапшотів

Фундаментальне правило: ніколи не тримайте ціль бекапу «гарячою»

Якщо ваш backup pool зайнятий на 85–95%, ви живете в борг. Продуктивність та поведінка ZFS деградують при зменшенні вільного простору, і видалення стає реальною роботою. Ви отримаєте повільні send, повільні receive, повільне видалення снапшотів і врешті-решт прогалини в реплікації, що примусить робити повні send.

Тримайте backup pool нижче ~70–80% у сталому стані. Так, фінанси спитають, чому «викинули» диски. Поясніть, що ви купуєте передбачуваність, а не сирі гігабайти.

Одна цитата (парафраз)

«Надія — не стратегія.» — парафраз ідеї, яку часто приписують лідерам операцій та інженерам надійності

Системи снапшотів та реплікації — це місце, куди йде надія, щоб померти. Добре. Будуйте системи, які її не потребують.

Цікаві факти та невелика історія для роботи

  1. ZFS з’явився у Sun Microsystems як дизайн «файлова система плюс менеджер томів», а не як додатковий інструмент RAID. Саме тому снапшоти та реплікація відчуваються нативно.
  2. Copy-on-write не винайшов ZFS, але ZFS популяризував модель end-to-end, де файлова система, контрольні суми та пул взаємодіють замість того, щоб конфліктувати.
  3. ZFS контролює контрольні суми кожного блоку і перевіряє при читанні; саме тому ZFS так добре підходить для резервних копій. Тиха корупція — ворог, що не попереджає.
  4. RAID-Z існує, бо традиційні RAID-контролери іноді нечесні щодо порядку запису й кешування. ZFS хотів софтварну нативну модель.
  5. Потоки zfs send портативні між платформами, що реалізують OpenZFS, тому реплікація між Linux та системами, похідними від illumos, поширена.
  6. Resumable receive («resume tokens») додали, бо великі реплікації помирали в реальних мережах. Це одне з найпрактичніших еволюцій в ZFS-операціях.
  7. Снапшоти не зупиняють час для додатків, якщо ви не координуєте запис. ZFS дає crash-consistent снапшоти за замовчуванням; application-consistent потребує додаткових кроків.
  8. Dedup існує, але рідко ваш друг на беккап-цілях, якщо ви не знаєте, що робите. Це оптимізація, що з’їдає RAM і має гострі кути.
  9. Компресія зазвичай вигідна для резервних копій: менше байтів по мережі, менше на диску, часто швидше через менше IO. Це одна з тих рідкісних «мати тортик і з’їсти його» функцій.

Спроєктуйте систему резервного копіювання ZFS, що переживе людей

Виберіть топологію реплікації з розумом

Ви опинитесь в одній з цих:

  • One-to-one: продуктивний хост реплікує на backup-хост. Простіше, поширено, добре.
  • Many-to-one: кілька продуктивних хостів реплікують на центральний backup-box. Зручно для операцій; стежте за іменуванням dataset, квотами та плануванням ємності пулу.
  • Fan-out: реплікація на локальний таргет, а потім на offsite-таргет. Так ви отримуєте швидке відновлення та DR.

Рекомендація з позицією: робіть many-to-one лише якщо маєте строгі стандарти іменування та квоти. Інакше одна команда заповнить пул, і всі дізнаються, що «резервні копії впали».

Визначте, що реплікувати: dataset, а не пул

Реплікуйте datasets (та їхні діти) з узгодженими властивостями. Якщо ви реплікуєте весь пул, ви успадкуєте кожну помилку властивостей і кожен експеримент. Datasets — ваш контроль радіусу ураження.

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

Більшість сервісів живуть у дереві: pool/app, pool/app/db, pool/app/logs. Якщо потрібна консистентна точка часу по цьому дереву, робіть снапшот рекурсивно з однаковим ім’ям. ZFS дає zfs snapshot -r, і інструменти реплікації покладаються на це.

Зробіть ретеншн політику — не побічний ефект

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

Виберіть багаторівневу ретеншн політику, що відповідає бізнес-реальності:

  • Hourly для 24–72 годин (швидке відновлення «ой»)
  • Daily для 14–35 днів (більшість інцидентів, коли ми тільки помітили проблему)
  • Weekly для 8–12 тижнів (повільні проблеми)
  • Monthly для 6–18 місяців (compliance-потреби)

Потім реалізуйте це автоматично, тегуючи снапшоти та видаляючи за тегом/префіксом. Не видаляйте снапшоти «з найстаршого першого», не розуміючи holds, клонів та залежностей реплікації.

Тримайте backup datasets тільки для читання (на стороні резервного копіювання)

На цілі встановіть отримані datasets як read-only, щоб запобігти «швидким виправленням», які назавжди розірвуть вашу лінію снапшотів.

Встановіть:

  • readonly=on
  • опційно canmount=off для суто бекап-датасетів

Шифрування: вирішіть, шифрувати в стані спокою, в транспорті чи і там, і там

SSH забезпечує шифрування транспорту. Нативне шифрування ZFS — шифрування даних на диску. Ваш модель загроз вирішує.

  • Якщо ви відправляєте на третю сторону або знімні носії: нативне шифрування важливе.
  • Якщо це всередині вашого захищеного ЦОД: SSH може бути «достатньо», але аудитори можуть не погодитися.

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

Надавайте перевагу інкрементальній реплікації, але плануйте повні send

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

  • створите спільний базовий снапшот (іноді можливо), або
  • зробите повний send (іноді болісно).

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

Практичні завдання (команди + виводи + рішення)

Це завдання, які я реально виконую при побудові або налагодженні реплікації ZFS. Кожне включає команду, типовий вивід і яке рішення з цього випливає.

Завдання 1: Визначити пули та базове здоров’я

cr0x@server:~$ zpool status
  pool: tank
 state: ONLINE
  scan: scrub repaired 0B in 02:11:18 with 0 errors on Sun Dec 22 03:10:42 2025
config:

        NAME        STATE     READ WRITE CKSUM
        tank        ONLINE       0     0     0
          raidz1-0  ONLINE       0     0     0
            sda     ONLINE       0     0     0
            sdb     ONLINE       0     0     0
            sdc     ONLINE       0     0     0

errors: No known data errors

Що це означає: Пул онлайн, без IO-помилок, нещодавній scrub чистий.

Рішення: Якщо ви бачите DEGRADED, checksum-ошибки або невдалі scrubs, виправте стан сховища перед налаштуванням реплікації. Реплікація не обженеться за поганими дисками.

Завдання 2: Перевірити заповнення пулу (тихий вбивця)

cr0x@server:~$ zfs list -o name,used,avail,refer,mountpoint -t filesystem tank
NAME   USED  AVAIL  REFER  MOUNTPOINT
tank  6.12T  1.45T   192K  /tank

Що це означає: Лише 1.45T доступно. В залежності від розміру пулу це може бути небезпечно тісно.

Рішення: Якщо пул понад ~80% використовуєте, почніть планувати зміни ретеншн або розширення ємності. Очікуйте уповільнення видалень снапшотів та receive.

Завдання 3: Переглянути datasets та кількість снапшотів (виявлення runaway ретеншн)

cr0x@server:~$ zfs list -t all -r tank/prod -o name,used,refer,creation | head
NAME                         USED  REFER  CREATION
tank/prod                    820G   96K   Sun Dec  1 10:02 2025
tank/prod@bk-dd-2025-12-01   2.1G   96K   Sun Dec  1 23:00 2025
tank/prod@bk-dd-2025-12-02   2.4G   96K   Mon Dec  2 23:00 2025
tank/prod@bk-dd-2025-12-03   1.9G   96K   Tue Dec  3 23:00 2025

Що це означає: Ви бачите снапшоти та їхній вплив на простір (USED). USED — простір, унікальний для снапшоту, порівняно з живим dataset.

Рішення: Якщо USED снапшота велике і зростає, ваша робоче навантаження сильно змінює дані. Посиліть ретеншн або розділіть високочастотні datasets (наприклад, образи ВМ) в окремі дерева.

Завдання 4: Створити консистентні рекурсивні снапшоти з одним іменем

cr0x@server:~$ zfs snapshot -r tank/prod@bk-hh-2025-12-25T0200Z

Що це означає: Кожен дочірній dataset під tank/prod отримає снапшот з точно таким самим іменем, що дозволяє консистентну реплікацію.

Рішення: Якщо ви не можете зробити рекурсивний снапшот через хаотичне дерево, це структурна проблема. Виправте layout dataset; не «просто снапшотьте те, що важливо» й не надейтесь.

Завдання 5: Перевірити наявність снапшоту по дереву

cr0x@server:~$ zfs list -t snapshot -r tank/prod -o name | grep bk-hh-2025-12-25T0200Z | head
tank/prod@bk-hh-2025-12-25T0200Z
tank/prod/db@bk-hh-2025-12-25T0200Z
tank/prod/web@bk-hh-2025-12-25T0200Z
tank/prod/logs@bk-hh-2025-12-25T0200Z

Що це означає: Снапшот є там, де ви очікували.

Рішення: Якщо будь-який дочірній відсутній, реплікація з -R не поведеться як очікується. Виправте автоматизацію створення снапшотів.

Завдання 6: Зробити першу повну реплікацію (з властивостями) щоб ініціалізувати бекап

cr0x@server:~$ zfs send -R tank/prod@bk-dd-2025-12-25 | ssh backup1 'zfs receive -u backup/prod'

Що це означає: -R включає нащадків та властивості; -u запобігає монтованню при receive.

Рішення: Використовуйте -u для backup-цілей, а монтаж робіть лише під час відновлення. Якщо receive падає, перевірте існування dataset, місце в пулі та права першочергово.

Завдання 7: Інкрементальна реплікація між двома снапшотами

cr0x@server:~$ zfs send -R -i tank/prod@bk-dd-2025-12-24 tank/prod@bk-dd-2025-12-25 | ssh backup1 'zfs receive -u backup/prod'

Що це означає: Відправлено лише зміни від снапшоту 24 до 25 числа.

Рішення: Якщо помилка «incremental source does not exist», ваша лінія снапшотів розійшлася. Не заклеюйте це — знайдіть, що видалено/перейменовано й чому.

Завдання 8: Використовуйте «replication streams» з примусовим rollback (обережно)

cr0x@server:~$ zfs send -R -i tank/prod@bk-dd-2025-12-24 tank/prod@bk-dd-2025-12-25 | ssh backup1 'zfs receive -u -F backup/prod'

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

Рішення: Використовуйте -F тільки на backup-цілях, якщо ви встановили readonly=on і розумієте, що відкидаєте будь-які локальні модифікації (яких не повинно бути).

Завдання 9: Перевірити та встановити read-only на отриманих datasets

cr0x@server:~$ ssh backup1 'zfs get -H -o name,property,value readonly backup/prod'
backup/prod	readonly	off

Що це означає: Цільовий dataset записуваний. Це запрошення до проблем.

Рішення: Увімкніть його:

cr0x@server:~$ ssh backup1 'zfs set readonly=on backup/prod'

Завдання 10: Діагностика «чому мій send повільний» (CPU vs диск vs мережа)

cr0x@server:~$ zfs send -nPv tank/prod@bk-dd-2025-12-25
full send of tank/prod@bk-dd-2025-12-25 estimated size is 812G
size	812G

Що це означає: Режим сухого запуску (-n) з прогресом/verbose дає оцінку. Якщо ви віддаєте 800G по 1Gb лінку, це буде довгий день.

Рішення: Якщо оцінений розмір несподівано великий, перевірте, чи не втрачено базовий інкрементальний снапшот або чи dataset не має масового churn.

Завдання 11: Моніторити прогрес receive і виявляти зависання

cr0x@server:~$ ssh backup1 'zpool iostat -v tank 5 2'
                              capacity     operations     bandwidth
pool                        alloc   free   read  write   read  write
--------------------------  -----  -----  -----  -----  -----  -----
tank                        6.12T  1.45T     12    205   8.1M  112M
  raidz1-0                  6.12T  1.45T     12    205   8.1M  112M
    sda                         -      -      4     68   2.7M  38.0M
    sdb                         -      -      3     69   2.4M  37.1M
    sdc                         -      -      5     68   3.0M  36.9M
--------------------------  -----  -----  -----  -----  -----  -----

Що це означає: Receive записує ~112MB/s у пул. Це здорово для багатьох дискових масивів.

Рішення: Якщо записи падають майже до нуля, але send все ще йде, перевірте мережу, backpressure SSH і чи пул не близький до повного або сильно фрагментований.

Завдання 12: Обробити перерваний receive за допомогою resume token-ів

cr0x@server:~$ ssh backup1 'zfs get -H -o name,property,value receive_resume_token backup/prod'
backup/prod	receive_resume_token	1-fd1b6a8c9d-118-789c...

Що це означає: Receive перервався і залишив resume token.

Рішення: Відновіть його замість початку заново:

cr0x@server:~$ zfs send -t 1-fd1b6a8c9d-118-789c... | ssh backup1 'zfs receive -u backup/prod'

Завдання 13: Підтвердити походження снапшотів на джерелі та цілі (уникнути розбитих інкрементів)

cr0x@server:~$ zfs list -t snapshot -o name -s creation -r tank/prod | tail -5
tank/prod@bk-dd-2025-12-21
tank/prod@bk-dd-2025-12-22
tank/prod@bk-dd-2025-12-23
tank/prod@bk-dd-2025-12-24
tank/prod@bk-dd-2025-12-25
cr0x@server:~$ ssh backup1 'zfs list -t snapshot -o name -s creation -r backup/prod | tail -5'
backup/prod@bk-dd-2025-12-21
backup/prod@bk-dd-2025-12-22
backup/prod@bk-dd-2025-12-23
backup/prod@bk-dd-2025-12-24
backup/prod@bk-dd-2025-12-25

Що це означає: Ціль має ті самі снапшоти. Інкрементали мають працювати.

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

Завдання 14: Перевірити властивості dataset, що впливають на бекапи (compression, recordsize, atime)

cr0x@server:~$ zfs get -o name,property,value -s local,default compression,recordsize,atime tank/prod
NAME       PROPERTY    VALUE
tank/prod  compression zstd
tank/prod  recordsize  128K
tank/prod  atime       off

Що це означає: Розумні дефолтні налаштування для багатьох серверних робочих навантажень: compression увімкнено, atime вимкнено.

Рішення: Якщо compression вимкнено, подумайте про його включення до масштабування реплікації. Якщо recordsize дуже не підходить для навантаження (наприклад, 1M для БД), ви можете посилювати churn і дельти бекапу.

Завдання 15: Перевірити, що можна відновити (монтувати отриманий снапшот в режимі тільки для читання)

cr0x@server:~$ ssh backup1 'zfs clone backup/prod@bk-dd-2025-12-25 backup/restore-test && zfs set readonly=on backup/restore-test && zfs mount backup/restore-test && ls -la /backup/restore-test | head'
total 12
drwxr-xr-x  3 root root  3 Dec 25 02:10 .
drwxr-xr-x  5 root root  5 Dec 25 02:10 ..
drwx------ 12 root root 12 Dec 25 02:00 data

Що це означає: Ви маєте доступ до відновленого вмісту. Клонування швидке, бо CoW.

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

Завдання 16: Знайти великі споживачі простору у снапшотах (що тримає простір закритим)

cr0x@server:~$ zfs list -t snapshot -o name,used -s used -r tank/prod | tail -5
tank/prod@bk-dd-2025-11-29  48.2G
tank/prod@bk-dd-2025-11-30  51.7G
tank/prod@bk-dd-2025-12-01  55.3G
tank/prod@bk-dd-2025-12-02  62.9G
tank/prod@bk-dd-2025-12-03  73.4G

Що це означає: Деякі дні приховують набагато більше унікальних даних. Це часто корелює з подіями у навантаженні (reindex, оновлення шаблонів ВМ, некоректна ротація логів).

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

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

1) Інцидент через хибне припущення: «Снапшоти майже безкоштовні, правда?»

У середній компанії команда використовувала ZFS на хості з дисками для ВМ. Вони пишалися своєю політикою: hourly снапшоти на два тижні, daily на три місяці. Ніхто не запитав, скільки churn у даних; припустили, що CoW — це магія.

Навантаження було переважно Windows VM з частими патчами та CI, що часто перебудовував образи. Churn був жорсткий. Снапшоти не копіювали дані, але вони «прикріплювали» старі блоки зі шаленим темпом, і пул почав «з’їдати себе».

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

Вони спробували агресивно видаляти снапшоти — «найстарші першими» — під час робочого часу. Це погіршило IO, бо видалення снапшотів — реальна робота. Віртуальні машини стали повільними, служба підтримки була не в захваті, і команда з п’ятьма менеджерами питала, чи не можна просто перезавантажити SAN.

Виправлення не було хитрим. Вони зменшили частоту снапшотів для дисків ВМ, винесли високочастотні datasets (CI-артефакти) в окреме дерево з коротшою ретеншн, і ввели цільові значення вільного простору пулу. Також планували видалення снапшотів в години низького завантаження і відстежували USED снапшотів. Припущення змінилося: снапшоти легко створювати, а не дешевко зберігати.

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

Інша організація мала великий backup-сервер і багато схожих datasets. Хтось захопився dedup. У теорії, dedup на цілі може суттєво зменшити витрати, бо «так багато файлів однакові між серверами».

Вони ввімкнули dedup=on на backup-datasets прямо перед підключенням нового парку серверів. Реплікація ще «працювала», і початкові графіки виглядали чудово. Усі посміхалися. Фінанси посміхалися теж — і це тривожний знак.

За кілька тижнів backup-система стала непередбачуваною. Receive були стрибкоподібними. Латентність вибухала при інтенсивному інгесті. Іноді видалення снапшотів пересувалося повільно. Таблиця dedup хотіла RAM, потім ще RAM, потім почала використовувати диск у спосіб, який усе ускладнив. Вони побудували систему, де повільний шлях став звичайним.

Оплутаність була оперативною: відновлення стали повільніші й менш надійні, що суперечить призначенню бекапів. Вони в підсумку перевели нові incoming datasets в non-dedup дерева, планували евакуацію dedup даних і встановили SLO для продуктивності відновлення. Урок: dedup — не безкоштовний ланч; це іпотека.

3) Нудна, але правильна практика, що врятувала день: «Щомісячні тренування відновлення»

Регульований бізнес робив майже образливо нудну річ: раз на місяць вони проводили drill по відновленню. Не на словах. Реальне відновлення у scratch-середовище. Вони перевіряли вміст файлової системи, права доступу та кілька рівнів перевірок додатків.

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

Одного місяця drill провалився. Дані відновилися, але перевірка на рівні додатку показала невідповідність. Виявилось, що снапшоти бази даних були crash-consistent, але не application-consistent. Вони не координувалися з режимом бекапу БД. Ніхто не помітив, бо «ZFS снапшоти консистентні». Так, консистентні — але не application-consistent.

Оскільки це був drill, це стало тікетом, а не інцидентом. Вони оновили процес: використовувати нативні механізми БД (або координоване fsfreeze/backup mode) перед зняттям снапшоту. Коли пізніше стався реальний випадок корупції, відновлення пройшло чисто. Нудна практика окупилася в один день — відмінний ROI, якщо ви любите спати.

Жарт №2 (короткий, доречний): тренування відновлення — як чищення зубів: дратує, поки ви не пропустите і не заплатите кров’ю.

Швидкий план діагностики: знайти вузьке місце швидко

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

Перше: це проблема здоров’я/ємності пулу?

  • Джерельний пул: zpool status чистий? Є checksum-ошибки? Історія scrub нормальна?
  • Цільовий пул: достатньо вільного місця? Не близько до повного? Йде resilver?

Якщо пул деградував або повний, перестаньте звинувачувати мережу. Сховище завжди збирає свою заборгованість.

Друге: чи потік send має очікуваний розмір?

  • Запустіть zfs send -nPv ... щоб оцінити розмір потоку.
  • Якщо інкрементальний розмір величезний, ймовірно ви втратили базовий снапшот або навантаження сильно змінює дані.

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

  • Мережа: чи ви насичуєте лінк? Є перевідправлення? (Використайте звичні мережеві інструменти; на багатьох системах можна переглянути помилки інтерфейсу та пропускну здатність.)
  • Диск: zpool iostat -v 5 показує реальний read/write bandwidth та операції.
  • CPU: компресія/шифрування може бути обмежена CPU. Якщо send сильно компресує або SSH-шифри важкі, ви помітите це.

Четверте: чи застрягли ви на видаленні снапшотів або держаннях (holds)?

  • Видалення снапшотів може блокувати відновлення простору і робити receives невдалими.
  • Holds можуть заважати видаленню і тихо ламати ретеншн.

П’яте: чи перерваний receive залишив resume token?

  • Перевірте receive_resume_token на цільовому dataset.
  • Поновіть з zfs send -t замість пересилання заново.

Швидка діагностика — це виключення категорій. Не налаштовуйте компресію, коли пул на 97% повний. Не додавайте диски, коли базовий снапшот видалено.

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

1) Інкрементальний send падає: «incremental source … does not exist»

Симптоми: Ваш скрипт працював вчора. Сьогодні він помилка під час zfs send -i.

Причина: Снапшот «from» видалено на джерелі або цілі, або lineage dataset розійшлася (локальні зміни на цілі, або отримання в інший шлях dataset).

Виправлення: Порівняйте списки снапшотів з обох сторін; відновіть спільний базовий снапшот. Якщо не можете — робіть повний send (плануйте вплив), потім зміцніть правила ретеншн, щоб зберігати базові снапшоти, поки вони не репліковані.

2) Receives раптово сповільнюються до повзання

Симптоми: Пропускна здатність реплікації падає; zfs receive ледь пише; IO-латентність росте.

Причина: Цільовий пул надто заповнений, сильна фрагментація, йде resilver/scrub, або тиск таблиці dedup. Іноді це також маленькі recordsize, що викликають метадані-чанк.

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

3) «cannot receive: destination has snapshots» / «destination is busy»

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

Причина: Хтось створив або видалив снапшоти на цілі, або ви отримуєте в неправильний шлях dataset.

Виправлення: Встановіть readonly=on і обмежте, хто може адмініструвати backup-pool. Використовуйте zfs receive -F лише якщо впевнені, що безпечно відкотити стан цілі.

4) Ви видаляєте снапшоти, але простір не повертається

Симптоми: Ви знищуєте старі снапшоти, але zfs list показує мало звільненого простору.

Причина: Дані посилаються клонями, hold-ами або іншими снапшотами; також можливо, що живий dataset є основним споживачем простору.

Виправлення: Шукайте клони і hold-и. Видаліть hold-и, якщо доречно. Ідентифікуйте клони і або промотуйте їх, або знищуйте після перевірки, що вони не потрібні.

5) Backup dataset містить «неочікувані» властивості або поведінку монтовання

Симптоми: Отримані datasets монтуються автоматично, або властивості як compression не відповідають очікуванням.

Причина: Використання zfs send/receive з прапорцями реплікації і спадкування властивостей без політики на цільовій стороні.

Виправлення: Приймайте з -u і встановлюйте політики цілі явно: readonly=on, canmount=off, контроль mountpoint-ів. Вирішіть, чи зберігати, чи перевизначати властивості.

6) Шифрована реплікація не вдається або дає непридатні відновлення

Симптоми: Receive завершується, але dataset не монтується; ключі недоступні; відновлення заблоковано.

Причина: Менеджмент ключів не спроєктований. Реплікація перемістила зашифровані datasets, не впевнившись у процедурах завантаження ключів на середовище відновлення.

Виправлення: Документуйте й тестуйте завантаження ключів. Переконайтеся, що runbook відновлення включає отримання ключів та їх перевірку. Проводьте drills, що включають шифрування.

7) «Відновилося, але додаток не працює»

Симптоми: Файли на місці; додаток скаржиться на корупцію/несумісність.

Причина: Crash-consistent снапшоти використані для додатків, які потребують координованих снапшотів (бази даних, деякі поштові системи тощо).

Виправлення: Використовуйте хук-и на рівні додатку: режим бекапу БД, freeze файлової системи де потрібно, або реплікуйте логічні бекапи в ZFS datasets.

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

Покроково: налаштування чистої реплікації з нуля

  1. Створіть layout джерельних datasets, щоб «те, що ви відновлюєте», було деревом dataset, а не випадковими директоріями.
  2. Виберіть іменування снапшотів (UTC, префікс рівня) і запишіть. Люди підуть по стежці, яку ви прокладете.
  3. Увімкніть розумні властивості на джерелі: compression=zstd для більшості навантажень; atime=off.
  4. Зробіть початковий рекурсивний снапшот з базовим ім’ям, який ви триматимете деякий час.
  5. Ініціалізуйте реплікацію повним zfs send -R на backup-ціль з zfs receive -u.
  6. Заблокуйте backup-ціль: встановіть readonly=on, розгляньте canmount=off, обмежте доступ адміністраторів.
  7. Автоматизуйте інкрементальну реплікацію з використанням однакової схеми іменування та явних «from»/«to» снапшотів.
  8. Реалізуйте ретеншн по рівнях; видаляйте снапшоти за префіксом і віком.
  9. Додайте моніторинг: ємність пулу, відставання реплікації (останній реплікований снапшот), статус scrubs та збої receive.
  10. Проводьте drills відновлення щомісяця (принаймні): клон, монтаж, валідація, знищення.

Чек-лист: перед увімкненням «хитрих» функцій

  • Dedup: чи маєте бюджет RAM і тестували найгірший сценарій інгесту та відновлення?
  • Нативне шифрування: чи є управління ключами і чи тестували процедури відновлення?
  • Зміни recordsize: чи розумієте вплив на churn і розмір інкременту?
  • Зміни компресії: чи бенчмаркували ви CPU та перевіряли швидкість реплікації?
  • Кілька цілей реплікації: чи є конвенції іменування та примус квот?

Чек-лист: відновлення під тиском

  • Знайдіть dataset і час снапшоту. Не вгадуйте; перевірте список снапшотів.
  • Клонуйте снапшот у restore-dataset (швидко, мінімальний ризик).
  • Спочатку монтуйте в режимі тільки для читання; перевірте вміст і власника.
  • Для додатків: виконайте recovery/validation кроки специфічні для додатку.
  • Лише потім копіюйте дані назад або промотуйте/перейменуйте за потреби.
  • Документуйте, який снапшот було використано і чому. Майбутній ви спитає про це.

FAQ

1) Чи є снапшоти ZFS «резервними копіями»?

Ні. Снапшоти в тому ж пулі захищають від випадкових видалень та невдалих деплоїв. Вони не захищають від втрати пулу, пожежі, крадіжки чи помилок адміністратора. Реплікуйте їх кудись ще.

2) Чи потрібно робити снапшоти щогодини повсюдно?

Тільки якщо навантаження та ретеншн це виправдовують. Дatasets з високим churn покарають вас. Почніть з hourly для короткого вікна і daily для довшого, потім налаштовуйте по росту USED снапшотів.

3) У чому різниця між crash-consistent і application-consistent снапшотом?

Crash-consistent — як вирубити живлення: файлова система консистентна, але додатки можуть потребувати відновлення. Application-consistent означає, що додаток співпрацював (flush, freeze, режим бекапу), отже відновлення чистіше.

4) Коли слід використовувати zfs receive -F?

На backup-цілі, яка повинна бути точною копією, і лише коли ви впевнені у відкаті цілі до вхідного потоку. Якщо ціль записувана або використовується для інших цілей, -F — потенційна міна.

5) Чому видалення снапшотів іноді триває вічно?

Бо ZFS має звільнити посиланні блоки та оновити метадані. Якщо снапшот посилається на багато унікальних блоків (високий churn) або пул під тиском, видалення може бути повільним. Плануйте видалення в низький сезон і не допускайте, щоб пули були гарячими.

6) Чи можна безпечно реплікувати зашифровані datasets?

Так, але «безпечно» означає наявність управління ключами і відпрацьованих drills. Якщо ключі недоступні під час інциденту, ваші резервні копії — зашифровані паперові гирі.

7) Чи замінює реплікація традиційне backup-пЗ?

Іноді. Реплікація чудова для швидкого відновлення та DR стану файлової системи. Але вам може знадобитися окреме ПО для архівування на довгий термін, відновлення між платформами та application-aware бекапів. Не намагайтеся одним інструментом покрити все.

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

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

9) Чи варто реплікувати весь пул з -R?

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

10) Який найбезпечніший спосіб тестувати відновлення без впливу на продакшн?

На backup-хості клонувати отриманий снапшот у тимчасовий dataset, змонтувати read-only, валідувати, потім знищити клон. Клони дешеві й оборотні.

Висновок: конкретні наступні кроки

Якщо хочете «без сліз», перестаньте ганятись за хитрощами і почніть впроваджувати нудну правильність:

  1. Стандартизовуйте іменування снапшотів (префікс + UTC-таймштамп) і розділяйте backup- та операційні снапшоти.
  2. Ініціалізуйте реплікацію чисто повним zfs send -R, потім робіть інкрементальні лише коли походження снапшотів підтверджено.
  3. Заблокуйте backup-ціль: readonly=on, отримуйте з -u, обмежуйте адміністративний доступ.
  4. Моніторте ємність пулу і тримайте її нижче зони ризику; не експлуатуйте сховище бекапів «гарячим».
  5. Плануйте drills відновлення і трактуйте їхні провали як баги продукту, а не особисті поразки.

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

← Попередня
MySQL vs PostgreSQL: пул підключень — кому потрібно раніше на VPS
Наступна →
Port 25 заблоковано: як усе одно відправляти пошту (без сумнівних хаків)

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