Шифрування ZFS: Надійний захист без втрат продуктивності

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

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

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

Що таке шифрування ZFS (і чого воно не робить)

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

Що воно робить

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

Чого воно не робить

Воно не шифрує весь пул. Деякі метадані на рівні пулу залишаються видимими (ім’я пулу, топологія vdev, частина інформації про розподіл). Зазвичай це нормально — якщо хтось має ваші диски, у вас вже серйозніші проблеми, ніж те, що вони дізналися, що ви використовували raidz2 — але це має значення для моделювання загроз.

Воно не замінює управління доступом. Якщо атакуючий має root на запущеному хості з відкритим датасетом, шифрування здебільшого театр. Шифрування захищає дані в стані спокою, а не скомпрометовані машини. Якщо хтось може запустити zfs send як root, їм не доведеться ламати AES; вони просто ввічливо вивезуть дані.

Це не вирок продуктивності. Але воно може ним стати, якщо ви поєднаєте його з дрібними блоками, синхронними записами, слабким вибором CPU і переконанням, що «стиснення — необов’язкове». Стек зберігання не карає вас за шифрування; він карає вас за те, що ви вважаєте шифрування єдиною дією.

Жарт №1: Шифрування як ремінь безпеки — дратує, поки не врятує, але все одно не варто навмисно в’їжджати у стіну.

Кілька фактів і історія, що мають значення

Кілька коротких контекстних пунктів, які допоможуть приймати кращі рішення:

  1. ZFS народився в Sun з підходом «зберігання — це система, а не купа дисків»; сучасна екосистема OpenZFS зберегла цю дисципліну, навіть коли реалізації розділялися й об’єднувалися.
  2. Рідне шифрування ZFS з’явилося пізніше, ніж очікували, бо зробити це «по‑ZFS‑івськи» означає зберегти семантику знімків, поведінку send/receive і консистентність на диску.
  3. Шифрування ZFS — на рівні датасету, а не на рівні пулу. Це дозволяє поступове впровадження і полегшує міграції.
  4. Шифрування й стиснення добре поєднуються у ZFS, бо стиснення відбувається до шифрування — стискати шифртекст марно.
  5. AES-GCM часто зустрічається в сучасних конфігураціях ZFS, оскільки це автентифіковане шифрування (конфіденційність + цілісність) з гарною апаратною прискореністю на більшості серверних CPU.
  6. ZFS send може передавати сирі зашифровані потоки (де це підтримується), тому приймач може зберігати зашифровані блоки, ніколи не бачачи відкритого тексту — це важливо для доменів резервного копіювання.
  7. Recordsize і форма робочого навантаження важать більше, ніж «накладні витрати шифрування» для багатьох реальних систем; випадковий ввід/вивід і синхронні записи домінують задовго до AES.
  8. Керування ключами — це реальний ризик для надійності: не тому, що криптографія складна, а тому, що люди забувають паролі, погано проводять ротацію ключів або проєктують розблокування при завантаженні як післядумку.

Модель загроз: що ви реально захищаєте

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

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

Рідне шифрування ZFS дуже добре підходить для «дані в безпеці, якщо диски пішли гуляти». Воно менш корисне, якщо «хтось отримав root на машині». Для цього потрібні загартування системи, принцип найменших привілеїв та моніторинг. Шифрування — шар захисту, а не аура.

Модель продуктивності: куди йдуть цикли

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

1) Цикли CPU (але часто не там, де ви думаєте)

На сучасних x86 серверах з AES‑NI (або еквівалентним прискоренням) шифрування AES‑GCM зазвичай не є вузьким місцем для послідовних навантажень. Де ви його відчуєте:

  • Дуже високе IOPS з малими блоками (інтенсивні метадані, випадковий ввід/вивід).
  • Системи, які вже обмежені CPU (стиснення, контрольні суми, дедуп, інтенсивні RAIDZ обчислення, SMB підписування тощо).
  • Віртуалізовані середовища, де «steal» CPU стає мовним саботажником.

2) Посилення I/O через невідповідний recordsize

Шифрування не змінює ваш recordsize, але підвищує ставки. Якщо ви запускаєте бази даних на датасеті з величезним recordsize, ви вже генеруєте read-modify-write. Додайте синхронні записи — і раптом усі думають «це зробило шифрування». Ні — це зробила стратегія блоків.

3) Синхронні записи та історія ZIL/SLOG

ZFS дотримується семантики sync. Якщо ваше навантаження виконує синхронні записи (бази даних, NFS, деякі шаблони зберігання VM), латентність домінує в шляху логування. Накладні витрати шифрування на основному шляху даних відходять на другий план, якщо ваш SLOG повільний, неправильно налаштований або відсутній.

4) Завантаження ключів і оркестрація монтування

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

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

Проєктування зашифрованих датасетів без жалю

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

Шифруйте на межах датасетів, які відповідають межам довіри

Приклади хороших меж:

  • Датасети на додаток: pool/app1, pool/app2
  • Датасети для кожного орендаря у мульти‑тенантному сховищі
  • Окремий датасет для бекапів/реплік (часто з іншим керуванням ключами)
  • Датасет для «холодних архівів» з іншими властивостями продуктивності

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

Вибирайте властивості шифрування свідомо

Вбудоване шифрування OpenZFS налаштовується під час створення датасету і наслідується. Головні параметри:

  • encryption: алгоритм/режим (звично aes-256-gcm)
  • keyformat: passphrase або raw
  • keylocation: де отримати ключ (prompt, файл тощо)

У продакшні реальне рішення не «AES-256 vs AES-128». Це: чи потрібна вам людська фраза пароля (добре для ручного розблокування, ризиковано для автоматизації) або сирий файл ключа (добре для автоматизації, вимагає сильної безпеки ОС і розповсюдження секретів)?

Стиснення — ваш друг, не ворог

Якщо ви шифруєте, майже завжди слід вмикати стиснення (зазвичай lz4). Воно зменшує дисковий I/O, зменшує трафік реплікації і часто покращує кінцеву продуктивність. Стиснення економить більше часу, ніж коштує шифрування у багатьох навантаженнях. Єдиний випадок, коли я систематично відключаю стиснення — це коли дані вже стиснені і CPU дійсно є вузьким місцем — а це трапляється рідше, ніж люди вважають.

Не плутайте шифрування з контрольними сумами та цілісністю

Контрольні суми ZFS виявляють корупцію; шифрування запобігає несанкціонованому читанню. З AES‑GCM ви також отримуєте автентифікацію, що допомагає виявляти підробки. Але контрольні суми ZFS все ще роблять реальну роботу, особливо при ненадійному обладнанні, контролерах або проблемах з RAM. Не вимикайте контрольні суми (і не намагайтесь; ZFS не дозволить це зробити так, як ви могли б сподіватися).

Керування ключами, яке працює о 3-й ранку

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

Надавайте перевагу невеликій кількості «класів» ключів

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

  • Один ключ на додаток або межу орендаря
  • Окремий ключ для бекапів/цілей реплікації
  • Окремий ключ для «спільної інфраструктури» (логи, конфіги), якщо вони містять секрети

Вирішіть, як відбувається розблокування

Поширені схеми:

  • Ручне розблокування після завантаження для чутливих датасетів (оператор вводить фразу пароля). Добре для моделі «вкрадений сервер»; відновлення повільніше.
  • Автоматичне розблокування через файл ключа збережений на хості (захищений механізмами ОС, TPM або обмеженим доступом). Швидше відновлення; підвищений ризик, якщо хост скомпрометовано.
  • Розділене розблокування: інфраструктурні датасети розблоковуються автоматично; «коронні» датасети вимагають ручного розблокування.

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

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

Наступні завдання припускають OpenZFS на Linux зі стандартними утилітами. Підлаштуйте шляхи й управління сервісами під ваше середовище. Команди показано як реальна shell-сесія; виводи репрезентативні.

Завдання 1: Перевірити, що зашифровано, а що ні

cr0x@server:~$ zfs list -o name,encryption,keylocation,keystatus,mounted -r tank
NAME                 ENCRYPTION        KEYLOCATION         KEYSTATUS  MOUNTED
tank                 off               none                -          yes
tank/apps             aes-256-gcm      file:///etc/zfs/keys/apps.key  available yes
tank/apps/db          aes-256-gcm      inherit             available yes
tank/backups          aes-256-gcm      prompt              unavailable no

Інтерпретація: tank/apps зашифрований і використовує файл ключа; дочірні наслідують. tank/backups потребує інтерактивного розблокування і наразі недоступний, тому не змонтований.

Завдання 2: Створити зашифрований датасет з розумними налаштуваннями

cr0x@server:~$ sudo install -d -m 0700 /etc/zfs/keys
cr0x@server:~$ sudo dd if=/dev/urandom of=/etc/zfs/keys/app1.key bs=32 count=1 status=none
cr0x@server:~$ sudo chmod 0400 /etc/zfs/keys/app1.key

cr0x@server:~$ sudo zfs create \
  -o encryption=aes-256-gcm \
  -o keyformat=raw \
  -o keylocation=file:///etc/zfs/keys/app1.key \
  -o compression=lz4 \
  -o atime=off \
  tank/app1

Інтерпретація: Сирий ключ + файл ключа зручні для автоматизації. compression=lz4 та atime=off — звичні продакшн‑дефолти для багатьох навантажень.

Завдання 3: Створити дочірній датасет для бази даних з налаштованим recordsize

cr0x@server:~$ sudo zfs create -o recordsize=16K -o logbias=latency tank/app1/pgdata
cr0x@server:~$ zfs get -o name,property,value encryption,recordsize,logbias tank/app1/pgdata
NAME              PROPERTY    VALUE
tank/app1/pgdata  encryption  aes-256-gcm
tank/app1/pgdata  recordsize  16K
tank/app1/pgdata  logbias     latency

Інтерпретація: Дочірній датасет наслідує шифрування, але ви налаштували recordsize для навантаження типу база даних і сказали ZFS оптимізувати для синхронної затримки.

Завдання 4: Завантажити ключ і змонтувати зашифрований датасет

cr0x@server:~$ sudo zfs load-key tank/backups
Enter passphrase for 'tank/backups': 
cr0x@server:~$ sudo zfs mount tank/backups
cr0x@server:~$ zfs get -o name,property,value keystatus,mounted tank/backups
NAME         PROPERTY  VALUE
tank/backups keystatus available
tank/backups mounted   yes

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

Завдання 5: Вивантажити ключ (і що це насправді робить)

cr0x@server:~$ sudo zfs unmount tank/backups
cr0x@server:~$ sudo zfs unload-key tank/backups
cr0x@server:~$ zfs get -o name,property,value keystatus,mounted tank/backups
NAME         PROPERTY  VALUE
tank/backups keystatus unavailable
tank/backups mounted   no

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

Завдання 6: Підтвердити, що реплікація може залишатися зашифрованою end-to-end

cr0x@server:~$ sudo zfs snapshot -r tank/app1@replica-test
cr0x@server:~$ zfs get -H -o value encryption tank/app1
aes-256-gcm

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

Завдання 7: Оцінили вплив стиснення та пропускної здатності запису

cr0x@server:~$ zfs get -o name,property,value compressratio,logicalused,used -r tank/app1
NAME           PROPERTY      VALUE
tank/app1      compressratio 1.62x
tank/app1      logicalused   48.3G
tank/app1      used          29.8G
tank/app1/pgdata compressratio 1.08x
tank/app1/pgdata logicalused 310G
tank/app1/pgdata used        287G

Інтерпретація: Дані додатка добре стискаються; база даних менше. Це важливо, бо економія за рахунок стиснення часто компенсує накладні витрати шифрування, зменшуючи фізичний I/O.

Завдання 8: Перевірити, чи ви обмежені CPU чи I/O під час навантаження

cr0x@server:~$ mpstat -P ALL 1 5
Linux 6.8.0 (server)  12/25/2025  _x86_64_  (16 CPU)

12:01:10 PM  CPU  %usr %nice %sys %iowait %steal %idle
12:01:11 PM  all  22.1  0.0   7.4    0.6    0.0  69.9
12:01:12 PM  all  78.5  0.0  12.0    0.3    0.0   9.2

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

Завдання 9: Спостерігати за I/O поведінкою ZFS у реальному часі

cr0x@server:~$ sudo zpool iostat -v tank 1 5
              capacity     operations     bandwidth
pool        alloc   free   read  write   read  write
----------  -----  -----  -----  -----  -----  -----
tank        3.21T  6.78T  1.25K  2.10K   210M  355M
  raidz2    3.21T  6.78T  1.25K  2.10K   210M  355M
    sda         -      -    150    260  26.0M  44.3M
    sdb         -      -    155    265  26.5M  45.0M
    ...

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

Завдання 10: Перевірити флаги функцій і сумісність (перевірка реплікації)

cr0x@server:~$ zpool get all tank | egrep 'feature@|ashift'
tank  ashift                      12                     local
tank  feature@encryption          active                 local
tank  feature@edonr               active                 local

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

Завдання 11: Підтвердити успадкування ключів датасетами та уникнути сюрпризів

cr0x@server:~$ zfs get -r -o name,property,value,keylocation,encryption keylocation,encryption tank/app1
NAME            PROPERTY    VALUE          SOURCE
tank/app1       encryption  aes-256-gcm    local
tank/app1       keylocation file:///etc/zfs/keys/app1.key local
tank/app1/pgdata encryption aes-256-gcm    inherited from tank/app1
tank/app1/pgdata keylocation file:///etc/zfs/keys/app1.key inherited from tank/app1

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

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

Тут команди нервуються — і мають. Потрібно спланувати, знімкувати і валідувати.

cr0x@server:~$ sudo dd if=/dev/urandom of=/etc/zfs/keys/app1-new.key bs=32 count=1 status=none
cr0x@server:~$ sudo chmod 0400 /etc/zfs/keys/app1-new.key

cr0x@server:~$ sudo zfs snapshot -r tank/app1@before-key-rotate
cr0x@server:~$ sudo zfs change-key -o keylocation=file:///etc/zfs/keys/app1-new.key tank/app1
cr0x@server:~$ zfs get -o name,property,value keylocation tank/app1
NAME      PROPERTY     VALUE
tank/app1 keylocation  file:///etc/zfs/keys/app1-new.key

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

Завдання 13: Виміряти вплив шифрування контрольованим тестом запису

cr0x@server:~$ sudo zfs create -o encryption=off -o compression=off tank/test-plain
cr0x@server:~$ sudo zfs create -o encryption=aes-256-gcm -o keyformat=raw -o keylocation=file:///etc/zfs/keys/app1.key -o compression=off tank/test-enc

cr0x@server:~$ sync
cr0x@server:~$ dd if=/dev/zero of=/tank/test-plain/blob bs=1M count=4096 oflag=direct status=progress
4294967296 bytes (4.3 GB, 4.0 GiB) copied, 4.8 s, 895 MB/s

cr0x@server:~$ dd if=/dev/zero of=/tank/test-enc/blob bs=1M count=4096 oflag=direct status=progress
4294967296 bytes (4.3 GB, 4.0 GiB) copied, 5.1 s, 842 MB/s

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

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

cr0x@server:~$ ls -l /etc/zfs/keys/app1.key
-r-------- 1 root root 32 Dec 25 11:58 /etc/zfs/keys/app1.key

Інтерпретація: Якщо цей файл читається не‑root користувачами, ви перетворили «шифрування даних у спокої» в «шифрування з печивами». Закрийте доступ.

Три міні‑історії з корпоративного життя

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

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

Потім відбувся плановий оновлення ядра. Перезавантаження. Хост повернувся, моніторинг показав, що ОС в порядку, SSH працював, а середнє навантаження дивно спокійне. Але додаток був вимкнений. Точка монтування існувала, порожня і весела, і додаток послухово створив нове дерево директорій у кореневій файловій системі. Це була одна з тих відмов, яка не виглядає як відмова, поки ви не помітите, що ваша база даних стала раптово 200 МБ і нова.

Причина не в хитрощах ZFS. Причина — граф сервісів. Зашифрований датасет вимагав zfs load-key перед монтуванням; ключ було налаштовано на prompt, і нікого не було, хто б його ввів. Система завантажилась «успішно», просто без даних. Додаток не впав відразу, бо шлях монтування існував. Воно писало в неправильне місце і ускладнило відновлення.

Виправлення було нудним і ефективним: вони зробили монтування датасету жорсткою залежністю, додали перевірку під час завантаження, яка відмовляла запуск додатка, якщо датасет не змонтований, і змінили обробку ключів для цього датасету відповідно до реальності (або ручне розблокування з чітким кроком для on‑call, або автоматичне розблокування з жорстким контролем хоста). Вони також додали запобіжник: невеликий файл на датасеті, який додаток перевіряє при старті. Якщо його немає — відмовляється запускатись.

Урок: шифрування рідко першим ламає продуктивність. Воно перше ламає припущення.

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

Інша команда вирішила «оптимізувати» накладні витрати шифрування, вимкнувши стиснення — з аргументом, що стиснення спалює CPU, а шифрування спалює CPU, тому відключивши стиснення вони заощадять цикли. На слайді звучало красиво.

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

А потім стало ще гірше: команда намагалася компенсувати, збільшуючи recordsize всюди, щоб «зменшити накладні витрати». Це допомогло для великих послідовних записів, але покарало випадкові оновлення і метадані. Декілька сервісів, які були чутливі до хвостової латентності (невелика OLTP база і черга), почали тайм-аутитись під навантаженням. Рев’ю інциденту було жорстким, бо зміна була зроблена під гаслом «безпеки», тож ніхто не хотів її ставити під сумнів, поки продакшн не покарав.

Відновлення — класичне: вони повернули compression=lz4, налаштували recordsize по датасетах і перестали трактувати «накладні витрати CPU» як одну купу. Шифрування не було лиходієм; вимірювання і невимірене налаштування були.

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

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

Одного дня полиця зі сховищем зазнала відмови контролера, яка потребувала відправки деталей і тимчасового переміщення робочих навантажень. Команда вирішила переключитись на резервний хост. На резерві були вже репліковані знімки, але його ніколи не використовували «по‑справжньому». Саме там більшість DR‑планів вмирають.

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

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

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

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

По‑перше: підтвердити, що змінилося (і ізолювати змінні)

  1. Перевірте статус шифрування й властивості на уражених датасетах: алгоритм, стиснення, recordsize, sync, logbias.
  2. Підтвердіть, що ключі завантажені і датасети змонтовані (проблеми з доступністю часто маскуються під «продуктивність»).
  3. Перевірте, чи не змінилося навантаження: нова версія додатка, інший характер I/O, інший графік реплікації.
cr0x@server:~$ zfs get -o name,property,value -r encryption,compression,recordsize,sync,logbias tank/app1
NAME              PROPERTY     VALUE
tank/app1          encryption   aes-256-gcm
tank/app1          compression  lz4
tank/app1          recordsize   128K
tank/app1          sync         standard
tank/app1          logbias      latency
tank/app1/pgdata   encryption   aes-256-gcm
tank/app1/pgdata   compression  lz4
tank/app1/pgdata   recordsize   16K
tank/app1/pgdata   sync         standard
tank/app1/pgdata   logbias      latency

По‑друге: вирішити CPU‑bound чи I/O‑bound

  1. Подивіться на використання CPU і iowait під час уповільнення.
  2. Якщо CPU високий і iowait низький: ви обмежені обчисленнями (шифрування могло б додати, але так само стиснення/контрольні суми/RAIDZ/додаток).
  3. Якщо iowait високий: вузьке місце — латентність сховища; перевірте SLOG, стан vdev, фрагментацію, глибину черги і синхронні навантаження.
cr0x@server:~$ vmstat 1 5
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 3  0      0 821220  88048 7340120   0    0   512  1024  980 2200 22  8 69  1  0
 9  2      0 780112  88120 7310040   0    0  4096  8192 1400 3400 55 15 10 20  0

По‑третє: перевірити поведінку пулу ZFS і підказки по латентності

  1. zpool iostat -v — щоб побачити, чи диски насичені або нерівномірні.
  2. zpool status — щоб виключити resilver, помилки контрольних сум чи деградовані vdev.
  3. Якщо навантаження синхронне: перевірте SLOG і його характеристики латентності.
cr0x@server:~$ sudo zpool status -x
all pools are healthy

По‑четверте: валідувати шлях робочого навантаження (sync, малі записи, метадані)

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

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

Помилка 1: Шифрування «всього» без меж датасетів

Симптом: Ротація ключів стає жахливою; реплікація та відновлення ламкі; розслідування — «який ключ що відкриває?»

Виправлення: Рефакторити в пер‑додаток/орендар датасети. Використовуйте успадкування, щоб зменшити відхилення конфігурації. Документуйте, які датасети ділять ключі і чому.

Помилка 2: Припущення, що зашифровані датасети автоматично монтуються після перезавантаження

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

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

Помилка 3: Вимкнення стиснення, щоб «зберегти CPU для шифрування»

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

Виправлення: Увімкніть compression=lz4 і виміряйте. Якщо CPU справді вузьке місце, масштабируйте CPU або налаштуйте навантаження; не міняйте I/O ампліфікацію заради теоретичної економії CPU.

Помилка 4: Трактування recordsize як універсальної ручки

Симптом: Бази даних тайм‑аутяться після «оптимізації», або VM‑зберігання стає рваним; посилюється write amplification.

Виправлення: Встановлюйте recordsize по датасету відповідно до робочого навантаження. Тримайте великий recordsize для послідовних даних; зменшуйте для випадкових оновлень.

Помилка 5: Використання фраз пароля для безлюдних серверів без плану

Симптом: Перезавантаження вимагає доступу до консолі; DR‑фейловер застопорився; on‑call шукає ту одну людину, яка «знає фразу пароля».

Виправлення: Або зобов’язуйтесь до ручного розблокування з чіткими процедурами і персоналом, або використовуйте сирі ключі з контрольованим розповсюдженням і суворим захистом ОС. Гібридний підхід поширений: авто‑розблокування для некритичних датасетів, ручне — для коронних.

Помилка 6: Неправильне розуміння семантики реплікації зі шифруванням

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

Виправлення: Тестуйте режими send/receive в лабораторії з тими ж версіями та фічами, що й продакшн. Підтвердіть властивості приймача та наявність ключів. Майте процес ескроу ключів, який відповідає вимогам комплаєнсу.

Помилка 7: Залишення файлів ключів читаємими або їх звичайне бекапування

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

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

Контрольні списки / покроковий план

Чек‑лист A: Безпечне розгортання шифрування ZFS (greenfield або ретрофіт)

  1. Визначте модель загроз: викрадені диски, викрадені хости, компрометація домену бекапів тощо.
  2. Обирайте межі датасетів: per app/tenant, бекапи окремо, архіви окремо.
  3. Виберіть стратегію ключів: сирі файли для автоматизації vs фрази паролів для ручного розблокування; вирішуйте по класах датасетів.
  4. Встановіть базові властивості: compression=lz4, atime=off, recordsize відповідно до навантаження, sync/logbias за потреби.
  5. Створіть датасети і мігруйте дані з планом відкату (знімки до і після).
  6. Оновіть порядок завантаження та сервісів: ключі завантажуються, потім монтування, потім служби. Додайте захисні перевірки.
  7. Протестуйте реплікацію: як рутинні процеси, так і відновлення, включно з наявністю ключів у DR.
  8. Тест навантаження: контрольовані тести плюс канарка з реальним навантаженням.
  9. Документуйте і репетируйте: ротація ключів та відновлення мають бути відпрацьовані, а не лише описані.

Чек‑лист B: Послідовність налаштування продуктивності (не налаштовуйте сліпо)

  1. Виміряйте CPU vs I/O під час періоду уповільнення (mpstat/vmstat + zpool iostat).
  2. Підтвердіть, що стиснення увімкнено, якщо немає доказів, що воно шкодить.
  3. Переконайтесь, що recordsize відповідає шаблонам навантаження.
  4. Перевірте шлях синхронних записів і придатність SLOG, якщо застосовно.
  5. Підтвердіть стан пулу і виключіть фонові операції (resilver/scrub).
  6. Лише потім розглядайте «накладні витрати шифрування» як основну причину — і якщо так, перевірте CPU‑можливості та обмеження віртуалізації.

Чек‑лист C: Дриль по ротації ключів (версія, що не зіпсує вікенд)

  1. Знімкуйте релевантні датасети (@before-key-rotate).
  2. Згенеруйте і виставте права на новий матеріал ключа.
  3. Змініть ключ на некритичному датасеті спочатку (канарка), потім продовжуйте.
  4. Перезавантажте резервний хост або протестуйте шлях монтування/розблокування, щоб упевнитися, що автоматизація працює.
  5. Підтвердіть реплікацію і відновлення з новим ключем.
  6. Виведіть з обігу старі ключі лише після доведення відновлення для знімків, що на них покладаються (якщо це стосується вашого процесу).

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

1) Чи є рідне шифрування ZFS «шифруванням всього диска»?

Ні. Це шифрування на рівні датасету. Деякі метадані на рівні пулу залишаються видимими. Якщо вам потрібно «усе, включно зі swap і завантаженням», ви можете комбінувати стратегії (наприклад, шифрування ОС для кореневого розділу плюс шифрування датасетів ZFS для даних).

2) Використовувати шифрування ZFS чи LUKS?

Вони вирішують різні операційні проблеми. LUKS шифрує блочні пристрої (проста межа, широка підтримка ОС). Рідне шифрування ZFS шифрує датасети (гранулярні межі, враховує знімки/реплікацію). Якщо вам потрібні ключі на рівні датасетів і семантика зашифрованої реплікації, рідне шифрування ZFS — інструмент. Якщо потрібна модель «розблокував диск і все готово», LUKS може бути простішим.

3) Чи ламає шифрування стиснення?

Ні — ZFS стискає перед шифруванням. Стиснення залишається ефективним і часто є різницею між «шифрування проходитиме» і «чому у нас закінчилися IOPS?»

4) Чи сповільнить шифрування мою базу даних?

Може, але частіше більшими факторами є латентність синхронних записів, невідповідний recordsize і дизайн пулу. Якщо ви вже працюєте близько до меж CPU, шифрування може «дістати» вас через ці межі. Вимірюйте CPU vs iowait і налаштовуйте властивості датасету для бази даних.

5) Чи можу я реплікувати зашифровані датасети, не розкриваючи plaintext на сервері бекапу?

У багатьох OpenZFS налаштуваннях — так: існують робочі процеси send/receive для сирих зашифрованих потоків, де приймач зберігає зашифровані блоки без потреби в ключах. Ви маєте перевірити підтримку функцій і тести відновлення. Не припускайте, що ваші конкретні версії поводяться однаково.

6) Що станеться, якщо я втратю ключ?

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

7) Чи повинні ключі жити на тому ж хості, що й дані?

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

8) Чи можу я зашифрувати існуючий датасет на місці?

Не як просте перемикання властивості. На практиці команди створюють новий зашифрований датасет і мігрують дані (часто через знімки і інкрементальні send). Плануйте робочий процес міграції і тестуйте відкат.

9) Чи впливає шифрування на scrubs і resilvers?

Scrub і resilver все ще читають і верифікують дані; шифрування додає роботу CPU для розшифрування/автентифікації там, де це застосовно. У багатьох системах пропускна здатність дисків залишається обмежувачем, але на CPU‑обмежених хостах ви можете спостерігати подовжені вікна обслуговування.

10) Який єдиний найкращий спосіб уникнути інцидентів «шифрування вбило продуктивність»?

Не тримайтеся одного важеля. Змінюйте по одній змінній за раз, зберігайте compression=lz4 за замовчуванням, налаштовуйте recordsize під навантаження і використовуйте план швидкої діагностики, щоб довести, чи ви обмежені CPU чи I/O.

Висновок

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

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

← Попередня
Кастомні чекбокси й радіокнопки на чистому CSS: доступні патерни, що не брешуть
Наступна →
Debian 13: Витоки пам’яті в сервісах — знайдіть їх із найменшими незручностями (випадок №43)

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