Чому драйвери стануть ще важливішою частиною гри

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

Аварія не почалася з очевидного «диск вийшов з ладу» або «лінк упав». Вона почалася з графіка, що виглядав… сонним.
Затримка трохи підвищилася. Потім трохи більше. Потім шар API почав робити повторні запити. А потім повторні запити стали трафіком.
І о 03:17 хтось вимовив фразу, яку ненавидить кожен SRE: «Але нічого не змінювалося».

Щось змінилося. Просто зміна жила в шарі, який нам подобається вдавати, що він нудний: драйвери.
Драйвери зберігання. Мережеві драйвери. Драйвери GPU. Драйвери віртуалізації. CSI-драйвери. «Драйвери» прошивки. Навіть сусідній із мікрокодом безлад.
Сучасний продакшен-стек — це переговори між можливостями апаратури, поведінкою ядра і тим, що команда драйверів припустила, що вам потрібно.

Драйвери тепер — функція продукту, а не «труби»

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

Це робить драйвери «частиною гри» так само, як компілятори стали частиною гри у інженерії продуктивності.
Ви більше не просто обираєте апаратні засоби. Ви обираєте бандл hardware+firmware+driver+kernel+configuration.
І ви або володієте цим бандлом від початку до кінця, або він володіє вашим розкладом сну.

Це не теорія. Якщо ви працюєте з:

  • NVMe в масштабі (локально або по fabric),
  • блоковим сховищем у хмарі з multipath,
  • Kubernetes з CSI-плагінами,
  • швидкими мережами (25/50/100/200G),
  • RDMA / RoCE,
  • DPDK, XDP, eBPF або агресивними оффлоадами,
  • GPU або іншими акселераторами,
  • віртуалізацією з virtio або SR-IOV,

…то ваш вибір драйверів не є «деталлю реалізації». Це оперативні важелі й операційні ризики.

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

Короткий жарт №1: Драйвери як офісні крісла — нікому не цікаво, поки воно не заскрипить голосно під час демонстрації для керівництва.

Чому це відбувається (нудні сили, що керують вашим життям)

1) Апаратне прискорилося; програмне стало витонченішим

Коли один NVMe-пристрій може виконувати сотні тисяч IOPS із затримками в мікросекундах, шлях ОС стає видимим.
Переривання, афініті CPU, локальність NUMA, відображення черг і рішення планувальника стають першорядними ефектами.
Драйвери — воротарі до цих механізмів.

2) «Розумні» пристрої перенесли логіку в прошивку, а драйвери стали контрактом

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

3) Віртуалізація й контейнеризація примножили шари трансляції

Один запис може пройти шлях: застосунок → libc → ядро → файлову систему → блоковий шар → dm-crypt → dm-multipath →
virtio-blk → гіпервізор → vhost → хостовий блоковий шар → HBA драйвер → ціль масиву зберігання.
Кожен хоп має таймаути, черги й семантику відмов. Драйвери присутні в кількох точках, і їхні значення за замовчуванням часто припускають
простіший світ.

4) Оновлення ядра стали рутиною, тому регресії драйверів — рутина

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

5) Обсервабельність перемістилася нижче в стек

У системах високого масштабу метрики на рівні додатка часто кажуть «затримки зросли», але не «чому».
Єдиний спосіб швидко відповісти «чому» — побачити під додатком: блоковий шар, черги пристроїв, поведінку переривань, проблеми DMA,
повторні передачі TCP, маркування ECN у RDMA тощо. Драйвери одночасно джерело цих даних і те, що ви діагностуєте.

6) Тиск на витрати: вичавлюємо більше з тієї ж апаратури

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

Короткий жарт №2: Найшвидший спосіб знайти баг у драйвері — назвати ротацію on-call «низький стрес».

Факти та історія: драйвери завжди мали значення, ми просто забули

Декілька контекстних моментів, що пояснюють, чому сьогодні відчувається інакше:

  1. Ранні SCSI-стеки робили чергування видимим. Tagged Command Queuing виніс конкурентність у шар пристрою,
    і глибина черги драйвера стала ручкою продуктивності задовго до появи NVMe.
  2. Linux 2.6 ввів істотну еволюцію планування вводу-виводу. CFQ та інші були відповіддю на змішані навантаження,
    і драйвери мали співпрацювати з новою семантикою планувальника.
  3. blk-mq змінив блоковий шар фундаментально. Мульти-черговий блоковий I/O знизив блокування й зробив видимим
    рішення відображення CPU/черги — драйвери стали ключовими для масштабування.
  4. NVMe стандартизував простіший набір команд, але додав паралелізм. Багато черг і глибоке відправлення команд
    зробили «локальність драйвера й CPU» важливішою за «витрати контролера».
  5. SR-IOV зробив «межі драйверів» архітектурним рішенням. Віртуальні функції перемістили частини NIC у гостя; «проблема драйвера» могла бути в хості, гості чи прошивці.
  6. RDMA відродило припущення транспорту. Коли ви обходите мережевий стек ядра, коректність драйвера та конфігурація
    стають критично важливими для надійності, а не тільки продуктивності.
  7. CSI зробив драйвери зберігання частиною контрольної площини. Provisioning томів у Kubernetes перейшов від «ops-скриптів»
    до «драйвера в кластері», що принесло нові режими відмов: вибори лідерів, обмеження API та RBAC.
  8. NVMe-oF зробив мережеві та сховищні драйвери єдиною проблемою. Затримка тепер функція як цілі, так і fabric, із драйверами на обох кінцях.

Режими відмов, які ви побачите частіше

За замовчуванням драйверів оптимізовані під бенчмарки, а не під ваше навантаження

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

Несумісність таймаутів між шарами

Один шар робить повторну спробу 30 секунд, інший здає позиції через 10, а ваш додаток робить повтори вічно.
Результат: дублювання записів, завислі I/O, розділення мозку при фейловерах або «деградований, але живий» стан, що повільно руйнує SLA.
Часто драйвер визначає перший таймаут у ланцюзі.

Оффлоади, які допомагають, поки не почнуть заважати

TCP segmentation offload, generic receive offload, checksum offload, LRO, апаратне шифрування і функції smart NIC:
вони можуть знизити навантаження CPU і підвищити пропускну здатність. Вони також можуть зламати захоплення пакетів, сплутати вимірювання затримки
і викликати баги прошивки під специфічні патерни трафіку.
Якщо ви керуєте високошвидкісними мережами, ви врешті-решт дізнаєтеся, які оффлоади довіряти, а які вимикати за принципом.

Проблеми NUMA та афініті, замасковані під «повільне сховище»

Черга, що працює на невірному сокеті, може додати відчутну затримку, особливо коли ви ганяєтеся за мікросекундами.
Драйвери експонують відображення черг, афініті переривань і використання MSI-X векторів.
Якщо ви не контролюєте афініті, планувальник «допоможе» вам у способи, що виглядають як випадковість.

Порожнини телеметрії

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

Плейбук швидкої діагностики: знайдіть вузьке місце до того, як зберуть «war room»

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

  1. Вузьке місце — CPU, пам’ять, мережа чи сховище?
  2. Це насичення, помилки/повторні спроби чи планування/афініті?
  3. Локально на вузлі, на класі пристроїв чи системно?

Перш за все: встановіть, чи бачить ядро I/O-проблеми

  • Перевірте використання по пристрою і очікуйте.
  • Перевірте глибину черги та об’єднання запитів.
  • Перевірте I/O-помилки, скиди, таймаути в dmesg/journal.

По‑друге: відокремте «пристрій повільний» від «шлях до пристрою повільний»

  • NVMe: журнали контролера, SMART, події скидання.
  • Multipath/iSCSI/FC: збої шляхів, фейловери, стан ALUA, таймаути.
  • Віртуалізація: contention хоста vs гостя, статистика virtio-черг, steal time.

По‑третє: перевірте історію несумісності драйвера/прошивки/ядра

  • Недавні зміни ядра або прошивки?
  • Зафіксовані версії драйверів, що відомі як хороші?
  • Зміни оффлоадів або нове налаштування?

По‑четверте: підтвердьте контролемований мікротест

  • Використайте мінімальний fio-тест з одним завданням і відомим розміром блоку.
  • Порівняйте з базою (навіть тижневою). Якщо бази немає — ви вже знайшли процесну помилку.

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

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

1) Ідентифікувати точний драйвер, прив’язаний до NIC

cr0x@server:~$ ethtool -i ens5
driver: ixgbe
version: 5.15.0-91-generic
firmware-version: 0x800003e5
expansion-rom-version:
bus-info: 0000:3b:00.0
supports-statistics: yes
supports-test: yes
supports-eeprom-access: yes
supports-register-dump: yes
supports-priv-flags: yes

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

2) Перевірити лічильники помилок і скиди NIC

cr0x@server:~$ ip -s link show dev ens5
2: ens5: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP mode DEFAULT group default qlen 1000
    link/ether 3c:fd:fe:aa:bb:cc brd ff:ff:ff:ff:ff:ff
    RX:  bytes  packets  errors  dropped  missed  mcast
    9876543210  12345678  0       421      0       9012
    TX:  bytes  packets  errors  dropped  carrier collsns
    8765432109  11223344  0       0        0       0

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

3) Переглянути налаштування оффлоадів (поширене джерело «дивного»)

cr0x@server:~$ ethtool -k ens5 | egrep 'gro|gso|tso|lro|rx-checksumming|tx-checksumming'
rx-checksumming: on
tx-checksumming: on
tcp-segmentation-offload: on
generic-segmentation-offload: on
generic-receive-offload: on
large-receive-offload: off

Що це означає: GRO/GSO/TSO увімкнені — нормально, але при налагодженні затримок або аномалій пакетів може знадобитись їх переключення.
Рішення: Якщо підозрюєте баги оффлоадів — вимикайте по одному та вимірюйте. Не «вимикайте все», якщо вам не подобається випадковий CPU DoS.

4) Підтвердити відповідність пристрою зберігання та драйвера

cr0x@server:~$ lsblk -o NAME,TYPE,SIZE,MODEL,ROTA,TRAN,MOUNTPOINT
NAME        TYPE   SIZE MODEL               ROTA TRAN MOUNTPOINT
nvme0n1     disk 931.5G Samsung SSD 980     0    nvme
├─nvme0n1p1 part     1G                     0    nvme /boot
└─nvme0n1p2 part 930.5G                     0    nvme /

Що це означає: ROTA=0 підтверджує очікування для SSD/NVMe. TRAN=nvme уточнює транспорт.
Рішення: Якщо ви очікували enterprise NVMe, а бачите споживчі моделі — зупиніться. Ваші розрахунки по продуктивності і витривалості змінилися.

5) Перевірити стан контролера NVMe і журнал помилок

cr0x@server:~$ sudo nvme smart-log /dev/nvme0
Smart Log for NVME device:nvme0 namespace-id:ffffffff
critical_warning                    : 0x00
temperature                         : 42 C
available_spare                     : 100%
available_spare_threshold           : 10%
percentage_used                     : 3%
data_units_read                     : 1,234,567
data_units_written                  : 987,654
media_errors                        : 0
num_err_log_entries                 : 12

Що це означає: num_err_log_entries > 0 може корелювати з тимчасовими таймаутами, скиданнями або проблемами лінку.
Рішення: Витягніть журнал помилок; якщо помилки згруповані під час інцидентів — ескалюйте до перевірки сумісності прошивки/драйвера.

6) Перевірити логи ядра на предмет скидань/таймаутів

cr0x@server:~$ sudo dmesg -T | egrep -i 'nvme|timeout|reset|blk_update_request|I/O error' | tail -n 8
[Mon Jan 21 03:12:09 2026] nvme nvme0: I/O 123 QID 4 timeout, aborting
[Mon Jan 21 03:12:10 2026] nvme nvme0: Abort status: 0x371
[Mon Jan 21 03:12:11 2026] nvme nvme0: resetting controller
[Mon Jan 21 03:12:15 2026] blk_update_request: I/O error, dev nvme0n1, sector 123456 op 0x1:(WRITE) flags 0x0 phys_seg 1 prio class 0

Що це означає: Таймаути й скидання контролера — це не «проблеми продуктивності». Це проблеми надійності з симптомами продуктивності.
Рішення: Якщо з’являються скидання — припиніть підбирати fio-флаги і почніть перевіряти прошивку, кабелі/бекплейн, помилки PCIe і версії драйвера ядра.

7) Виявити помилки PCIe (часто плутають з «поганими дисками»)

cr0x@server:~$ sudo lspci -s 0000:3b:00.0 -vv | egrep -i 'LnkSta:|AER|UESta|CESta' -n
45:		LnkSta:	Speed 8GT/s, Width x8
97:		CESta: RxErr- BadTLP- BadDLLP- Rollover- Timeout- NonFatalErr+ FatalErr-

Що це означає: Кориговані помилки (NonFatalErr+) все одно можуть спричиняти повтори і джіттер.
Рішення: Якщо помилки накопичуються — розглядайте це як нестабільність шляху апаратури. Поміняйте слот/кабель/бекплейн або налаштуйте PCIe ASPM, якщо це доречно.

8) Швидко виміряти латентність і завантаження по пристрою

cr0x@server:~$ iostat -x 1 3
Linux 5.15.0-91-generic (server) 	01/21/2026 	_x86_64_	(32 CPU)

avg-cpu:  %user   %nice %system %iowait  %steal   %idle
           9.12    0.00    2.95    7.88    0.00   80.05

Device            r/s     w/s   rKB/s   wKB/s  avgrq-sz avgqu-sz   await  r_await  w_await  %util
nvme0n1         120.0   980.0  3840.0 15680.0     32.0     8.10   8.20     2.10     9.00   96.50

Що це означає: %util близько 100% з високим await вказує на насичення на пристрої або його драйверному чергуванні.
Рішення: Якщо await підвищується, а пропуск залишається плоским — ви чергуєте. Рішайте, зменшити конкуренцію на боці додатку чи масштабувати пристрої.

9) Перевірити налаштування черги блок-слою (планувальник, nr_requests)

cr0x@server:~$ cat /sys/block/nvme0n1/queue/scheduler
[none] mq-deadline kyber

Що це означає: NVMe часто використовує «none», але mq-deadline може допомогти хвостовій латентності при змішаних навантаженнях в деяких середовищах.
Рішення: Якщо ви бачите екстремальну p99 латентність під конкуренцією — тестуйте mq-deadline у staging з вашим навантаженням. Не здогадуйтеся.

10) Перевірити глибину черги та поточні незавершені I/O

cr0x@server:~$ cat /sys/block/nvme0n1/queue/nr_requests
1023

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

11) Спостерігати реальний час обслуговування диска по процесах

cr0x@server:~$ sudo iotop -oPa
Total DISK READ:         0.00 B/s | Total DISK WRITE:       12.34 M/s
  TID  PRIO  USER     DISK READ  DISK WRITE  SWAPIN      IO    COMMAND
12345 be/4  postgres    0.00 B/s   8.90 M/s  0.00 %  12.00 %  postgres: writer process
23456 be/4  root        0.00 B/s   3.44 M/s  0.00 %   4.50 %  java -jar service.jar

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

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

cr0x@server:~$ findmnt -no SOURCE,TARGET,FSTYPE,OPTIONS /
/dev/nvme0n1p2 / ext4 rw,relatime,errors=remount-ro

Що це означає: Опції як noatime, поведінка бар’єрів (залежно від файлової системи) і режими журналювання впливають на патерни I/O.
Рішення: Якщо ви налагоджуєте сплески затримок — підтвердіть, що опції монтування відповідають вашим намірам і не є «успадкованими за замовчуванням».

13) Виявити стан multipath і флапи шляхів

cr0x@server:~$ sudo multipath -ll
mpatha (3600508b400105e210000900000490000) dm-2 IBM,2145
size=200G features='1 queue_if_no_path' hwhandler='0' wp=rw
|-+- policy='service-time 0' prio=50 status=active
| `- 3:0:0:1 sdb 8:16 active ready running
`-+- policy='service-time 0' prio=10 status=enabled
  `- 4:0:0:1 sdc 8:32 active ready running

Що це означає: Якщо статус часто перемикається між active/enabled — ви можете переживати фейловери, що додають латентність.
Рішення: Якщо існують флапи шляхів — перестаньте звинувачувати базу даних. Виправте SAN-zoning, кабелювання, FC/iSCSI таймаути або проблеми драйвера/прошивки.

14) Підтвердити версії модулів ядра та те, що завантажено

cr0x@server:~$ lsmod | egrep 'nvme|dm_multipath|ixgbe|mlx5' | head
nvme                  69632  2
nvme_core            167936  3 nvme
dm_multipath          40960  0
ixgbe                286720  0

Що це означає: Підтверджує, який код задіяно. Якщо ви очікували mlx5 (Mellanox), а бачите щось інше — знайшли дрейф конфігурації.
Рішення: Вирівняйте версії модулів по флоту; зафіксуйте відомо-стабільні збірки там, де надійність важливіша за новизну.

15) Перевірити, чи ви CPU-bound у softirq (тиск від мережевого драйвера)

cr0x@server:~$ mpstat -P ALL 1 2 | tail -n 8
Average:     CPU   %usr   %nice %system %iowait  %irq  %soft  %steal  %idle
Average:      0    5.10    0.00  12.40    0.20  0.30   18.70    0.00  63.30
Average:      1    3.90    0.00   9.80    0.10  0.20   25.10    0.00  60.90

Що це означає: Високий %soft вказує на тиск обробки пакетів (NAPI/softirq), часто від RX-сплесків або незбалансованого афініті IRQ.
Рішення: Налаштуйте афініті переривань / RSS, збільшіть RX-черги або зменшіть оффлоади, які раптово перекладають роботу на CPU.

16) Перевірити розподіл переривань для NIC (афініті має значення)

cr0x@server:~$ grep -E 'ens5|ixgbe' /proc/interrupts | head -n 6
  64:   1234567          0          0          0  IR-PCI-MSI 524288-edge      ens5-TxRx-0
  65:         0    1133445          0          0  IR-PCI-MSI 524289-edge      ens5-TxRx-1
  66:         0          0     998877          0  IR-PCI-MSI 524290-edge      ens5-TxRx-2
  67:         0          0          0     887766  IR-PCI-MSI 524291-edge      ens5-TxRx-3

Що це означає: Ідеально — щоб переривання розподілялися між CPU; «всі переривання на CPU0» — класична самостворена рана.
Рішення: Якщо розподіл зміщений — налаштуйте irqbalance або прив’яжіть IRQ для критичних робочих навантажень. Виміряйте до/після.

17) Швидкий контрольований мікро-бенчмаркінг сховища (не розганяйтесь)

cr0x@server:~$ sudo fio --name=randread --filename=/var/tmp/fio.test --rw=randread --bs=4k --iodepth=32 --numjobs=1 --size=1G --runtime=30 --time_based --direct=1
randread: (groupid=0, jobs=1): err= 0: pid=27182: Tue Jan 21 03:22:01 2026
  read: IOPS=85.2k, BW=333MiB/s (349MB/s)(9990MiB/30001msec)
    slat (usec): min=3, max=89, avg=7.2, stdev=1.1
    clat (usec): min=45, max=4120, avg=365.1, stdev=55.4
    lat  (usec): min=55, max=4130, avg=372.5, stdev=55.6

Що це означає: Ви отримуєте перевірку здоров’я: IOPS, пропускну здатність і розподіл затримок. Максимальні clat-шипи можуть натякати на чергування або скидання.
Рішення: Якщо fio виглядає добре, а ваш додаток повільний — вузьке місце, ймовірно, вище: поведінка файлової системи, патерни sync, блокування або мережа.
Якщо fio поганий — негайно досліджуйте шлях пристрою та драйвер.

Три корпоративні міні-історії (анонімізовано, болісно правдоподібні)

Міні-історія 1: Інцидент, спричинений неправильною припущенням

Середня SaaS-компанія розгорнула нові вузли обчислень для зайнятого Kubernetes-кластеру. Той самий модель CPU, та сама RAM, «такий самий» NVMe-об’єм.
Закупівля зробила свою роботу: купили те, що відповідало специфікації. Платформна команда образувала їх і додала до пулу вузлів.
Все виглядало добре тиждень.

Потім p99 затримки по ключовому сервісу почали коливатися щодня в другій половині дня. Автоскейлінг увімкнувся, що збільшило витрати, але не виправило p99.
On-call помітив дивну деталь: найгірші хвостові затримки були тільки у подів, які сиділи на нових вузлах. Проте fio на цих вузлах здавався «окей»
якщо запускати його у тихі години. Під час піку був хаос: випадкові мілісекундні clat-шипи.

Неправильне припущення було простим: «NVMe — це NVMe». Нові вузли мали споживчі NVMe-пристрої з агресивним енергозбереженням
і поєднанням прошивки/драйвера, яке віддавало перевагу пропускній здатності у сплесках над сталою латентністю. При стійкому змішаному навантаженні контролер
заходив у поведінки, що проявлялися як періодичні зупинки. Ніхто не перевіряв nvme smart-log або записи журналу помилок, бо не було жорстких відмов.
Лише багато «продуктивності».

Виправлення було не екзотичним. Вони стандартизували enterprise NVMe-моделі, зафіксували прошивки і додали крок пре-флайт перевірки:
fio з порогом по хвостовій латентності, а не тільки по середніх IOPS. Також почали фіксувати відбитки драйверів і прошивок в інвентарі.
Справжній виграш — культурний: вони припинили вважати драйвери фоном і почали трактувати їх як частину дизайну платформи.

Міні-історія 2: Оптимізація, що відкотилася

Компанія з платежів переслідувала зниження CPU-витрат. Обробка мережі займала значну частку, і хтось мав яскраву ідею:
увімкнути всі «корисні» оффлоади NIC по всьому флоту. Це впроваджували поступово, і у синтетичних тестах пропуск зросла.
CPU впав. Графіки виглядали героїчно.

Через два тижні з’явилися тікети підтримки про «випадкові таймаути». Не постійні. Не регіональні. Просто… випадкові.
Логи додатків показували підвищені повторні передачі і іноді збої TLS-handshake. Балансувальники не бачили помилок лінку.
Команда інциденту виконувала звичний танець: звинувачували DNS, сертифікати, «інтернет».

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

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

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

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

Якось квартально треба було швидко запатчити через advisory по безпеці ядра. Вони просунули нове ядро в staging і одразу
побачили підвищену затримку зберігання під нічними батч-джобами. Нічого не падало. Просто стало повільніше так, що робота не вклалася б у maintenance window у продакшені.

Тест регресії відреагував. Команда бісекла дельту в staging: те саме навантаження, те ж апаратне, інше ядро.
Вони підтвердили, що корелює зі зміною в обробці черг NVMe-драйвером під змішані чит/запис. Це не була драматична «помилка».
Це була зміна поведінки, що шкодила їхньому конкретному навантаженню.

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

Поширені помилки

1) Симптом: сплески p99, середні значення в нормі

Корінь: Чергування драйвера приховує зворотний тиск; глибокі черги + бурстове навантаження створюють підвищення хвостової латентності.

Виправлення: Зменшити конкуренцію на рівні додатку, протестувати mq-deadline/kyber де доречно, переконатися, що прошивка пристрою не застигає. Міряйте p95/p99, а не тільки середнє.

2) Симптом: «Сховище повільне» тільки на певних вузлах

Корінь: Мішані версії прошивки/драйвера, різна поведінка PCIe-слотів або відмінності NUMA афініті.

Виправлення: Порівняйте відбитки (драйвер/прошивка/lspci), перевірте PCIe AER-лічильники і нормалізуйте IRQ/чергу афініті по пулу вузлів.

3) Симптом: випадкові мережеві таймаути, без помилок лінку

Корінь: Взаємодія оффлоадів (GRO/TSO/checksum) або модерація переривань, що створює хвостову латентність під мікросплесками.

Виправлення: Перемикайте оффлоади по одному; перевірте CPU в softirq; підтвердіть розміри кілець і розподіл RSS.

4) Симптом: Multipath-сховище показує періодичні затримки

Корінь: Флапи шляхів + поведінка queue_if_no_path викликають накопичення I/O під час коротких простоїв.

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

5) Симптом: Після оновлення ядра пропуск впав на 15–30%

Корінь: Регресія драйвера або змінені значення за замовчуванням (планувальник, мапінг черг, налаштування оффлоадів).

Виправлення: Перезапустити базові fio і мережеві тести, порівняти налаштування sysfs і зафіксувати або відкотити, поки не валідуєте нову поведінку в staging.

6) Симптом: Високий %iowait, але диски не зайняті

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

Виправлення: Використовуйте iotop + perf/eBPF при можливості, перевірте steal time у віртуалізації і перевірте на скидання/таймаути драйвера, що блокують блок-слой.

7) Симптом: Захоплення пакетів не відповідає реальності

Корінь: Оффлоади (особливо GRO/GSO/TSO) змінюють те, що ви бачите у tcpdump відносно того, що на дроті.

Виправлення: Тимчасово відключіть оффлоади для налагодження або захоплюйте на span/mirror-точці; не будьте робити теорію на підставі оманливих пакетів.

8) Симптом: «Працює добре» до піку трафіку, потім колапс

Корінь: Нерівність переривань/черг: гаряча черга, один CPU обробляє більшість переривань або проблеми з бюджетом NAPI.

Виправлення: Перевірте /proc/interrupts, встановіть RSS/афініті розумно, валідуйте конфігурацію irqbalance і перетестуйте під піковим навантаженням.

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

Покроково: побудувати продакшен-базу, що враховує драйвери

  1. Інвентар відбитків.
    Зафіксуйте драйвер+прошивку NIC, драйвер+прошивку NVMe, версію ядра і ключові налаштування sysfs для кожного класу хостів.
  2. Визначте релевантні тести продуктивності.
    Один профіль fio для сховища і один мережевий профіль, що відповідають реальним розмірам I/O і конкуренції.
  3. Слідкуйте за хвостовими метриками.
    Вимагайте порогів p95/p99, а не тільки пропускної здатності.
  4. Розгортайте поетапно з канаркою.
    Спочатку одна зона/рейк/пул вузлів з прописаними критеріями відкату.
  5. Зафіксуйте відомо-стабільні бандли.
    Апаратне + прошивка + драйвер + ядро як одиниця, для кожної платформи.
  6. Зробіть відкат рутинним.
    Майте автоматизований шлях для безпечного повернення ядра/драйверів.
  7. Тестуйте фейловер під навантаженням.
    Multipath, bonded NICs або NVMe-oF фейловери повинні тестуватися з реальною конкуренцією.
  8. Документуйте вашу політику оффлоадів.
    Які оффлоади дозволені, які заборонені і які потребують явного обґрунтування.

Покроково: реагування на інцидент, коли «сховище/мережа повільні»

  1. Окресліть масштаб. Які вузли, які пристрої, який часовий проміжок? Якщо це один клас вузлів — підозрюйте дрейф драйверів/прошивок.
  2. Зберіть відбитки негайно. ethtool -i, lsmod, uname -a, nvme smart-log.
  3. Перевірте на помилки/скиди. dmesg і PCIe AER-лічильники. Скиди змінюють історію від «налаштування» до «стабільності».
  4. Перевірте сигнали насичення. iostat -x, глибина черги, %util, CPU у softirq.
  5. Запустіть контрольований мікротест. fio або невеликий мережевий тест з мінімальним впливом.
  6. Прийміть рішення. Відкотьте зміну, ізолюйте пул вузлів, вимкніть конкретний оффлоад або відмовтеся від підозрілого класу пристроїв.
  7. Напишіть постінцидентну дельту драйверів. Що змінилося на шарі драйвер/прошивка/ядро і як ви запобіжите тихому дрейфу?

Чого уникати (бо вам заманеться)

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

FAQ

1) Чому драйвери стали важливішими зараз, ніж п’ять років тому?

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

2) Якщо драйвер від вендора «підтримує Linux», хіба цього недостатньо?

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

3) Чи завжди варто використовувати найновіше ядро заради кращих драйверів?

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

4) Чи варто використовувати оффлоади?

Часто так, особливо для пропускної здатності і ефективності CPU. Але ставте їх як production-фічі: вмикайте вибірково, валідуйте обсервабельність
і майте план швидкого відкату. Деякі середовища віддають перевагу дебагабельності над піковою пропускною здатністю.

5) Як зрозуміти, чи вузьке місце — це «драйвер», а не «пристрій»?

Шукайте скиди/таймаути в логах, помилки PCIe і зміни поведінки після оновлень ядра. Проблема пристрою часто показує індикатори здоров’я/помилок,
тоді як проблема драйвера часто корелює зі змінами версій і проявляється по класу хостів.

6) Яка найкорисніша метрика для проблем зі сховищем?

Хвостова латентність (p95/p99), скорельована з глибиною черги та %util. Середні значення брешуть. Якщо черги ростуть і p99 стрибає — ви де-небудь буферизуєте біль.

7) У Kubernetes, чому CSI-драйвери такі важливі?

Вони — не тільки «шлях даних». Вони актори контрольної площини: provisioning, attaching, resizing, snapshotting. Баги або тротлінг можуть блокувати планування,
створювати завислі томи або викликати каскадні повторні спроби, що виглядає як нестабільність кластера.

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

Міняйте одну змінну за раз, канаркуйте, міряйте хвостову латентність і лічильники помилок, і документуйте до/після.
Якщо ви не можете пояснити, чому це допомогло — робота не завершена.

9) Чи потрібно турбуватися про NUMA для зберігання та мережі?

Якщо ви оперуєте високим IOPS або великою пропускною здатністю — так. Локальність NUMA і афініті IRQ можуть бути різницею між стабільним p99 і періодичним джіттером.
Трактуйте це як частину планування потужності.

10) Що стандартизувати спочатку: апаратне, прошивку чи драйвери?

Стандартизуйте бандл. Практично: оберіть SKU апаратури, зафіксуйте прошивки, зафіксуйте базовий kernel/driver і впровадьте виявлення дрейфу.
Часткова стандартизація — як ви отримуєте «той самий сервер», що поводиться по-різному о 2:00.

Висновок: наступні кроки, які ви дійсно можете зробити

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

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

  • Створіть інвентар відбитків драйверів/прошивки для кожного класу вузлів і зробіть дрейф видимим.
  • Побудуйте два базові профілі: fio-профіль для зберігання і мережевий профіль, що відповідають вашому навантаженню (включно з хвостовими метриками).
  • Зафіксуйте відомо-стабільні бандли (апаратне + прошивка + ядро + драйвер) і просувайте зміни через канарки.
  • Запишіть політику оффлоадів і ставтесь до змін оффлоадів як до релізів фіч.
  • Попрактикуйте плейбук швидкої діагностики один раз, коли ніхто не в паніці, щоб він працював, коли все горить.

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

← Попередня
Ланцюги CNAME у DNS: коли вони шкодять продуктивності та надійності
Наступна →
WordPress не відправляє пошту: налаштування SMTP, яке дійсно доставляє

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