Windows Explorer показує «Копіювання… 112 MB/s» протягом трьох секунд, потім швидкість падає до 0 B/s і зависає, ніби роздумує про сенс життя. Користувачі звинувачують «мережу». Мережа звинувачує «зберігання». Зберігання звинувачує «Windows». Усі помиляються по-своєму.
Якщо ви працюєте з SMB на базі ZFS (зазвичай Samba на Linux або інколи пристрій зберігання), ви можете зробити копіювання з Windows стабільно швидким. Але не через хаотичне крутіння налаштувань. Потрібно виявити, де з’являється затримка, а потім виправити ту частину, яка «бреше».
Що насправді означає «повільне копіювання» (і чого це не стосується)
«Windows копіювання повільне» — це не одна проблема. Це видима користувачу ознака для конвеєра, який включає: поведінку клієнта Windows, семантику протоколу SMB, деталі реалізації Samba, групи транзакцій ZFS та шляхи запису, і фізичну латентність носіїв. Ваше завдання — знайти етап, де пропускна здатність перетворюється на очікування.
Три шаблони копіювання, які треба розрізняти
- Великі послідовні копії (наприклад, ISO, VHDX): мають йти ближче до лінійної швидкості, поки сервер може комітити записи достатньо швидко.
- Багато дрібних файлів (наприклад, дерева вихідного коду): домінують операції з метаданими (створення, setattr, close, rename), а не пропускна здатність.
- Змішані навантаження (домашні шари + ВМ + сканери): «повільно» часто означає head-of-line blocking — один поганий шаблон псує чергу для всіх.
Чого це зазвичай не стосується
Зазвичай це не «SMB повільний». SMB3 може бути дуже швидким. Зазвичай це не «ZFS повільний». ZFS може наситити серйозні мережі. Зазвичай це спайки затримки від sync-записів, дрібних випадкових I/O, посилення метаданих або поганого вирівнювання кешування, які проявляються в клієнті, що показує оптимістичні сплески швидкості.
Ще одне переналаштування: Windows Explorer — не бенчмарк, а візуалізатор тривоги. Той графік — швидше емоційний індикатор, ніж осцилограф.
Цікаві факти та історичний контекст (щоб поведінка стала зрозумілішою)
- SMB1 vs SMB2/3 змінило все. SMB2 (ера Vista/2008) зменшила балакучість, збільшила розміри читань/записів і додала конвеєрування. Багато історій «SMB повільний» насправді — «ви застрягли на SMB1».
- Samba починалася як проект з реверс-інженерії. Вона виросла з «змушує UNIX говорити з Windows» до рівня enterprise SMB-сервера. Деякі значення за замовчуванням консервативні, бо Samba має витримувати дивні клієнти.
- ZFS групує записи. ZFS комітить дані в transaction group (TXG). Це робить пропускну здатність чудовою, але створює помітний «пульс», якщо фаза коміту затягується.
- Sync-записи — це зобов’язання, а не відчуття. Коли SMB-клієнт просить забезпечити надійність, ZFS має безпечно закомітити. Якщо ваш пул не вміє робити low-latency fsync, ви отримаєте класичний графік «швидко, потім нуль».
- SMB durable handles і leases змінили поведінку close/open. Сучасний Windows агресивно кешує. Це добре, поки додаток не вимагає семантики durable і не перетворює кешування на синхронний біль.
- Recordsize важливіший для файлових шарів, ніж багато кому здається. recordsize ZFS формує I/O-амліфікацію. Неправильний recordsize не лише марнує місце — він додає зайві IOPS при дрібному випадковому доступі.
- Стиснення часто допомагає SMB, навіть на швидких CPU. Багато офісних файлів добре стиснюються, знижуючи навантаження на диск і мережу. Перемога часто в латентності, а не в пропускній здатності.
- SMB signing став поширенішим з міркувань безпеки. Увімкнення підпису — це податок на CPU. Налаштування «secure» інколи перетворюється на «securely slow», коли серверний CPU слабкий або обмежений одним потоком.
Швидкий план діагностики
Це порядок дій, який швидко знаходить вузьке місце, не впадаючи в пастку «налаштуй усе підряд».
По-перше: класифікуйте навантаження
- Один великий файл? Багато дрібних файлів? Додаток пише з вимогами до збереження (durability)?
- Швидкість падає через фіксовані інтервали (кожні кілька секунд)? Це пахне TXG commit latency.
- Трапляється лише на певних шарах (shares)? Це пахне властивостями dataset або опціями SMB share.
По-друге: вирішіть, чи це мережа, CPU чи латентність зберігання
- Мережа: помилки інтерфейсу, повторні передачі, неправильний MTU, погане хешування LACP, Wi‑Fi клієнти, які поводяться як сервери.
- CPU: один ядро завантажене в
smbd, наклад від signing/encryption, переривання, насичення softirq. - Шлях зберігання: високий
awaitна vdev, блокування шляху ZFSsync, відсутній/повільний SLOG, пул майже заповнений або фрагментований.
По-третє: перевірте поведінку sync (зазвичай це винуватець)
- Перевірте властивість dataset
syncта налаштування Samba, які примушують sync (наприклад, strict sync). - Виміряйте fsync-латентність з самого хоста SMB, а не з вашого ноутбука.
- Якщо потрібна семантика sync, забезпечте правильний SLOG-пристрій (з захистом від втрати живлення) або прийміть обмеження продуктивності ваших основних vdev.
По-четверте: ізолюйте випадок «багато дрібних файлів»
- Метадані — це навантаження. Перевірте
atime, поведінкуxattrта продуктивність дрібних блоків. - Переконайтеся, що розташування пулу відповідає очікуванням по IOPS для метаданих (компроміс між mirror та RAIDZ).
По-п’яте: налаштовуйте лише те, що показали вимірювання
Якщо ви не можете показати before/after у латентності I/O, завантаженні CPU або повторних передачах, ви не налаштовуєте — ви декоруєте.
Припиніть здогадки: вимірюйте, куди йде час
SMB-копії — це переговори між клієнтом, який буферизує, і сервером, який комітить. Explorer показує «швидкість» на основі того, як швидко дані приймаються в буфери, а не того, наскільки швидко вони надійно записані. Тоді як ZFS може швидко прийняти дані в ARC і «грязні» буфери, а потім призупинитись під час коміту TXG. Саме ця пауза викликає нуль на графіку.
Ваш план вимірювань має відповісти на три питання:
- Чи клієнт чекає на сервер (латентність), чи він просто не надсилає (обмеження клієнта)?
- Чи сервер чекає на скидання на диск (sync-путь), чи на CPU (signing/encryption), чи на мережу?
- Чи ZFS підсилює навантаження (несумісний recordsize, фрагментація, тиск на метадані)?
Інженерія надійності має просте правило: вимірюйте систему, яка у вас є, а не ту, якою ви хотіли б її бачити.
Парафраз (Gene Kim): «Покращення потоку означає знаходження та усунення обмеження». Ось у чому справа.
Реалії ZFS, які ускладнюють роботу з SMB
TXG і шаблон «швидко, потім нуль»
ZFS накопичує «брудні» дані в пам’яті і періодично комітить їх на диск як transaction group. Якщо фаза коміту затягується, система пригальмовує записувачів. Очима клієнта: швидкий сплеск, потім пауза. Повторюється. Це не «мережева нестабільність». Це збереження надійності зберігання.
Sync-записи: податок на надійність
Коли навантаження виконує синхронні записи (або сервер їх трактує як такі), ZFS має гарантувати, що дані на стабільному носії перед підтвердженням. На пулах без швидкого intent log (SLOG) sync-записи лягають на основні vdev. Якщо це RAIDZ на HDD, результат передбачуваний: біль з часовими відмітками.
Recordsize, ashift та I/O-ампліфікація
recordsize ZFS керує максимальною роздільною здатністю блоків для даних файлу. SMB-шерінги часто містять змішані розміри файлів; занадто великий recordsize не завжди шкодить послідовним читанням, але може нашкодити випадковим записам і частковим перезаписам. Занадто малий — збільшує накладні витрати на метадані і погіршує ефективність стиснення.
Метадані не «безкоштовні»
Копії дрібних файлів навантажують метадані: записи в директоріях, ACL, xattr, timestamps. ZFS може це обробити, але тільки якщо макет пулу і кешування розумні. Якщо ви побудували широкий RAIDZ для ємності і потім використовуєте його для метаданих важкого SMB-шару, ви фактично купили автобус і заявили його на мотогонку.
Заповненість пулу та фрагментація
Коли пул заповнюється, розміщення блоків ускладнюється, фрагментація зростає, і латентність зростає. Користувачі SMB відчують це як «все працювало минулого місяця». ZFS не забуває, як писати; йому просто виснажуються легкі місця для розміщення блоків.
Реалії SMB, які ускладнюють роботу з ZFS
Семантика копіювання Windows: буферизація, close і надійність
Windows може буферизувати записи й вимагати надійності лише при закритті файлу, залежно від прапорів додатка та конфігурації сервера. Деякі додатки (і деякі засоби безпеки) вимагають write-through семантики. Це миттєво перетворює навантаження з «переважно async» на «сильно sync».
Signing і шифрування: безпека має ціну CPU
SMB-підпис часто вимагається політиками. Може бути увімкнено шифрування для певних шарів. Обидва споживають CPU. Якщо сервер SMB має скромний CPU з швидким NIC, ви можете вдаритися в стелю, де мережа проста, а одне ядро працює на межі можливостей у криптоопераціях.
SMB3 Multichannel: чудово, коли працює, неважливо, коли ні
Multichannel може використовувати кілька NIC і черг RSS. При неправильному конфігу ви отримаєте єдиний TCP-потік, застряглий на одній черзі. Тоді хтось скаже «але у нас подвійний 10GbE», ніби сервер зобов’язаний зацікавитися.
Opportunistic locks, leases і антивірус
Кешування на клієнті (oplocks/leases) зменшує чати. Але засоби безпеки на кінцевих точках люблять відкривати файли, змушувати оновлювати атрибути і загалом ламати поведінку кешування. Це може перетворити копію «багато дрібних файлів» в шаленство системних викликів.
Жарт №1: Трасування проблем SMB схоже на офісну політику — кожен наполягає, що він вузьке місце, і всі вони якимось чином праві.
Практичні завдання: команди, виводи, рішення
Нижче — реальні завдання, які ви можете виконати на SMB/ZFS сервері. Кожне містить, що означає вивід і яке рішення потрібно прийняти далі. Приклади орієнтовані на Linux + Samba + OpenZFS, бо саме там більшість тикетів «Windows копіювання повільне» живе.
Завдання 1: Підтвердіть стан пулу (бо продуктивність часто — симптом помираючого диска)
cr0x@server:~$ sudo zpool status -v tank
pool: tank
state: ONLINE
scan: scrub repaired 0B in 04:12:19 with 0 errors on Tue Dec 10 03:20:01 2025
config:
NAME STATE READ WRITE CKSUM
tank ONLINE 0 0 0
mirror-0 ONLINE 0 0 0
ata-SAMSUNG_SSD_1TB_A ONLINE 0 0 0
ata-SAMSUNG_SSD_1TB_B ONLINE 0 0 0
errors: No known data errors
Значення: «ONLINE» і чистий scrub означають, що ви не боретесь із прихованими ретраями чи навантаженням resilver. Якщо ви бачите DEGRADED, resilvering або checksum errors, припиніть тонке налаштування продуктивності і спочатку виправте апаратні проблеми.
Рішення: Якщо будь-який vdev показує помилки або триває resilver, заплануйте усунення та перевірте продуктивність після стабілізації.
Завдання 2: Перевірте заповненість пулу (майже повні пули повільні в передбачуваний спосіб)
cr0x@server:~$ zfs list -o name,used,avail,refer,mountpoint tank
NAME USED AVAIL REFER MOUNTPOINT
tank 38.2T 2.1T 96K /tank
Значення: ~95% заповнений (38.2T used, 2.1T avail) — це зона ризику для багатьох навантажень. Розміщення ускладнюється; фрагментація зростає.
Рішення: Якщо використання понад ~80–85% і продуктивність важлива, плануйте звільнення місця або розширення. Жоден параметр Samba не переможе фізику.
Завдання 3: Визначте dataset, який використовує SMB share, і виведіть ключові властивості
cr0x@server:~$ sudo zfs get -H -o property,value recordsize,compression,atime,sync,xattr,acltype,primarycache,logbias tank/shares/engineering
recordsize 1M
compression lz4
atime on
sync standard
xattr sa
acltype posixacl
primarycache all
logbias latency
Значення: У вас recordsize 1M (добре для великих послідовних файлів, ризиковано для часткових перезаписів), atime увімкнено (додаткові записи метаданих), sync standard (sync шанується), xattr у SA (часто добре), logbias latency (віддає перевагу SLOG якщо є).
Рішення: Якщо шар — «багато дрібних файлів», розгляньте recordsize=128K і atime=off. Якщо це образи ВМ, інша стратегія потрібна (ймовірно не через SMB).
Завдання 4: Виміряйте I/O-латентність пулу під час копіювання (істина в iostat)
cr0x@server:~$ sudo zpool iostat -v tank 1 5
capacity operations bandwidth
pool alloc free read write read write
-------------------------- ----- ----- ----- ----- ----- -----
tank 38.2T 2.1T 12 2400 3.1M 210M
mirror-0 38.2T 2.1T 12 2400 3.1M 210M
ata-SAMSUNG_SSD_1TB_A - - 6 1250 1.6M 108M
ata-SAMSUNG_SSD_1TB_B - - 6 1150 1.5M 102M
-------------------------- ----- ----- ----- ----- ----- -----
Значення: Висока кількість операцій запису (2400/s) з помірною пропускною спроможністю вказує на дрібні записи або sync-важке навантаження. Якщо пропускна здатність низька, але ops високі, ви обмежені IOPS або flush-путтям.
Рішення: Якщо записи дрібні й часті, дослідіть синхронні семантики, навантаження на метадані та невідповідність recordsize. Якщо ops низькі і пропускна здатність низька — підозрюйте мережу або обмеження SMB.
Завдання 5: Спостерігайте латентність по vdev через iostat (await — як сигнал тривоги)
cr0x@server:~$ sudo iostat -x 1 3
Linux 6.6.15 (server) 12/25/2025 _x86_64_ (16 CPU)
Device r/s w/s rkB/s wkB/s avgrq-sz avgqu-sz await r_await w_await svctm %util
nvme0n1 2.0 950.0 64.0 118000.0 248.0 3.20 3.4 1.2 3.4 0.6 58.0
nvme1n1 1.0 910.0 32.0 112000.0 246.0 3.05 3.3 1.1 3.3 0.6 55.0
Значення: ~3.3ms write await — це нормально для NVMe. Якщо під час копій ви бачите десятки/сотні ms, зберігання обмежує вашу пропускну здатність.
Рішення: Високий await + низький CPU + чиста мережа = проблема шляху зберігання (sync-записи, заповнений пул, повільні vdev або проблеми з SLOG).
Завдання 6: Перевірте, чи взагалі є у вас SLOG (і чи він щось робить)
cr0x@server:~$ sudo zpool status tank | sed -n '1,120p'
pool: tank
state: ONLINE
config:
NAME STATE READ WRITE CKSUM
tank ONLINE 0 0 0
mirror-0 ONLINE 0 0 0
ata-SAMSUNG_SSD_1TB_A ONLINE 0 0 0
ata-SAMSUNG_SSD_1TB_B ONLINE 0 0 0
logs
nvme-SLOG_INTEL_OPTANE ONLINE 0 0 0
Значення: Є окремий лог-пристрій. Добре. Але наявність не означає продуктивність; пристрій має бути швидким і захищеним від втрати живлення.
Рішення: Якщо існують sync-важкі навантаження і SLOG відсутній, вирішіть, чи потрібна вам семантика sync. Якщо так — додайте відповідний SLOG. Якщо ні — не підмінюйте це sync=disabled, якщо ви не готові втрачати підтверджені дані при відключенні живлення.
Завдання 7: Спостерігайте TXG-тротлінг і поведінку «брудних» даних
cr0x@server:~$ sudo arcstat 1 3
time read miss miss% dmis dm% pmis pm% mmis mm% arcsz c avail
12:10:01 320 12 4 1 0 11 3 0 0 84.2G 96.0G 21.4G
12:10:02 410 16 3 2 0 14 3 0 0 84.2G 96.0G 21.4G
12:10:03 390 10 2 1 0 9 2 0 0 84.2G 96.0G 21.4G
Значення: ARC не має суттєвих промахів; кешування не є вашим поточним обмеженням. Якщо ARC малий відносно пам’яті або промахи стрімко зростають, можливо ви обмежені пам’яттю або маєте неправильні налаштування.
Рішення: Якщо під час читань промахи ARC високі, налаштуйте розмір пам’яті/ARC або набір робочих даних (або прийміть, що навантаження не кешується добре).
Завдання 8: Підтвердіть версію Samba і чи погоджується SMB3
cr0x@server:~$ smbd -V
Version 4.19.5-Debian
cr0x@server:~$ sudo smbstatus -b | sed -n '1,60p'
Samba version 4.19.5-Debian
PID Username Group Machine Protocol Version Encryption Signing
-------------------------------------------------------------------------------------------------------------------------
23144 user1 domain users 10.10.20.55 (ipv4:10.10.20.55:53122) SMB3_11 - partial
Значення: SMB3_11 погоджено, це добре. Signing показано «partial» (залежить від конфігурації і клієнта). Якщо ви бачите SMB1 — у вас проблеми більші, ніж налаштування.
Рішення: Якщо виявлено SMB1, вимкніть його і усуньте сумісність клієнтів усвідомлено. Не тримайте SMB1 «через один старий сканер». Замініть сканер або ізолюйте його.
Завдання 9: Перевірте конфіг Samba на наявність «вбивць» sync (strict sync, sync always)
cr0x@server:~$ sudo testparm -sv | sed -n '/^\[engineering\]/,/^\[/{p}'
[engineering]
path = /tank/shares/engineering
read only = No
vfs objects = acl_xattr
strict sync = Yes
sync always = No
Значення: strict sync = Yes змушує Samba виконувати більше flush-ів. Це класичне налаштування «ми ввімкнули його для безпеки», яке може знищити пропускну здатність.
Рішення: Якщо у вас немає суворої вимоги відповідності, виставте strict sync = No і перевірте коректність додатків. Якщо потреба є — інвестуйте в SLOG і низьколатентне зберігання.
Завдання 10: Перевірте, чи увімкнено SMB signing/encryption і чи є CPU-обмеження
cr0x@server:~$ sudo smbstatus -b | awk 'NR==1 || NR==2 || $0 ~ /SMB3/'
Samba version 4.19.5-Debian
PID Username Group Machine Protocol Version Encryption Signing
23144 user1 domain users 10.10.20.55 (ipv4:10.10.20.55:53122) SMB3_11 AES-128-GCM mandatory
cr0x@server:~$ top -b -n 1 | sed -n '1,20p'
top - 12:12:41 up 34 days, 3:01, 2 users, load average: 9.12, 8.40, 7.95
Tasks: 291 total, 2 running, 289 sleeping, 0 stopped, 0 zombie
%Cpu(s): 12.1 us, 2.0 sy, 0.0 ni, 78.0 id, 0.0 wa, 0.0 hi, 7.9 si, 0.0 st
MiB Mem : 256000.0 total, 21000.0 free, 95000.0 used, 140000.0 buff/cache
Значення: Шифрування увімкнено. CPU здебільшого простає, тож шифрування, ймовірно, зараз не є вузьким місцем. Якщо ви бачите завантаження ядра або високі softirq — потрібно перевірити.
Рішення: Якщо encryption/signing обов’язкові і CPU гарячий — оновіть CPU, використовуйте системи з AES-NI, налаштуйте RSS і multiqueue, або звузьте шифрування до конкретних чутливих шарів.
Завдання 11: Перевірте лінк NIC, дуплекс та лічильники помилок (дешеві перевірки, дорогі наслідки)
cr0x@server:~$ ip -s link show dev bond0
2: bond0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9000 qdisc noqueue state UP mode DEFAULT group default qlen 1000
link/ether 9c:dc:71:aa:bb:cc brd ff:ff:ff:ff:ff:ff
RX: bytes packets errors dropped missed mcast
1223344556677 1023344556 0 0 0 120034
TX: bytes packets errors dropped carrier collsns
1334455667788 1124455667 0 0 0 0
cr0x@server:~$ ethtool bond0 | sed -n '1,25p'
Settings for bond0:
Supported ports: [ ]
Supported link modes: Not reported
Speed: 20000Mb/s
Duplex: Full
Auto-negotiation: off
Значення: Немає помилок, повний дуплекс, очікувана швидкість. Якщо ви бачите помилки або дропи — виправляйте мережу перш ніж чіпати ZFS.
Рішення: Якщо є помилки: перевірте кабелі, порти комутатора, узгодженість MTU та налаштування offload. Налаштування продуктивності поверх втрат пакетів — це театр.
Завдання 12: Перевірте повторні передачі TCP та тиск на сокети (SMB над хворою мережею — ілюзія)
cr0x@server:~$ ss -s
Total: 884
TCP: 211 (estab 104, closed 72, orphaned 0, timewait 72)
Transport Total IP IPv6
RAW 0 0 0
UDP 11 8 3
TCP 139 113 26
INET 150 121 29
FRAG 0 0 0
cr0x@server:~$ netstat -s | sed -n '1,80p'
Tcp:
154239 active connection openings
149802 passive connection openings
1124 failed connection attempts
1821 connection resets received
0 connections established
224159 segments received
231008 segments sent out
214 segments retransmitted
Значення: Повторні передачі є, але не у величезній кількості. Якщо під час копій retransmits зростають, ви побачите паузи, що не пов’язані зі зберіганням. SMB чутливий до стрибків латентності.
Рішення: Високі retransmits: перевірте буфери комутатора, невідповідність MTU, драйвер/прошивку NIC або перевантажений шлях через фаєрвол.
Завдання 13: Визначте, чи навантаження sync-важке (серверний тест fsync)
cr0x@server:~$ sync; sudo bash -c 'time dd if=/dev/zero of=/tank/shares/engineering/.fsync-test bs=1M count=256 conv=fdatasync status=none'
real 0m1.92s
user 0m0.00s
sys 0m0.28s
cr0x@server:~$ sudo rm -f /tank/shares/engineering/.fsync-test
Значення: Це вимірює «запис, а потім примусове забезпечення надійності». Якщо це повільно (наприклад, 10–60s), ваш пул не може швидко комітити sync-записи для SMB-навантажень, які їх вимагають.
Рішення: Повільний fsync: додайте/перевірте SLOG, зменшіть кількість примусових sync у Samba, якщо це прийнятно, або переробіть зберігання для низьколатентних записів.
Завдання 14: Переконайтеся, що dataset випадково не змушує sync вимкненим (або увімкненим) там, де ви не планували
cr0x@server:~$ sudo zfs get -H -o name,property,value sync tank/shares/engineering tank/shares/finance
tank/shares/engineering sync standard
tank/shares/finance sync always
Значення: Finance share має примусово встановлене sync=always. Це може бути свідомо (додатки потребують надійності) або помилкова конфігурація, що робить його повільним.
Рішення: Якщо знайдено sync=always, уточніть у власників додатків причини. Якщо ніхто не може обґрунтувати — поверніть на standard і протестуйте.
Завдання 15: Перевірте стиснення ZFS і реальне співвідношення (бо «ми увімкнули стиснення» ≠ «воно працює»)
cr0x@server:~$ zfs get -H -o name,property,value compression,compressratio tank/shares/engineering
tank/shares/engineering compression lz4
tank/shares/engineering compressratio 1.62x
Значення: 1.62x означає, що ви економите I/O і місце. Якщо ratio ~1.00x, стиснення мало допомагає, але звичайно LZ4 не шкодить.
Рішення: Тримайте LZ4 за замовчуванням. Відключайте лише якщо виміряли насичення CPU і дані майже не піддаються стисненню.
Завдання 16: Пошукайте патологічну фрагментацію (особливо якщо пул старий і майже повний)
cr0x@server:~$ sudo zdb -bbbs tank | sed -n '1,40p'
Block Size Histogram:
512: 0
1K : 0
2K : 1048576
4K : 2097152
8K : 1048576
16K: 524288
32K: 262144
64K: 131072
128K: 65536
256K: 32768
512K: 16384
1M : 8192
Значення: Це грубий огляд; на практиці ви звʼяжете фрагментацію з поведінкою розміщення і латентністю. Велике різноманіття дрібних блоків у dataset, призначеному для великих послідовних записів, може бути підказкою.
Рішення: Якщо фрагментація і заповненість високі — плануйте міграцію даних або розширення пулу. ZFS чудовий, але він не дефрагментує себе бажанням.
Три міні-історії з корпоративної практики
Міні-історія 1: Інцидент через хибне припущення
У них був новий ZFS-файловий сервер і два uplink по 10GbE. Розгортання виглядало добре перший тиждень, переважно тому, що тест був «скопіювати 20GB ISO один раз», і всі пішли додому задоволені.
Потім настав кінець кварталу. Фінанси завантажили тисячі дрібних PDF і таблиць у шар з Windows-додатку, який вимагав write-through. Користувачі повідомили, що копії «зависають кожні кілька секунд». Мережа не бачила насичення, тому її визнали вільною від вини. Команда зберігання бачила багато вільної RAM і гадала, що ARC все вирівняє. Але ні.
Хибне припущення було тонким: «Якщо пул може робити 1GB/s послідовних записів, він може робити офісні копії». Це різні види навантаження. Послідовна пропускна спроможність — це парадний заїзд; sync-важкі метадані — це смуга перешкод.
Коли хтось запустив простий тест dd ... conv=fdatasync на dataset, стало очевидно. Латентність коміту sync була вузьким місцем. Пул був RAIDZ на HDD. Чудово для ємності, жахливо для низьколатентних записів.
Виправлення теж було делікатним: вони не вимикали sync. Додали якісний SLOG з захистом від втрати живлення і прибрали strict sync з шарів, які цього не вимагали. Фінанси зберегли свої гарантії, інженери повернули швидкість. Тікети служби підтримки припинилися — це єдина KPI, що справді має значення, коли ти на чергуванні.
Міні-історія 2: Оптимізація, що відкотилася
Інша компанія мала повільні копії домашніх директорій. Хтось прочитав форум і вирішив «більший recordsize — значить швидше». Тому вони виставили recordsize=1M для всіх SMB dataset, включно з домашніми та проектними деревами.
Великі файли трохи прискорилися. Потім скарги стали дивнішими: збереження дрібних документів загальмувало, доступ до Outlook PST став ривкоподібним, і деякі додатки почали «не відповідати» при збереженні. Сервер SMB не впав; він просто виконував зайву роботу.
Чому? Часткові перезаписи великих блоків можуть створити write amplification. Невелика зміна в файлі може викликати read-modify-write великого блоку, особливо коли навантаження випадкове і додаток робить багато дрібних оновлень. ZFS — copy-on-write, тож і так веде детальний облік; додаткова ампліфікація — це як просити його жонглювати на біговій доріжці.
Невдала «оптимізація» також збільшила навантаження на метадані, бо профілі користувачів генерують купу дрібних файлів і атрибутних оновлень. Більший recordsize не допоміг у шляху метаданих; він лише зробив шлях даних менш дружнім.
Відкат був дисциплінований: вони розділили dataset за робочим навантаженням. Домашні директорії отримали 128K recordsize, atime off. Великі архіви залишилися на 1M. Продуктивність стабілізувалась. Урок закарбувався: налаштування — не шведський стіл, де можна все навантажити.
Міні-історія 3: Нудна, але правильна практика, що врятувала ситуацію
Команда, що керувала ZFS + Samba кластером, мала одну непримітну звичку: щотижневі звіти scrub і щомісячні базові знімки продуктивності. Не панелі для керівництва. Просто текстовий файл з zpool status, zpool iostat під навантаженням і базові лічильники помилок NIC.
Одного вівторка користувачі повідомили про «стрибкоподібні» копії. Інженер на чергуванні не гадала. Вони порівняли базовий знімок з поточними числами. Велика зміна: латентність запису на одній нозі mirror трохи піднялася, і з’явилися виправні помилки — достатньо, щоб викликати ретраї, але не достатньо, щоб диск вийшов з ладу.
Оскільки були історичні дані, вони не витратили півдня на суперечки про прапори Samba. Вони замінили диск у вікні технічного обслуговування, зробили resilver, і затримки копій зникли.
Нічого героїчного. Жодних магічних налаштувань. Просто помічати, що «регрес продуктивності» часто означає «апарат старіє повільно». Ось як виглядає нудна компетентність у продакшені.
Рішення з налаштування, які справді дають ефект
1) Визначте свою позицію щодо sync явно (не дозволяйте цьому статися випадково)
SMB-навантаження можуть бути sync-важкими, особливо з певними додатками і політиками. У вас є три варіанти:
- Шанувати sync і платити за це: тримайте
sync=standard, уникайте налаштувань Samba, які примушують додаткові flush, і розгорніть реальний SLOG, якщо потрібен. - Примусово sync завжди:
sync=alwaysдля шарів з вимогами відповідності. Очікуйте нижчу пропускну спроможність; проектуйте зберігання відповідно. - Вимкнути sync:
sync=disabled— бізнес-рішення, щоб ризикувати втратою підтверджених записів при відключенні живлення або збої. Це може бути прийнятно для тимчасових шарів, але не видавайте це за «безкоштовну продуктивність». Це інша угода щодо надійності.
2) Розділіть dataset за навантаженням (один шар — одна поведінка)
Один dataset для всього — найшвидший спосіб переконатися, що нічого не буде добре. Розділіть:
- Домашні директорії (метадані-важкі, дрібні файли)
- Інженерні проектні дерева (багато дрібних файлів, переважно для читання)
- Медіа-архіви (великі послідовні файли)
- Зони доставки додатків (можуть вимагати суворої надійності)
Потім задайте властивості на dataset: recordsize, atime, sync, стиснення, поведінка ACL.
3) Підібрати recordsize «достатньо правильно»
- Загальні SMB-шари: почніть з
recordsize=128K. - Архіви великих файлів: розгляньте
recordsize=1M, якщо більшість файлів великі і послідовні. - Бази даних/образи ВМ поверх SMB: уникайте цього, якщо можете; якщо ні — використовуйте спеціальні налаштування і ретельно тестуйте. SMB-файлообслуговування і datastore для ВМ — не випадкове поєднання.
4) Вимкніть atime для SMB-шарів (якщо немає реальної потреби)
atime=on додає записи метаданих при читанні. Більшість організацій не використовують час доступу для чогось суттєвого, і Windows точно не потребує, щоб ваш ZFS-сервер писав додаткові метадані щоразу при відкритті файлу.
5) Тримайте LZ4 стиснення за замовчуванням
LZ4 — одне з небагатьох «дефолтних» налаштувань, яке я захищаю в продакшені. Воно часто підвищує ефективну пропускну здатність і зменшує I/O. Не ускладнюйте до доказу з насичення CPU.
6) Використовуйте реальний SLOG, коли він потрібен (і не економте)
SLOG-пристрій — це не «будь-який SSD». Він має мати низьку латентність під sync-навантаженням і захист від втрати живлення. Інакше ви побудували дорогий генератор латентності.
7) Samba: уникайте «strict sync», якщо не можете його обґрунтувати
strict sync може знищити пропускну спроможність для навантажень, що генерують багато fsync-пунктів (включно з певною поведінкою Windows при закритті файлів). Якщо вам потрібна сувора семантика — зробіть зберігання здатним її підтримувати. Якщо ні — не платіть за це.
8) SMB signing/encryption: сфокусуйте застосування
Команди безпеки люблять загальні політики. Продукційні системи люблять бюджети. Якщо підпис/шифрування обов’язкові, переконайтеся, що хост SMB має запас CPU і сучасне апаратне прискорення криптооперацій. Якщо тільки певні шари містять чутливі дані — обмежуйте політики на рівні шару або трафіку.
Жарт №2: Нічого не робить файловий сервер швидшим так, як політичне засідання, що закінчилося словами «ми нічого не змінювали».
Типові помилки: симптом → корінь проблеми → фікс
1) Симптом: Копія починається швидко, потім падає до 0 B/s повторно
Корінь проблеми: TXG commit stalls через sync-записи або повільну латентність flush (немає SLOG, повільні vdev, пул занадто заповнений).
Виправлення: Виміряйте fsync (dd ... conv=fdatasync), перевірте налаштування Samba щодо sync, додайте якісний SLOG або переробіть пул для низької латентності, звільніть місце.
2) Симптом: Великі файли копіюються нормально; багато дрібних файлів повзають
Корінь проблеми: Навантаження, що залежить від метаданих (ACL, xattr, timestamps) плюс обмеження дрібних випадкових I/O.
Виправлення: atime=off, переконайтеся у відповідних властивостях dataset, розгляньте зеркала для пулів з високими вимогами метаданих, перевірте, чи VFS-модулі Samba не додають накладних витрат; прийміть, що це IOPS, а не bandwidth.
3) Симптом: Швидкість обмежується приблизно ~110 MB/s на «10GbE»
Корінь проблеми: Клієнт/сервер погодили 1GbE, неправильне хешування LACP або один TCP-потік без multichannel.
Виправлення: Перевірте швидкість лінку через ethtool, перевірте конфіг switch, протестуйте SMB multichannel і переконайтеся, що клієнт не знаходиться в сегменті 1GbE.
4) Симптом: Продуктивність гірша після увімкнення SMB signing або encryption
Корінь проблеми: CPU-обмеження в крипто/підписі, одномодульні «гарячі» місця, недостатні RSS-черги.
Виправлення: Виміряйте завантаження CPU по ядрах під час передачі, увімкніть multiqueue/RSS, оновіть CPU, звужуйте зону застосування signing/encryption або використайте обладнання з прискоренням.
5) Симптом: Копії час від часу зависають «саме на кілька секунд»
Корінь проблеми: Повторні передачі в мережі, bufferbloat або конгестія комутатора; іноді часи TXG збігаються з паузами.
Виправлення: Перегляньте retransmits (netstat -s), дропи інтерфейсу і лічильники комутатора. Якщо чисто — поверніться до перевірки латентності зберігання та sync.
6) Симптом: Один шар повільний; інший на тому ж сервері ок
Корінь проблеми: Різниця властивостей dataset (sync=always, дивний recordsize, atime on), відмінності в конфігурації Samba (strict sync, VFS-модулі) або квоти/резервування, що впливають на розміщення.
Виправлення: Порівняйте виходи zfs get і блоки testparm -sv для обох шарів. Нормалізуйте усвідомлено.
7) Симптом: «Windows каже, що потрібно 2 години», але сервер виглядає простою
Корінь проблеми: Сканування на стороні клієнта (антивірус, індексація), накладні витрати на дрібні файли або клієнт чекає на кожну операцію метаданих.
Виправлення: Відтворіть на чистому клієнті, протестуйте robocopy з опціями і перевірте метрики сервера під час операції. Не налаштовуйте сервери, щоб компенсувати проблемні кінцеві точки.
Контрольні списки / покроковий план
Покроково: виправлення «швидко, потім нуль» SMB-копій на ZFS
- Підтвердіть стан пулу:
zpool status -v. Якщо degraded або помилки — зупиніться і виправте диски. - Перевірте заповненість пулу:
zfs list. Якщо >85% використано — плануйте очищення/розширення. - Визначте dataset і властивості:
zfs get recordsize,atime,sync,compression. - Перегляньте конфіг Samba:
testparm -svна предметstrict sync,aioта VFS-модулів. - Виміряйте sync-латентність: серверний
dd ... conv=fdatasync. Якщо повільно — це головний підозрюваний. - Перевірте наявність/продуктивність SLOG:
zpool statusдля логів і впевніться, що клас пристрою відповідний. - Спостерігайте латентність дисків під навантаженням:
iostat -xіzpool iostatпід час відтворення. - Перевірте здоровʼя мережі:
ip -s link, retransmits (netstat -s) і швидкість лінку (ethtool). - Застосовуйте по одній зміні: наприклад, відключіть
strict syncна тестовому шарі або додайте SLOG; потім повторіть ту саму передачу і порівняйте. - Запишіть результат: зніміть латентність, пропускну здатність і чи зникли паузи. Памʼять тьмяніє; тикети — ні.
Базовий контрольний список (нудні речі, за які ви подякуєте собі)
- Щотижневий scrub запланований; звіти scrub переглядаються.
- Щомісячний знімок:
zpool status, ключові властивостіzfs get,ip -s linkі повторюваний тест throughput + fsync. - Макет dataset документований за категорією навантаження.
- Ясна політика щодо sync: які шари вимагають гарантій надійності.
- Контроль змін для конфігурації Samba; без «однорядкових фіксів» у продакшені о 2-й ночі.
ЧаПи
1) Чому Windows Explorer показує швидку швидкість, а потім 0 B/s?
Explorer показує на основі буферизації та короткочасного прийому. ZFS і Samba можуть швидко прийняти дані, а потім призупинитися під час коміту sync-записів або TXG. Вимірюйте латентність на сервері.
2) Чи robocopy швидший за Explorer?
Іноді. Велика перевага в тому, що robocopy передбачуваніший і скриптуємий, та показує повторні спроби і поведінку по файлах. Він не вирішить синхронну латентність на сервері.
3) Чи варто ставити sync=disabled, щоб прискорити?
Тільки якщо ви готові ризикнути втратити підтверджені записи при відключенні живлення або збою. Для тимчасових шарів це може бути прийнятно. Для бізнес-даних — це зниження надійності, а не трюк налаштування.
4) Чи потрібен мені SLOG для SMB?
Якщо ваше навантаження генерує багато sync-записів (або налаштування Samba примушують суворе флешування), хороший SLOG може кардинально змінити ситуацію. Якщо навантаження переважно async — SLOG мало допоможе.
5) Який recordsize слід використовувати для SMB-шарів?
Починайте з 128K для загального призначення. Використовуйте 1M для великих послідовних архівів. Уникайте глобальних змін; розділяйте dataset за навантаженням.
6) Чи ввімкнення LZ4 сповільнить роботу?
Зазвичай ні, і часто воно пришвидшує роботу, зменшуючи I/O. Якщо CPU вже завантажений (шифрування/підпис, важке навантаження), виміряйте перед прийняттям рішення.
7) Чи RAIDZ поганий для SMB?
Не «поганий», але RAIDZ менш дружній до дрібних випадкових записів і метаданих-важких навантажень, ніж mirror. Якщо ваш SMB-випадок — багато дрібних файлів і sync-поведінка, mirrored vdev часто виграють по латентності.
8) Чому один SMB-шар повільний, а інші — ок?
Різні властивості dataset або опції Samba. Шукайте sync=always, atime=on, дивний recordsize або strict sync лише на одному шарі.
9) Чи SMB Multichannel вирішує все?
Ні. Воно може підвищити пропускну здатність і стійкість, але не виправить латентність зберігання або sync-паузи. Також вимагає коректних NIC, драйверів і підтримки на клієнті.
10) Як зрозуміти, що проблема в CPU?
Під час передачі одне або кілька ядер будуть постійно завантажені, часто в smbd або ядровому networking/crypto. Тим часом диски і NIC не будуть насичені. Це ваш знак.
Наступні кроки на цей тиждень
Виконайте ці кроки у порядку. Кожен крок робить рішення очевиднішим, і жоден не вимагає віри.
- Виберіть один відтворюваний тест трансфер (один великий файл і одна папка «багато дрібних файлів») і тримайте його постійним.
- Запустіть швидкий план діагностики і збережіть виводи:
zpool iostat,iostat -x,ip -s link,netstat -s,smbstatus. - Доведіть або виключіть синхронну латентність за допомогою серверного тесту
dd ... conv=fdatasyncна dataset. - Розділіть dataset за навантаженням, якщо ще не зроблено. Встановіть
atime=offі розумніrecordsizeдля кожної категорії. - Виправте реальне вузьке місце: додайте якісний SLOG для sync-важких шарів, звільніть місце якщо пул занадто повний, або розвʼяжіть CPU/мережеві проблеми якщо саме вони — джерело.
- Напишіть односторінковий ранбуk з базовими командами і «нормальними» виводами. Майбутнє ви купить каву минулому вам.
Мета не в ідеальному графіку. Мета — передбачувана продуктивність в межах контракту на надійність, який ви справді хочете надавати. Коли ви свідомо обираєте цей контракт, ZFS і SMB перестають бути містичними і стають… просто вимогливими.