Тестування втрати живлення ZFS: як перевірити безпеку без втрати даних

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

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

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

Що ви насправді тестуєте (і що ні)

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

Ось що ви тестуєте:

  • Кризова консистентність: після раптового відключення пул імпортується чисто й метадані узгоджені.
  • Стійкість синхронних записів: дані, підтверджені як sync, фактично знаходяться на стабільному носії.
  • Поведінка ZIL/SLOG під навантаженням: скільки даних ви втрачаєте в польоті та чи відбувається чисте відтворення.
  • Процес відновлення: як швидко люди можуть повернути сервіс, не ускладнюючи стан речей.
  • Правдивість стеку зберігання: чи виконуються flush, barrier і FUA кінцям у кінці.

Що ви не доводите:

  • Що корупція ніколи не трапиться. Ви зменшуєте ймовірність і покращуєте виявлення.
  • Що асинхронні записи є довговічними. Якщо додаток пише асинхронно, ви тестуєте «найкращі зусилля», а не гарантії.
  • Що RAIDZ — це резервне копіювання. Ні, і ZFS не сперечатиметься з вами з цього питання.

Одна цитата варта того, щоб її прикріпити на монітор. Ідея, яку часто приписують Peter Drucker:
Що вимірюється, тим і керують.
У збереженні даних те, що вимірюють, також починають вірити. Тому вимірюйте правильно.

Факти та контекст, які впливають на рішення

Це не дрібниці. Це причини, чому певні «очевидні» налаштування тихо небезпечні.

  1. ZFS — це copy-on-write (CoW): він ніколи не перезаписує живі блоки на місці, тому після збою консистентність пулу зазвичай відмінна.
  2. ZFS контролює контрольні суми для всього (метадані й дані): він виявляє корупцію навіть коли диск повертає «сміття» з усмішкою.
  3. ZIL існує навіть без SLOG: наміри синхронних транзакцій десь логуються; виділений лог-пристрій лише змінює місце.
  4. SLOG — не кеш запису: він прискорює синхронні записи; не робить асинхронні записи безпечними і не замінює потребу в RAM.
  5. Кеші запису інколи брешуть: деякі диски/SSD мають леткі кеші, які можуть підтверджувати записи до їхнього збереження, якщо PLP не реалізовано.
  6. Barriers і flush — це контракт: Linux + контролер + пристрій мають виконувати semantics cache flush/FUA. Один слабкий ланцюг робить «sync» театром дорогого характеру.
  7. Scrub у ZFS — не fsck: scrub — це перевірка цілісності через контрольні суми і відновлення через надлишковість. Це не загальний інструмент «пофіксувати мені пул».
  8. Баги при відключенні часто пов’язані з таймінгом: один і той самий тест може пройти 99 разів і впасти на сотому, бо баг ховається в невеликому вікні гонки.
  9. Ранній ZFS популяризував end-to-end контрольні суми в операціях: не перший файлосистема з цим, але той, з якою багато SRE-команд познайомилися і відмовилися працювати без неї.

Жарт №1: Інженери зі сховищ не вірять у привидів. Ми віримо в «незрозумілу латентність» і «воно зникло після перезавантаження», що по суті те саме, але з кращими графіками.

Модель загроз: режими відмов, що мають значення

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

1) Збій без обману з боку сховища («хороший» збій)

Ядро зупиняється. Живлення відключається. Пристрої зупиняються миттєво. Після перезавантаження ZFS відтворює логи намірів, відкочує до останнього консистентного TXG
і ви втрачаєте максимум кілька секунд асинхронної роботи. Синхронна робота зберігається.

2) Збій з летким кешем («поганий» збій)

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

3) Збій під час resilver/scrub («стресовий» збій)

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

4) Часткове відключення / brownout («дивний» збій)

Одна шафа знеструмлена, інша — ні. Один блок живлення вижив. SAS-експандери перезапускаються. NVMe лімітує.
Це ті відключення, де логи виглядають як місце злочину і ви дізнаєтесь, чи адекватні multipath та таймаути.

5) Помилки при відновленні людиною («найпоширеніший» збій)

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

Побудуйте лабораторію, яка каже правду

Якщо ви тестуєте на SSD з ноутбука з одним пулом і ввічливим навантаженням, ви тестуєте емоційний комфорт команди, а не систему.
Лабораторія не має бути дорогою, але вона має бути чесною.

Правила для надійного тестового середовища

  • Та ж клас зберігання, що і в продакшені: ті ж моделі SSD/HDD, той же HBA, та та ж сімейство прошивки. «Достатньо близько» — це місце, куди йдуть дані померти.
  • Ті ж ashift і recordsize-політики: не «оптимізуйте» лабораторію іншим розміром блоків і не чекайте однакової поведінки при відмовах.
  • Відтворюване відключення живлення: керований PDU-вихід, реле або вимкнення через IPMI. Тягнути випадковий кабель — це не науковий експеримент.
  • Веде консоль за межами смуги: серійна консоль, IPMI SOL або принаймні персистентні журнали. Ви хочете бачити останні 2 секунди.
  • Таймбоксовані тести: визначте, що означає «пройшов», перш ніж починати. Інакше ви будете тестувати, поки не набридне.

Що вам потрібно відтворити з продакшену

Відтворіть топологію пулу, кількість vdev і чи використовується виділений SLOG. Відтворіть політику sync.
Відтворіть стиснення й atime. І, так, відтворіть ваші найгірші навантаження.

Що не слід відтворювати

Не відтворюйте відсутність моніторингу в продакшені. Лабораторія — місце, де додають додаткову інструментацію.
Ви повинні бачити cadence комітів TXG, активність ZIL, поведінку flush пристроїв і розподіли латентності.

Навантаження та метрики: припиніть «dd» і почніть вимірювати

«Я записав великий файл і все було нормально» — це не тест. Це колискова пісня.
Ваше навантаження має включати синхронні записи, інтенсивні оновлення метаданих, дрібні випадкові IO і стійку пропускну здатність. Також конкуренцію.

Ключові поведінки, які потрібно викликати

  • Тиск на синхронні коміти: бази даних, NFS зі sync, додатки з великою кількістю fsync.
  • Оновлення метаданих: масові створення/видалення файлів, snapshot-и, клонування, зміни властивостей dataset.
  • Активність space map: звільнення, перезаписи та патерни фрагментації.
  • Змішане читання/запис під навантаженням: бо відключення не чекають завершення пакетної роботи.

Метрики, що мають значення під час тестування

  • Розподіл латентності синхронних записів: p50/p95/p99, а не лише середнє.
  • Час коміту TXG: довгі коміти збільшують вікно втрати асинхронних даних і можуть вказувати на проблеми з flush пристроїв.
  • Завантаження ZIL/SLOG: як часто і наскільки активно ви його використовуєте.
  • Помилки контрольної суми та IO: після перезавантаження і після scrub.
  • Час імпорту і час відтворення: оперативний вплив має значення.

Жарт №2: Якщо ваш план тесту втрати живлення — «вискоблити шнур і надіятись», вітаю — ви винайшли chaos engineering, але з меншою кількістю дашбордів.

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

Це перевірки і процедури рівня продакшен, які можна виконати в лабораторії і — обережно — у продакшені для валідації.
Кожне завдання містить: команду, що означає вивід і яке рішення приймається.
Приклади припускають OpenZFS на Linux. Налаштуйте імена пристроїв і пулів під себе.

Завдання 1: Визначити стан і топологію пулу

cr0x@server:~$ sudo zpool status -v tank
  pool: tank
 state: ONLINE
  scan: scrub repaired 0B in 00:12:41 with 0 errors on Tue Dec 24 02:10:12 2025
config:

        NAME                        STATE     READ WRITE CKSUM
        tank                        ONLINE       0     0     0
          raidz2-0                  ONLINE       0     0     0
            ata-WDC_WD80EFZX-68UW8N0  ONLINE       0     0     0
            ata-WDC_WD80EFZX-68UW8N1  ONLINE       0     0     0
            ata-WDC_WD80EFZX-68UW8N2  ONLINE       0     0     0
            ata-WDC_WD80EFZX-68UW8N3  ONLINE       0     0     0
            ata-WDC_WD80EFZX-68UW8N4  ONLINE       0     0     0
            ata-WDC_WD80EFZX-68UW8N5  ONLINE       0     0     0

errors: No known data errors

Що означає вивід: Ви хочете бачити ONLINE, нуль помилок і недавній scrub без ремонтів.

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

Завдання 2: Перевірити політику sync dataset (перевірка «чи ми тихо відмовились від безпеки?»)

cr0x@server:~$ sudo zfs get -o name,property,value -s local,default sync tank
NAME  PROPERTY  VALUE
tank  sync      standard

Що означає вивід: standard поважає запити додатків на sync; disabled обманює додатки; always змушує sync для всіх записів.

Рішення: Для валідації безпеки тимчасово тестуйте з sync=always на dataset(ах), які мають значення, щоб перевірити реальну довговічність.

Завдання 3: Перевірити наявність SLOG і який він

cr0x@server:~$ sudo zpool status tank | sed -n '1,80p'
  pool: tank
 state: ONLINE
config:

        NAME        STATE     READ WRITE CKSUM
        tank        ONLINE       0     0     0
          raidz2-0  ONLINE       0     0     0
            sda     ONLINE       0     0     0
            sdb     ONLINE       0     0     0
            sdc     ONLINE       0     0     0
            sdd     ONLINE       0     0     0
        logs
          nvme0n1p1 ONLINE       0     0     0

Що означає вивід: Розділ logs вказує на окремий пристрій SLOG.

Рішення: Якщо ви покладаєтесь на швидкість sync або NFS sync, перевірте захист SLOG від втрати живлення і латентність.

Завдання 4: Підтвердити ключові властивості dataset, що впливають на поведінку при відмовах

cr0x@server:~$ sudo zfs get -o name,property,value recordsize,compression,atime,logbias,primarycache tank/data
NAME       PROPERTY     VALUE
tank/data  recordsize   128K
tank/data  compression  lz4
tank/data  atime        off
tank/data  logbias      latency
tank/data  primarycache all

Що означає вивід: logbias=latency схильний активніше використовувати SLOG для sync-записів; throughput штовхає більше в основний пул.

Рішення: Для баз даних logbias=latency з правильним PLP SLOG — розумний вибір; інакше ви можете платити податок на латентність даремно.

Завдання 5: Підтвердити політику write cache та ризик «леткого кешу» на SSD/NVMe

cr0x@server:~$ sudo nvme id-ctrl /dev/nvme0n1 | egrep -i 'vwc|oncs|wzsl'
vwc     : 0x1
oncs    : 0x5f
wzsl    : 0x0

Що означає вивід: vwc: 0x1 вказує на наявність леткого кешу запису. Це не автоматично погано — але ставить питання: чи є у диска PLP?

Рішення: Якщо пристрій має леткий кеш і немає PLP, не використовуйте його як SLOG. Ставте під сумнів твердження про стійкість sync, поки не доведете їх.

Завдання 6: Перевірити налаштування write cache SATA-диска (звідси іноді починаються брехні)

cr0x@server:~$ sudo hdparm -W /dev/sda | head -n 2
/dev/sda:
 write-caching =  1 (on)

Що означає вивід: Write caching увімкнено. Багато дисків безпечні; деякі — ні; контролери також можуть втручатися.

Рішення: Якщо ви не можете підтвердити захист від втрати живлення, розгляньте можливість вимкнути write cache для тестів (поступившись продуктивністю) або використайте enterprise-диски з PLP.

Завдання 7: Переконатися, що ZFS бачить ashift і що він адекватний

cr0x@server:~$ sudo zdb -C tank | egrep 'ashift|vdev_tree' | head -n 20
        vdev_tree:
            type: 'root'
            id: 0
            guid: 1234567890123456789
            ashift: 12

Що означає вивід: ashift: 12 означає 4K сектори. Неправильний ashift може спричинити патологічне write amplification і довгі коміти TXG.

Рішення: Якщо ashift неправильний, виправляйте це, перестроївши пул. Не виправдовуйтесь; пул не переймається вашими почуттями.

Завдання 8: Базова латентність IO та черги перед тим, як ламати щось

cr0x@server:~$ iostat -x 1 3
Linux 6.8.0 (server)   12/26/2025  _x86_64_  (16 CPU)

avg-cpu:  %user   %nice %system %iowait  %steal   %idle
           2.31    0.00    1.12    0.45    0.00   96.12

Device            r/s     rkB/s   rrqm/s  %rrqm r_await rareq-sz     w/s     wkB/s   wrqm/s  %wrqm w_await wareq-sz  aqu-sz  %util
sda              0.00      0.00     0.00   0.00    0.00     0.00   12.00   512.00     0.00   0.00    7.20    42.67    0.09   8.40
nvme0n1          0.00      0.00     0.00   0.00    0.00     0.00   80.00 10240.00    0.00   0.00    0.45   128.00    0.04   2.10

Що означає вивід: Слідкуйте за w_await, aqu-sz та %util. SLOG з високим await під час sync-тестів — тривожний знак.

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

Завдання 9: Згенерувати sync-важке навантаження, яке справді викликає fsync

cr0x@server:~$ sudo fio --name=syncwrite --directory=/tank/data/test \
  --rw=randwrite --bs=4k --size=2G --iodepth=1 --numjobs=4 \
  --fsync=1 --direct=1 --time_based --runtime=60 --group_reporting
syncwrite: (groupid=0, jobs=4): err= 0: pid=22310: Fri Dec 26 10:12:41 2025
  write: IOPS=410, BW=1640KiB/s (1679kB/s)(96.1MiB/60001msec)
    clat (usec): min=650, max=42000, avg=2400.12, stdev=1100.55
    lat (usec): min=670, max=42120, avg=2420.88, stdev=1102.10

Що означає вивід: З --fsync=1 і iodepth=1 ви змушуєте часті точки довговічності.

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

Завдання 10: Відстежувати латентність ZFS і статистику черг під час тесту

cr0x@server:~$ sudo zpool iostat -v tank 1 5
              capacity     operations     bandwidth
pool        alloc   free   read  write   read  write
----------  -----  -----  -----  -----  -----  -----
tank        1.20T  5.80T     20    450  2.5M  1.7M
  raidz2-0  1.20T  5.80T     20    210  2.5M  1.2M
    sda         -      -      3     35   420K   220K
    sdb         -      -      3     35   420K   220K
    sdc         -      -      3     35   420K   220K
    sdd         -      -      3     35   420K   220K
logs            -      -      -    240     -   520K
  nvme0n1p1     -      -      -    240     -   520K

Що означає вивід: Якщо під синхронним навантаженням записи накопичуються в logs, ви використовуєте SLOG як задумано. Якщо ні, ваше навантаження може бути не sync, або відрізняються налаштування logbias/sync.

Рішення: Якщо SLOG насичений, очікуйте високу латентність sync. Розгляньте дзеркальний SLOG або кращий пристрій, а не більший пул.

Завдання 11: Підтвердити передзбоєм: зробити snapshot маркера, щоб довести, що вижило

cr0x@server:~$ sudo zfs snapshot -r tank/data@pre_cut_01

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

Рішення: Завжди створюйте snapshot перед відключенням живлення. Це перетворює «я думаю, що це змінилося» на реальний diff.

Завдання 12: Після збою: імпортувати пул безпечно та спостерігати відтворення

cr0x@server:~$ sudo zpool import
   pool: tank
     id: 1234567890123456789
  state: ONLINE
 action: The pool can be imported using its name or numeric identifier.
 config:

        tank        ONLINE
          raidz2-0  ONLINE
            sda     ONLINE
            sdb     ONLINE
            sdc     ONLINE
            sdd     ONLINE
        logs
          nvme0n1p1 ONLINE
cr0x@server:~$ sudo zpool import -o readonly=on -N tank

Що означає вивід: Імпорт в режимі read-only дозволяє інспектувати без негайного запису нового стану.

Рішення: Якщо ви бачите попередження про відсутні пристрої або UNAVAIL, зупиніться і розслідуйте підключення/перезавантаження контролера перед імпортом у режимі читання-запису.

Завдання 13: Перевірити останній відомий transaction group і події в історії

cr0x@server:~$ sudo zpool history -i tank | tail -n 25
2025-12-26.10:14:03 zpool import -o readonly=on -N tank
2025-12-26.10:14:21 zpool export tank
2025-12-26.10:15:10 zpool import tank

Що означає вивід: Ви можете корелювати імпорти/експорти з хронікою тесту. Несподівані експорти/імпорти можуть вказувати на watchdog-і або автоматику, що втручається.

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

Завдання 14: Запустити scrub і інтерпретувати результат

cr0x@server:~$ sudo zpool scrub tank
cr0x@server:~$ sudo zpool status -v tank
  pool: tank
 state: ONLINE
  scan: scrub repaired 0B in 00:16:22 with 0 errors on Fri Dec 26 10:32:18 2025
config:

        NAME        STATE     READ WRITE CKSUM
        tank        ONLINE       0     0     0
          raidz2-0  ONLINE       0     0     0
            sda     ONLINE       0     0     0
            sdb     ONLINE       0     0     0
            sdc     ONLINE       0     0     0
            sdd     ONLINE       0     0     0
        logs
          nvme0n1p1 ONLINE       0     0     0

errors: No known data errors

Що означає вивід: «0 errors» після збою — те, чого ви прагнете. Якщо бачите відремонтовані байти, розслідуйте, чи було це до тесту, чи викликано ним.

Рішення: Будь-які помилки контрольної суми після контрольованого тесту — серйозний сигнал: підозрівайте брехню кешу, некоректний SLOG або проблему контролера.

Завдання 15: Порівняти стан до/після відключення за допомогою snapshot-ів (довести межі втрати даних)

cr0x@server:~$ sudo zfs snapshot -r tank/data@post_cut_01
cr0x@server:~$ sudo zfs diff -FH tank/data@pre_cut_01 tank/data@post_cut_01 | head
M	/tank/data/test/file0001
M	/tank/data/test/file0002
-	/tank/data/test/tmp_8831

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

Рішення: Втрата даних, які були підтверджені fsync — не «очікувана втрата». Це баг або брехня апаратури. Ескалюйте до валідації обладнання.

Завдання 16: Перевірити журнали ядра на предмет скидів контролерів і невдач flush

cr0x@server:~$ sudo journalctl -b -k | egrep -i 'zfs|nvme|sd |scsi|reset|timeout|flush' | tail -n 40
Dec 26 10:15:18 server kernel: nvme nvme0: controller reset occurred
Dec 26 10:15:19 server kernel: sd 0:0:0:0: [sda] Synchronize Cache(10) failed: Result: hostbyte=DID_OK driverbyte=DRIVER_SENSE
Dec 26 10:15:20 server kernel: ZFS: Loaded module v2.2.4-1
Dec 26 10:15:27 server kernel: ZFS: pool tank imported, checkpoint disabled

Що означає вивід: Невдачі синхронізації кешу або скиди контролера навколо збою — це місця, де витікає правда.

Рішення: Якщо flush-и падають, не довіряйте стійкості sync. Оновіть прошивку, змініть режим HBA або замініть пристрої.

Як безпечно відключити живлення (і чого не робити)

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

Бажані методи (найвідтворювані)

  • Керований PDU-вихід: відключити харчування хоста, залишивши мереже та логування цілими в інших місцях.
  • IPMI chassis power off: послідовно, залоговано і зручне для віддаленого керування. Не «чисте», але достатньо для багатьох сценаріїв.
  • Rеле-контрольоване відключення змінного струму: найближче до «реального», при цьому зберігаючи відтворюваність.

Методи, що створюють більше плутанини, ніж інсайтів

  • Витягування випадкових блоків живлення в системах з резервуванням: це тест на відмову PSU, а не тест втрати живлення. Все ж корисно, але називайте це правильно.
  • Натискання кнопки reset з лютою інтервальною імпровізацією: додає людський шум по часу; постмортем перетвориться на суперечки про секунди.
  • Виклик kernel panic як єдиний тест: тестує відновлення ядра, а не втрату живлення. Це інший режим відмов.

Стадіювання відключення: що таке «гарна гігієна»

Запустіть навантаження. Дайте йому досягти стабільного стану. Зробіть snapshot. Збережіть базові метрики. Потім відключіть живлення в визначений момент (наприклад, через 30 секунд від початку sync-навантжування).
Ні про що не повинно бути випадковості. Випадковість — для атакувальників і балансувальників навантаження.

Плейбук швидкої діагностики

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

Перший: чи імпортується пул чисто і що ZFS думає сталося?

  • Запустіть zpool import і zpool status -v після імпорту.
  • Перевірте на відсутні пристрої, suspended pool або помилки контрольної суми.
  • Рішення: Якщо пул DEGRADED або помилки ненульові, розглядайте це як інцидент цілісності даних, а не проблему продуктивності.

Другий: перевірте журнали ядра на скиди, таймаути і невдачі flush

  • Використовуйте фільтри journalctl -b -k для nvme/sd/scsi/reset/timeout/flush.
  • Рішення: Невдачі flush або повторювані скиди вказують на проблеми апаратури/прошивки/контролера. Не налаштовуйте ZFS, щоб «обійти» ці брехні.

Третій: визначте, чи болить синхронна латентність (SLOG або основний пул)

  • Запустіть sync-навантження (fio з fsync) і дивіться zpool iostat -v та iostat -x.
  • Рішення: Якщо пристрій logs гарячий і з великою латентністю — SLOG вузьке місце. Якщо основні vdev гарячі — обмеження на розміщення або диски.

Четвертий: перевірте цілісність через scrub (не гадати)

  • Запустіть zpool scrub, потім моніторте через zpool status.
  • Рішення: Будь-які помилки контрольної суми після збою означають, що ваш ланцюг довговічності порушено. Ескалюйте перед повторним тестуванням.

П’ятий: доведіть межі довговічності на рівні додатку

  • Порівняйте snapshot-и або маркери додатку (transaction ID, позиції WAL, порядкові номера).
  • Рішення: Якщо додаток втратив підтверджені коміти, стек зберігання підтвердив записи, які фактично не збереглися.

Три корпоративні історії з передової

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

Середня компанія перевела критичний внутрішній сервіс на ZFS. Хороший вибір. Вони також використали «швидкий NVMe» для SLOG.
Логіка була проста: NVMe — сучасний, сучасний — надійний, і в специфікації є слова на кшталт «flush».

Їхні NFS-експорти були налаштовані зі sync-семантикою. Команда додатку святкувала: латентність впала, графіки стали кращими,
і всі тихо вирішили, що проблема зі сховищем вирішена назавжди. Потім стався подій в електромережі — короткий, різкий і реальний.
Хости перезавантажились. Пули імпортовані. Здавалось, без очевидних помилок.

Через два дні почались дивні повідомлення: кілька файлів мали старіші версії. Не відсутні. Не явно пошкоджені. Просто… повернулися в часі.
Це помітили інженери, які порівняли згенеровані артефакти з манифестом збірки, який робив fsync при завершенні.
Спочатку команда зберігання підозрювала баг в додатку. Додаткова команда підозрювала зберігання. Всі підозрювали всіх — це нормально.

Прорив стався завдяки нецікавій рядку в логах: періодичні невдачі flush і скиди контролера під час важких sync-сплесків.
«Швидкий NVMe» виявився споживчим пристроєм з летким кешем і без реального захисту від втрати живлення.
Він міг швидко приймати sync-записи, а потім втрачати їх при відключенні. ZFS зробив, що йому наказали. Пристрій — що він хотів.

Вони замінили SLOG на enterprise-пристрій з PLP і повторили тести відключення живлення. Ефект «подорожі в часі» зник.
Урок не в «NVMe — погано». Урок в тому, щоб не робити припущень про довговічність через маркетингові слова «data center» на коробці.

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

Інша організація мала важке навантаження на запис і ненавиділа sync-латентність. Хтось запропонував «практичну» правку:
встановити sync=disabled на dataset, бо «наш додаток у будь-якому разі реплікується».
Це не був злочинець з вусами. Це був добре намірений інженер, що намагався досягти SLO латентності за обмежений бюджет.

Продуктивність зросла драматично. Драматично настільки, що зміна поширилась із одного dataset на декілька.
Вона протрималась кілька кварталів, переживши кілька рівнів рев’ю, бо ніхто не хоче бути тим, хто поверне латентність.
У них був UPS. Резервні PSU. Віра.

Потім прийшло оновлення прошивки сховища і серія перезавантажень хостів. Один хост впав під час сплеску записів.
Реплікація не врятувала, бо потік реплікації також був джерелом з тією ж «sync-disabled» реальністю.
Вони втратили частину підтверджених транзакцій. Не всі, але достатньо, щоб виникли незмиренні невідповідності.

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

Сухий фінал: вони дотримувались SLO латентності, поки не досягли SLO «пояснити фінансам, чому рахунки зникли», яке важче візуалізувати графіками.

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

Третя компанія використовувала ZFS для зберігання VM. Нічого особливого. Дзеркальні vdev, дзеркальний SLOG з PLP і щомісячний scrub.
Вони також мали ритуал: кожного кварталу проводити контрольований тест відключення живлення у staging після циклів патчування.
Це не було захопливо. Ніхто не отримував підвищень за це. Саме так ви знаєте, що це правильна практика.

Одного кварталу, після оновлення ядра, їхній staging-тест відключення викликав затримку імпорту пулу і кілька помилок контрольної суми на scrub.
Не катастрофа, але неприйнятно. Оскільки це було в staging, у них був час. Вони відкотили, бісекували зміни і виявили
взаємодію драйвера/прошивки, що викликала періодичні NCQ/flush аномалії на підмножині SATA SSD під великим sync-навантаженням.

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

Зовнішній світ про це нічого не помітив. Ось у чому суть. «Нудний» квартальний тест перетворив несподівану відмову на рутинне перезавантаження.
Репутація цієї команди була побудована на нічних відсутніх інцидентах — це єдина чесна слава.

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

1) Симптом: sync-навантаження швидкі, але після збою дані відсутні

Корінна причина: леткий кеш запису підтверджував записи без їхнього збереження (немає PLP), або flush/FUA не проходять через шлях контролера.

Виправлення: використайте PLP-здатний SLOG; перевірте, що контролер у режимі IT/HBA; оновіть прошивку; підтвердіть успіх flush у логах; повторіть тест з sync=always.

2) Симптом: пул імпортується, але scrub знаходить помилки контрольної суми після кожного тесту відключення

Корінна причина: пристрій write cache бреше або нестабільне обладнання (скиди контролера, поганий кабель/бекплейн), або відключення викликає часткові записи поза межами того, що надлишковість може виправити.

Виправлення: перевірте journalctl на скиди/таймаути; замініть сумнівні компоненти; вимкніть write cache для порівняння в тесті; перевірте подачу живлення і резервування PSU.

3) Симптом: імпорт зависає довго після збою

Корінна причина: затримки перерахування пристроїв, таймаути multipath або повільний/невідповідальний log-пристрій (проблеми SLOG можуть затримувати replay).

Виправлення: перевірте журнали завантаження ядра на таймаути пристроїв; підтвердіть наявність і здоров’я SLOG; розгляньте видалення несправного log-пристрою (в лабораторії) лише після ретельного аналізу.

4) Симптом: жахлива синхронна латентність, але SLOG виглядає неактивним

Корінна причина: навантаження насправді не sync (немає fsync/O_DSYNC), або dataset sync і logbias не ті, що ви думаєте, або опції NFS експорту відрізняються.

Виправлення: згенеруйте відоме sync-навантження (fio з fsync); перевірте властивості dataset; підтвердіть налаштування NFS; стежте за zpool iostat -v.

5) Симптом: після збою додатки скаржаться, але ZFS показує «No known data errors»

Корінна причина: очікування довговічності на рівні додатку перевищує фактично запитані операції (асинхронні записи, відсутність fsync) або помилка в додатку щодо порядку операцій.

Виправлення: інструментуйте додаток: підтвердіть точки fsync, поведінку WAL або маркери комітів; використайте snapshot-diff навколо відомих маркерів; не звинувачуйте ZFS, поки не доведете, що додаток напряму просив довговічності.

6) Симптом: scrub займає вічність або спричиняє падіння продуктивності після збою

Корінна причина: пул вже майже заповнений, або один повільний пристрій тягне vdev; подія живлення виявила слабкий диск.

Виправлення: ідентифікуйте повільні пристрої через iostat -x і zpool iostat -v; замініть повільні; розгляньте додавання vdev (не «більших дисків»), якщо потрібні IOPS.

7) Симптом: «zpool status» показує помилки запису, але немає помилок контрольної суми

Корінна причина: проблеми на рівні транспорту (кабелі, HBA, експандер) або таймаути пристрою, а не корупція.

Виправлення: перевірте SMART/NVMe логи помилок, повідомлення ядра та кабельні з’єднання; не ганяйтеся за контрольними сумами, коли шина горить.

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

Покроково: безпечний цикл тесту втрати живлення (відтворюваний)

  1. Оберіть цільові dataset(и): тестуйте те, що важливо, а не весь пул за замовчуванням.
  2. Базовий стан пулу: zpool status -v має бути чистим; бажано недавній scrub.
  3. Зафіксуйте конфіг: збережіть zpool get all і zfs get all для релевантних dataset-ів; збережіть виводи з часовими мітками.
  4. Увімкніть збір доказів: переконайтеся в персистентному журналі, віддаленому syslog або захопленні консолі поза смугою.
  5. Створіть маркер: невеликий файл або маркер транзакції додатку записаний з fsync; snapshot @pre_cut.
  6. Запустіть навантаження: використайте fio з fsync для sync-поведінки; опційно паралельно запустіть змішане навантаження.
  7. Спостерігайте стабільний стан: збирайте 60–120 секунд zpool iostat -v і iostat -x.
  8. Відключіть живлення: через PDU/IPMI/rele; зафіксуйте точний час і метод.
  9. Поверніть живлення: завантажте систему; уникайте автоматичного імпорту в режимі read-write, якщо це можливо.
  10. Імпортуйте спочатку в режимі read-only: інспектуйте вивід zpool import; потім імпортуйте нормально, якщо все здорово.
  11. Перевірте маркери: перевірте файли-маркери, різниці snapshot-ів і консистентність на рівні додатку.
  12. Запустіть scrub: виконайте zpool scrub, перевірте нуль помилок.
  13. Документуйте: зафіксуйте пройдено/не пройдено і що змінилося. Якщо не можете це пояснити, ви не протестували.

Чек-лист: умови «не продовжувати»

  • Існуючі помилки контрольної суми перед тестуванням.
  • Невдачі flush або скиди пристроїв в логах ядра під час нормальної роботи.
  • SLOG-пристрій без підтвердженого PLP використують для навантажень, критичних щодо довговічності sync.
  • Пул вже працює на високому заповненні, де результати будуть домінуватися перевантаженням.

Чек-лист: докази, які треба збирати кожного запуску

  • zpool status -v до і після.
  • zfs get для sync/logbias/recordsize/compression для тестованих dataset-ів.
  • zpool iostat -v під час навантаження.
  • Журнали ядра навколо перезавантаження: скиди контролерів, таймаути, невдачі flush.
  • Різниця snapshot-ів навколо відомого маркера.
  • Результат scrub після відновлення.

Питання та відповіді

1) Чи гарантує ZFS нуль втрат даних при відключенні живлення?

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

2) Якщо мій пул імпортується чисто після відключення, чи я в безпеці?

Ви безпечніші, ніж у багатьох файлових системах, але «іміпортовано чисто» ≠ «sync-записи були довговічними».
Вам все одно потрібні маркери на рівні додатку і scrub, щоб валідувати цілісність і межі втрат.

3) Чи потрібен SLOG для безпеки при втраті живлення?

Ні. SLOG головним чином покращує продуктивність синхронних записів. Безпека походить від коректних sync-семантик і чесних пристроїв.
Поганий SLOG може навіть зменшити безпеку, концентруючи sync-записи на пристрої, який брешe під відключення живлення.

4) Чи ставити sync=always скрізь?

Для тестування довговічності і виявлення апаратних брехунів: так, на тестованих dataset-ах. Для продакшену: тільки якщо ваш бюджет на латентність це дозволяє.
Інакше тримайте sync=standard і впевніться, що додатки викликають fsync там, де потрібно.

5) Як дізнатися, чи мій SSD має захист від втрати живлення?

Специфікації від виробника допомагають, але надійна відповідь — тестування плюс пристрої enterprise-класу, відомі своєю PLP.
Якщо ви не можете підтвердити PLP, не використовуйте такий пристрій як SLOG для критичних навантажень.

6) Чи є витягування штекера найкращим тестом?

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

7) У чому різниця між crash-тестом і тестом втрати живлення?

Crash-тест (kernel panic, reboot) зупиняє ОС, але часто зберігає живлення пристроїв, тому кеші можуть встигнути скинутися.
Тест втрати живлення знімає живлення, тож леткі кеші не отримують «гідного виходу». Це різні правди.

8) Чи може UPS замінити тестування втрати живлення?

Ні. UPS зменшує частоту і купує час, але не вирішує баги прошивки, брехню flush або часткові події живлення.
До того ж: батареї старіють, і вікна техобслуговування мають властивість «виявлятися».

9) Чи поводяться RAIDZ і дзеркала по-різному при втраті живлення?

CoW консистентність залишається, але експлуатаційно дзеркала зазвичай відновлюються швидше і дають кращі IOPS, що може зменшити
час відновлення і вплив scrub. RAIDZ може бути цілком безпечним; він також може бути повільнішим під навантаженням.

10) Якщо я бачу помилки контрольної суми після відключення, чи моя data назавжди пошкоджена?

Не обов’язково. За наявності надлишковості ZFS часто може відновити дані. Але помилки контрольної суми після контрольованого тесту — гучний тривожний сигнал.
Трактуйте це як вказівку, що ваш ланцюг довговічності порушено, і виправте корінну причину перед тим, як довіряти системі.

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

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

Наступні кроки, які дійсно змінюють ситуацію:

  • Підніміть лабораторію, що відповідає класу і топології сховища продакшену.
  • Запустіть скриптований цикл тесту з sync=always на цільових dataset-ах і реальним fsync-навантженням.
  • Відключайте живлення відтворювано, імпортуйте спочатку в режимі read-only, потім валідуйте через snapshot-diff і scrub.
  • Якщо використовуєте SLOG — тримайте його як компонент довговічності: PLP-спроможний, під моніторингом і протестований.
  • Перетворіть результати в runbook: процедура імпорту, перевірки логів, валідація цілісності і критерії «зупинити роботу».

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

← Попередня
Неприємності з рідким металом: апгрейд, що перетворюється на рахунок за ремонт
Наступна →
Intel XeSS: як Intel приєднався до боротьби через програмне забезпечення

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