Випадкові розриви на сервері — це особливий вид болю: нічого не “лежить” настільки довго, щоб викликати мережеву команду, але все працює ненадійно достатньо довго, щоб ви виглядали ненадійним. SSH зависає. RPC дає таймаути. Монти сховищ зупиняються, ніби думають про своє існування. А коли ви заходите — канал “в порядку”.
Тут народжуються забобони. Люди вимикають оффлоади, ніби переключають зачарований вимикач. Перезавантажують сервер. Звинувачують “оновлення Ubuntu”. Можна краще. Мета не знайти магічний sysctl. Мета — довести, де саме втрачаються пакети: на дроті, у комутаторі, у NIC, у драйвері, у приймальному шляху ядра або в вашій конфігурації.
Практична модель: де насправді відбуваються «розриви»
Більшість «випадкових розривів» насправді не є розривами. Це транзитні втрати, перестановки, затримки або короткі переговори лінку, які ваша аплікація інтерпретує як помилку. Потрібно розділити режими відмов:
- Флапи лінку: фізичний лінк опускається/піднімається (кабель, SFP, порт комутатора, autoneg). Linux часто це чітко логуватиме.
- Скидання драйвера/NIC: пристрій залишається “up”, але драйвер скидає черги, прошивку або DMA. Виглядає як короткий збій; логи можуть бути тонкими.
- Перевантаження прийому: лінк увімкнений, але RX-кільця переповнюються або softnet backlog дропає пакети. Не потрібні фізичні помилки.
- Взаємодії оффлоадів/функцій: контрольні суми, GRO/LRO, TSO/GSO, VLAN-offload або XDP можуть створювати дивні ефекти з певними комутаторами, тунелями або ревізіями NIC.
- PMTU blackhole: лінк в порядку; але виявлення PMTU не працює. Деякі потоки зависають; пінги «працюють».
- Неправильна робота bonding/LACP/VLAN/bridge: ви побудували щось хитре, і тепер інколи воно «їсть» пакети.
Ваше завдання — правильно класифікувати подію. Коли це зроблено, виправлення стає смішно простим.
Парафраз ідеї (з віднесенням): John Allspaw давно стверджує, що надійність походить від ставлення до операцій як науки доказів, а не театру звинувачень.
Швидкий план діагностики (перший/другий/третій)
Коли ви на виклику, немає часу милуватися графіками пакетів. Почніть тут. Мета — з’ясувати, який рівень вас обманює.
Перший: підтвердьте, чи це флап лінку, скидання драйвера, або перевантаження/дропи
- Логи ядра в межах вікна події: down/up лінку проти reset проти queue timeout.
- Лічильники NIC: CRC та alignment помилки кричать про фізичний рівень; RX_missed_errors та rx_no_buffer вказують на черги/інтеррути.
- Softnet drops: якщо ядро відкидає ще до того, як додаток бачить пакети, ви знайдете це тут.
Другий: відокремте «дивності оффлоадів» від «реальної проблеми пропускної здатності»
- Перевірте стан оффлоадів і версії драйвера/прошивки.
- Відтворіть тест контрольованим трафіком (навіть простим iperf3) і дивіться лічильники.
- Якщо відключення оффлоада «вирішує» проблему, доведіть чому: зміни в лічильниках, пересталися скидання або конкретна інкапсуляція перестала ламатися.
Третій: перевірте комутатор, оптику та кабелі як доросла людина
- Шукайте сплески FEC/CRC, символ-помилки та повторні переговори по лінку на обох кінцях.
- Поміняйте оптику/кабель, щоб виключити фізичну проблему. Це не гламурно, але швидко.
- Підтвердіть налаштування партнера LACP та MTU кінця в кінець.
Правило рішення: Якщо ОС показує down/up лінк — починайте з фізики і конфігурації порту комутатора. Якщо лінк залишається up, але лічильники ростуть і softnet drops стрибають — налагоджуйте хост. Якщо NIC скидається — дивіться драйвер/прошивку і здоров’я PCIe/живлення.
Факти й контекст, які бажано знати заздалегідь
- Факт 1: «Помилки контрольної суми» в захопленнях можуть бути артефактами: з TX checksum offload пакети на хості можуть виглядати хибними до того, як NIC виправить їх на дроті.
- Факт 2: GRO (Generic Receive Offload) в Linux — це програмний механізм; LRO керується NIC і історично частіше поводиться некоректно з тунелями та певними типами трафіку.
- Факт 3: Мережевий стек Linux давно має RSS, але відображення черг на ядра залишається поширеною самосаботажною помилкою на мультисокетних системах.
- Факт 4: Багато «випадкових дропів», звинувачених у ядрах, насправді були мікросплесками в комутаторі: короткі піки, які переповнюють буфери швидше, ніж ваш інтервал моніторингу встигає зафіксувати.
- Факт 5: Energy Efficient Ethernet (EEE) має довгу історію «в теорії добре» і «на практиці таємничо сплесково» на обладнанні від різних вендорів.
- Факт 6: На сучасних NIC прошивка — частина поверхні надійності. Оновлення драйвера без оновлення прошивки може додати нових багів і зберегти старий мікрокод.
- Факт 7: Піддомен автонеготації не є реліктом 90‑х. Вона виникає сьогодні через погані DAC, маргінальні оптики або примусові налаштування лише на одній стороні.
- Факт 8: Bonding (LACP) міцний, але лише якщо обидві сторони узгоджені щодо хешування, режиму LACP і визначення “up”. Інакше він інколи ламається витончено.
- Факт 9: PMTU blackholes залишаються поширеними, бо фільтрація ICMP усе ще розглядається як «безпека», хоча часто вона виступає як «генератор випадкових відмов».
Практичні завдання (команди + значення + рішення)
Нижче — польові завдання, які можна виконати на Ubuntu 24.04. Кожне містить, що означає вивід і що робити далі. Копіювати/вставляти дозволено. Відчуття — ні.
Завдання 1: Ідентифікуйте NIC, драйвер і прошивку, які фактично працюють
cr0x@server:~$ sudo ethtool -i eno1
driver: ixgbe
version: 6.8.0-31-generic
firmware-version: 0x800003e7
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
Значення: Тепер у вас є точний кортеж: версія ядра/драйвера, назва драйвера, версія прошивки, PCI шина. Саме цей кортеж корелюється зі скиданнями й відомими особливостями. «Intel 10G» — це не кортеж.
Рішення: Якщо розриви корелюють з недавніми оновленнями ядра, збережіть цей вивід в нотатках інциденту. Якщо прошивка дуже стара щодо вашого флоту — заплануйте оновлення. Якщо драйвер вбудований, але вендор рекомендує новий зовнішній драйвер — розглядайте це як гіпотезу, а не догму.
Завдання 2: Перевірте флапи лінку і скидання драйвера в логах ядра
cr0x@server:~$ sudo journalctl -k --since "2 hours ago" | egrep -i "eno1|link is|down|up|reset|watchdog|tx timeout|nic"
[ 7432.112233] ixgbe 0000:3b:00.0 eno1: NIC Link is Down
[ 7435.556677] ixgbe 0000:3b:00.0 eno1: NIC Link is Up 10 Gbps, Flow Control: RX/TX
[ 8121.000111] ixgbe 0000:3b:00.0 eno1: Detected Tx Unit Hang
[ 8121.000222] ixgbe 0000:3b:00.0 eno1: Reset adapter
Значення: Перший набір — справжній флап лінку. Останні рядки вказують на зависання Tx і скидання адаптера — інша категорія проблеми.
Рішення: Link down/up вказує на оптику/кабель/порт/autoneg/EEE. Tx hang/reset вказує на драйвер/прошивку/PCIe/керування живленням і поведінку черг/інтеррутів.
Завдання 3: Слідкуйте за станом лінку та параметрами переговору в реальному часі
cr0x@server:~$ sudo ethtool eno1 | egrep -i "Speed|Duplex|Auto-negotiation|Link detected"
Speed: 10000Mb/s
Duplex: Full
Auto-negotiation: on
Link detected: yes
Значення: Це ваша базова лінія. Якщо бачите перемикання швидкості (10G → 1G) або autoneg вимкнений на одній стороні — маєте конфігураційну або фізичну проблему.
Рішення: Якщо флапи лінку співпадають із переукладанням переговорів або змінами швидкості — припиніть крутити оффлоади. Говоріть з командою комутатора і міняйте компоненти.
Завдання 4: Витягніть лічильники NIC, що розрізняють фізичні та хостові дропи
cr0x@server:~$ sudo ethtool -S eno1 | egrep -i "crc|align|symbol|discard|drop|miss|overrun|timeout" | head -n 30
rx_crc_errors: 0
rx_align_errors: 0
rx_symbol_err: 0
rx_discards: 124
rx_dropped: 0
rx_missed_errors: 98765
tx_timeout_count: 3
Значення: CRC/align/symbol помилки вказують на корупцію фізичного рівня. rx_missed_errors зазвичай означає, що NIC не зміг DMA-помістити пакети в буфери хоста достатньо швидко (голодання черги / інтеррупт-модерація / планування CPU).
Рішення: Якщо фізичні помилки ненульові і зростають під час інцидентів — ставте це як проблему кабелю/оптики/порту. Якщо missed errors ростуть, а фізичні помилки нульові — фокусуйтесь на RX-червях, IRQ, NAPI та конкуренції CPU.
Завдання 5: Інспектуйте softnet drops (ядро дропає до рівня сокета)
cr0x@server:~$ awk '{print NR-1, $1, $2, $3, $4, $5}' /proc/net/softnet_stat | head
0 0000001a 00000000 0000003f 00000000 00000000
1 00000020 00000000 00000110 00000000 00000000
Значення: Поле 1 — оброблені пакети, поле 2 — дропнуті пакети (в hex), поле 3 — time_squeeze. Дропи/time_squeeze вказують, що CPU/softirq не встигає.
Рішення: Якщо дропи зростають під час розривів — це не «таємниця». Це перевантаження або неправильне розміщення CPU/IRQ. Перейдіть до задач по IRQ/RSS.
Завдання 6: Підтвердіть, що інтеррути NIC призначені розумно
cr0x@server:~$ grep -i eno1 /proc/interrupts | head -n 10
98: 12345678 0 0 0 IR-PCI-MSI 524288-edge eno1-TxRx-0
99: 12 0 0 0 IR-PCI-MSI 524289-edge eno1-TxRx-1
100: 10 0 0 0 IR-PCI-MSI 524290-edge eno1-TxRx-2
Значення: Черга 0 робить всю роботу, тоді як інші черги простаюють. Це може бути через некоректну конфігурацію RSS, типи потоків або проблему пінування.
Рішення: Якщо одна черга гаряча, а інші холодні — виправте RSS/кількість черг і розгляньте прив’язку IRQ. Якщо хост мультисокетний — переконайтеся, що черги NIC знаходяться на локальних NUMA‑ядрах.
Завдання 7: Перевірте RSS і кількість об’єднаних каналів
cr0x@server:~$ sudo ethtool -l eno1
Channel parameters for eno1:
Pre-set maximums:
RX: 0
TX: 0
Other: 0
Combined: 64
Current hardware settings:
RX: 0
TX: 0
Other: 0
Combined: 8
Значення: NIC підтримує до 64 об’єднаних черг, зараз налаштовано 8. Це не “неправильно”, але має відповідати ядрам CPU і навантаженню.
Рішення: Якщо бачите missed errors або softnet drops і маєте запас CPU — збільшення combined channels може допомогти. Якщо ви вже завантажені на CPU — більше черг додають накладні витрати. Тюньте обдумано.
Завдання 8: Змініть кількість каналів (тимчасово) для тесту гіпотези
cr0x@server:~$ sudo ethtool -L eno1 combined 16
cr0x@server:~$ sudo ethtool -l eno1 | tail -n +1
Channel parameters for eno1:
Pre-set maximums:
RX: 0
TX: 0
Other: 0
Combined: 64
Current hardware settings:
RX: 0
TX: 0
Other: 0
Combined: 16
Значення: Ви збільшили паралелізм черг. Якщо дропи зникли під навантаженням — ви знайшли вузьке місце прийому. Якщо латентність погіршилася і CPU підскочив — ви перестаралися.
Рішення: Залишайте зміну лише якщо доведете покращення через лічильники та симптоми аплікацій. Зробіть це постійним через systemd-networkd/NetworkManager‑хуки або udev правила, а не покладайтеся на те, що виживе перезавантаження.
Завдання 9: Перевірте, які оффлоади зараз увімкнені
cr0x@server:~$ sudo ethtool -k eno1 | egrep -i "rx-checksumming|tx-checksumming|tso|gso|gro|lro|rx-vlan-offload|tx-vlan-offload|ntuple"
rx-checksumming: on
tx-checksumming: on
tcp-segmentation-offload: on
generic-segmentation-offload: on
generic-receive-offload: on
large-receive-offload: off
rx-vlan-offload: on
tx-vlan-offload: on
ntuple-filters: off
Значення: GRO/TSO/GSO/checksum offload увімкнено. LRO вимкнено (часто хороший дефолт). VLAN offload увімкнено.
Рішення: Не вимикайте все «щоб безпечно». Вимикайте одну функцію за раз, тільки щоб перевірити підозрілу взаємодію. Якщо ви вимкнете checksumming — очікуйте збільшення CPU і, можливо, гірший пропуск; ви обмінюєте гіпотезу про коректність на вимірювану вартість.
Завдання 10: Переключіть один оффлоад для перевірки багу (і спостерігайте лічильники)
cr0x@server:~$ sudo ethtool -K eno1 gro off
cr0x@server:~$ sudo ethtool -k eno1 | grep -i generic-receive-offload
generic-receive-offload: off
Значення: GRO вимкнено. Якщо ваша проблема пов’язана з GRO (часто при тунелях/інкапсуляції або з певними комбінаціями NIC/драйвера), симптоми можуть швидко змінитися.
Рішення: Якщо вимкнення GRO усуває затримки, але підскочує CPU і знижує пропускну здатність, ви, ймовірно, натрапили на крайній випадок драйвера/ядра. Потім або (a) тримаєте GRO вимкненим для цього інтерфейсу, або (b) змінюєте kernel/driver/firmware, або (c) перепроектовуєте інкапсуляцію. Обирайте, виходячи з бізнес-обмежень, а не гордості.
Завдання 11: Перевірте MTU і чи випадково ви не фрагментуєте або не потрапляєте в blackhole
cr0x@server:~$ ip -br link show eno1
eno1 UP 10.10.0.12/24 fe80::1234:56ff:fe78:9abc/64
cr0x@server:~$ ip link show eno1 | egrep -i "mtu|state"
2: eno1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9000 qdisc mq state UP mode DEFAULT group default qlen 1000
Значення: MTU — 9000. Якщо ваш шлях комутатора або пір — 1500, ви маєте відтворювану періодичну помилку: маленькі пакети працюють, великі — зависають або фрагментуються дивно, і «випадковість» стає трендом.
Рішення: Підтвердіть MTU кінця в кінець. Для тунелів пам’ятайте про оверхед. Якщо не можете гарантувати jumbo frames по всьому шляху — не використовуйте їх частково.
Завдання 12: PMTU тест з ping «не фрагментувати»
cr0x@server:~$ ping -M do -s 8972 -c 3 10.10.0.1
PING 10.10.0.1 (10.10.0.1) 8972(9000) bytes of data.
From 10.10.0.12 icmp_seq=1 Frag needed and DF set (mtu = 1500)
From 10.10.0.12 icmp_seq=2 Frag needed and DF set (mtu = 1500)
From 10.10.0.12 icmp_seq=3 Frag needed and DF set (mtu = 1500)
--- 10.10.0.1 ping statistics ---
3 packets transmitted, 0 received, +3 errors, 100% packet loss, time 2043ms
Значення: Шлях не може нести 9000-байтові фрейми. Це не тонко. Ваш інтерфейс має MTU більше, ніж підтримує шлях.
Рішення: Виправте невідповідність MTU. Або встановіть MTU 1500 на хості або увімкніть jumbo frames кінець в кінець (включно з bond, bridge, підінтерфейсами VLAN та портами комутатора).
Завдання 13: Перевірте TCP retransmits і статистику мережі ядра
cr0x@server:~$ nstat -az | egrep -i "TcpRetransSegs|TcpTimeouts|IpInDiscards|IpOutDiscards"
IpInDiscards 120
IpOutDiscards 0
TcpTimeouts 18
TcpRetransSegs 3490
Значення: Ретрансмити і таймаути підтверджують реальні втрати/затримки, які відчуває TCP, а не просто скарги аплікації. IP discards вказують на дропи на верхньому рівні.
Рішення: Якщо ретрансмити стрибнули під час інцидентів при стабільному лінку — корелюйте з softnet drops, NIC missed errors і буферами порту комутатора. Далі обирайте: тюнінг хоста або виправлення мережі.
Завдання 14: Підтвердіть, чи NetworkManager/systemd-networkd не блокує інтерфейс
cr0x@server:~$ systemctl status NetworkManager --no-pager
● NetworkManager.service - Network Manager
Loaded: loaded (/usr/lib/systemd/system/NetworkManager.service; enabled; preset: enabled)
Active: active (running) since Mon 2025-12-29 09:12:10 UTC; 3h 2min ago
Docs: man:NetworkManager(8)
cr0x@server:~$ sudo journalctl -u NetworkManager --since "2 hours ago" | egrep -i "eno1|carrier|down|up|deactivat|activat"
Dec 29 10:41:12 server NetworkManager[1023]: <info> [....] device (eno1): carrier: link connected
Dec 29 10:41:13 server NetworkManager[1023]: <info> [....] device (eno1): state change: activated -> deactivating (reason 'carrier-changed')
Dec 29 10:41:14 server NetworkManager[1023]: <info> [....] device (eno1): state change: deactivating -> activated (reason 'carrier-changed')
Значення: Carrier змінюється; NM реагує. Це зазвичай відображає реальну подію лінку, а не випадкову поведінку NM.
Рішення: Не боріться з network manager. Виправте нестабільність carrier (фізика/комутатор) або скидання драйвера, що викликають зміни carrier.
Завдання 15: Перевірте підказки про здоров’я PCIe (AER помилки виглядають як «випадкові проблеми NIC»)
cr0x@server:~$ sudo journalctl -k --since "24 hours ago" | egrep -i "AER|pcieport|Corrected error|Uncorrected|DMAR|IOMMU" | head -n 30
[ 8120.998877] pcieport 0000:3a:00.0: AER: Corrected error received: 0000:3a:00.0
[ 8120.998900] pcieport 0000:3a:00.0: PCIe Bus Error: severity=Corrected, type=Physical Layer, (Receiver ID)
Значення: Corrected PCIe фізичні помилки можуть передувати гикам або скиданням пристрою, особливо під навантаженням або з маргінальними слотами/райзерами.
Рішення: Якщо логи AER корелюють зі скиданнями NIC — припиніть сперечатися про GRO і почніть перевіряти фізичний хост: правильність посадки, райзери, налаштування BIOS щодо PCIe power management і платформену прошивку.
Оффлоади без забобонів: коли вони допомагають, коли шкодять
Оффлоади не злі. Це функції продуктивності, що переміщують роботу з CPU на NIC (або амортизують роботу в ядрі). Вони також часто служать козлом відпущення, бо їх легко вимкнути, а симптоми переривчасті. Той факт, що перемикач змінює симптоми, не означає, що ви зрозуміли причину.
Знайте, що ви перемикаєте
- TX checksum offload: ядро передає пакет із чексуом «щоб заповнити»; NIC рахує контрольну суму. Захоплення на хості можуть показувати «погану суму» тому, що вона ще не обчислена.
- TSO/GSO: великі TCP сегменти створюються стеком і сегментуються пізніше (NIC або ядро). Чудово для пропуску; може посилити брусті.
- GRO: згортає отримані пакети в більші SKB перед подачею в стек. Зберігає CPU; може змінити характеристики затримки.
- LRO: подібна концепція, але керована NIC; може погано взаємодіяти з інкапсуляціями і легше ламати семантику пакетів.
- VLAN offloads: NIC обробляє VLAN-теги; зазвичай нормально, інколи болісно при bridging або дивній поведінці комутатора.
Ось підхід для дорослих: розглядайте оффлоади як змінні в експерименті. Перемкніть один, виміряйте лічильники, виміряйте симптоми аплікації і вирішіть, чи знайшли реальний баг або просто перенесли вузьке місце.
Коли доцільно вимикати оффлоади
Вимикайте оффлоад тимчасово, коли:
- Є доказ скидань драйвера корельованих з функцією (наприклад, Tx hang з TSO під конкретним трафіком).
- Дебагуєте захоплення пакетів і потрібні коректні контрольні суми на хості.
- Працюєте з інкапсуляцією/тунелюванням (VXLAN/Geneve) і підозрюєте, що оффлоад шлях поламан на конкретному NIC/драйвері.
І тримайте його вимкненим лише якщо не можете оновити драйвер/прошивку/ядро вчасно і витрати CPU прийнятні.
Коли вимкнення оффлоадів — це культ
Вимикання оффлоадів — це культ, коли:
- Проблема — флапи лінку (оффлоади не тріпають кабель).
- RX CRC помилки ненульові (checksum offload не створює CRC помилок на дроті).
- Softnet drops — справжня проблема (вимкнення оффлоадів часто збільшує CPU роботу і погіршує стан).
Жарт #1: Вимикання всіх оффлоадів — це як витягати батарейки з пожежного датчика, бо він голосно пищить. Вогонь все одно переможе.
IRQs, RSS, кільця буферів і пастка «дропи без помилок»
Один із найпоширеніших шаблонів розривів на швидких NIC: лінк стабільний, CRC помилок немає, комутатор виглядає чистим, але аплікації повідомляють таймаути. Під капотом хост дропає пакети, бо не встигає обслуговувати інтеррути і спустошувати черги. Це не теорія; це те, що відбувається, коли 10/25/40/100G NIC зустрічається з CPU, який зайнятий буквально чимось іншим.
Що зазвичай означають “rx_missed_errors” і “rx_no_buffer”
Ці лічильники зазвичай означають, що NIC мав кадри для доставки, але не зміг помістити їх у пам’ять хоста, бо приймальне кільце було повне або не було доступних буферів. Причини включають:
- Занадто мало RX дескрипторів (розмір кільця занадто малий для сплесків).
- Інтеррупт-модерація надмірно агресивна (пакети накопичуються, а потім переповнюються).
- Голод CPU для ksoftirqd/softirq контексту.
- Погана афініті для IRQ (всі черги прив’язані до одного CPU, часто CPU0, бо світ жорстокий).
- NUMA mismatch (інтеррути NIC обробляються на віддаленому сокеті).
Розміри кілець: грубий, але ефективний інструмент
cr0x@server:~$ sudo ethtool -g eno1
Ring parameters for eno1:
Pre-set maximums:
RX: 4096
RX Mini: 0
RX Jumbo: 0
TX: 4096
Current hardware settings:
RX: 512
RX Mini: 0
RX Jumbo: 0
TX: 512
Значення: Ви використовуєте 512 дескрипторів, хоча NIC підтримує 4096. Це не помилка, але не стійко до сплесків.
Рішення: Якщо спостерігаєте сплески/мікросплески і missed errors — збільшіть кільця до розумного розміру (наприклад, 2048) і виміряйте вплив на пам’ять і латентність.
cr0x@server:~$ sudo ethtool -G eno1 rx 2048 tx 2048
Значення: Ви збільшили буферизацію на межі NIC. Це може зменшити дропи під час сплесків за рахунок додаткової латентності і використання пам’яті.
Рішення: Якщо ваша проблема — дропи від мікросплесків, це часто допомагає швидко. Якщо проблема — стале перевантаження, це тільки відкладає неминуче.
Інтеррупт-модерація: компроміс латентність/CPU, про який ніхто у вашій організації не документує
Об’єднання інтерруптів зменшує навантаження на CPU шляхом пакетування інтерруптів. Але якщо ви занадто агресивно об’єднуєте, то можете додати сплески затримок і створити переповнення кілець під час сплесків.
cr0x@server:~$ sudo ethtool -c eno1 | head -n 40
Coalesce parameters for eno1:
Adaptive RX: on TX: on
rx-usecs: 50
rx-frames: 64
tx-usecs: 50
tx-frames: 64
Значення: Adaptive coalescing увімкнено, і є базові пороги в мікросекундах/кадрах. Адаптивні режими можуть бути чудовими або осцилювати під певним навантаженням.
Рішення: Якщо женетеся за короткими затримками, розгляньте тимчасове вимкнення adaptive coalescing і встановлення консервативних фіксованих значень. Виміряйте хвостову латентність і дропи. Не «оптимізуйте» в темряві.
IRQ афініті: коли дефолт — це «надія»
Ubuntu може запускати irqbalance, який намагається розподілити інтеррупти. Іноді це працює. Іноді ваше навантаження настільки чутливе, що ви хочете детерміноване розміщення, особливо на NUMA-системах.
cr0x@server:~$ systemctl status irqbalance --no-pager
● irqbalance.service - irqbalance daemon
Loaded: loaded (/usr/lib/systemd/system/irqbalance.service; enabled; preset: enabled)
Active: active (running) since Mon 2025-12-29 09:12:12 UTC; 3h 1min ago
Значення: irqbalance активний. Це нормально, але не завжди оптимально.
Рішення: Якщо ви бачите одну гарячу чергу або NUMA віддалені інтеррути — розгляньте прив’язку IRQ NIC до локальних CPU і виключення цих CPU від шумних сусідів. Це особливо важливо на серверах сховищ і гіпервізорах.
Жарт #2: Налаштування IRQ — як планування посадки в офісі: всі погоджуються, що це важливо, і ніхто не любить збори, де це змінюють.
Помилки канального рівня та на боці комутатора, що маскуються під проблеми Linux
Linux отримує звинувачення, бо його логи читабельні, а логи комутатора — за тикетом. Тим не менше фізичний рівень і комутатор — часті винуватці. Особливо коли відмова переривчаста.
Фізичні індикатори, які повинні припинити дискусію «це ядро»
- CRC/alignment/symbol помилки, що ростуть під час інцидентів.
- Зростання корекцій FEC (поширено на вищих швидкостях; сильна корекція може передувати дропам).
- Цикли автонеготації, видимі як повторні down/up лінку.
- Зміни швидкості/дуплексу або сюрпризи типу «link is up 1Gbps».
На стороні хоста ви не завжди бачите деталі FEC, але бачите достатньо, щоб обґрунтувати ескалацію.
EEE і управління живленням: смерть від «зелених» дефолтів
Якщо бачите періодичні мікро-перерви і все інше виглядає чистим — перевірте, чи ввімкнено Energy Efficient Ethernet (EEE). Змішане обладнання може поводитися погано.
cr0x@server:~$ sudo ethtool --show-eee eno1
EEE Settings for eno1:
EEE status: enabled - active
Tx LPI: 1 (on)
Supported EEE link modes: 1000baseT/Full 10000baseT/Full
Advertised EEE link modes: 1000baseT/Full 10000baseT/Full
Link partner advertised EEE link modes: 1000baseT/Full 10000baseT/Full
Значення: EEE активний. Це не автоматично погано, але часто змінна в переривчастій латентності і коротких зупинках.
Рішення: Якщо підозрюєте EEE — вимкніть його на обох кінцях для тестового вікна і спостерігайте, чи зникають переривання.
cr0x@server:~$ sudo ethtool --set-eee eno1 eee off
Bonding і LACP: надійні при коректній конфігурації, хаотичні при припущеннях
Збої bonding часто виглядають як випадкові розриви, бо хешування відправляє деякі потоки по поламаному шляху, а інші проходять. Ви побачите «деякі сервіси нестабільні», а не «хост упав».
cr0x@server:~$ cat /proc/net/bonding/bond0
Ethernet Channel Bonding Driver: v6.8.0-31-generic
Bonding Mode: IEEE 802.3ad Dynamic link aggregation
Transmit Hash Policy: layer3+4 (1)
MII Status: up
MII Polling Interval (ms): 100
Up Delay (ms): 0
Down Delay (ms): 0
Slave Interface: eno1
MII Status: up
Aggregator ID: 2
Actor Churn State: churned
Partner Churn State: churned
Slave Interface: eno2
MII Status: up
Aggregator ID: 1
Actor Churn State: churned
Partner Churn State: churned
Значення: Churned стани вказують на нестабільність переговорів LACP. Це не проблема оффлоаду Linux; це проблема контрольної площини агрегації лінків.
Рішення: Залучіть команду комутатора з цими доказами. Перевірте режим LACP (active/passive), trunking VLAN і що обидва лінки термінуються в одному LACP-групі. Також перевірте таймери і чи комутатор не блокує один член через помилки.
Три корпоративні історії (анонімізовано, болісно правдоподібні)
Міні-історія 1: Інцидент через неправильне припущення
Середня компанія тримала внутрішній кластер об’єктного сховища на Ubuntu-серверах. Симптом — «випадкові розриви» між шлюзовими вузлами і бекендом сховища. Це відбувалося переважно в робочий час, тож усі підозрювали «навантаження», але ніхто не наважився його кількісно виміряти.
Перше припущення було класичним: «це регресія ядра». Команда недавно перейшла на нове ядро і новий драйвер NIC, і час підозріло збігався. Вони відкотили два хости. Проблема залишилась. Відкотили ще два. Все одно лишалося. Тепер у них був змішаний флот з непослідовною поведінкою і без кореневої причини. Надійність не покращилася; стало важче її аналізувати.
Коли хтось нарешті викликав ethtool -S, вони помітили, що rx_crc_errors не нуль. Невеликий, але він зростав точно під час скарг на розриви. Це зламало наратив. CRC помилки не з’являються від sysctl. CRC помилки — це фізичний рівень.
Фактична причина була болісно побутова: партія DAC кабелів була маргінальною для 10G у специфічному розташуванні стійки з різкими згинами і натисненими конекторами. Під температурними змінами помилки росли, LACP шурувався, і деякі потоки були чорними ямами достатньо довго, щоб ламати сесії сховища. Виправлення — заміна кабелів і перепідключення оптики. Відкат ядра потім скасували, коли всі перестали сіпатися.
Урок не в «перевірці кабелів». Урок — не починайте з найемоційнішої теорії. Почніть з лічильників, які можуть її спростувати.
Міні-історія 2: Оптимізація, що відстріляла в ногу
Команда SaaS мала проблему латентності на API-шарі, і хтось вирішив, що rate інтерруптів NIC «занадто високий». Вони увімкнули агресивну інтеррупт-модерацію і налаштували її, доки графіки CPU не заспокоїлися. Святкували. CPU впав. Написали внутрішню замітку про «виграш продуктивності».
Через два тижні клієнти повідомили про випадкові зависання 1–2 секунди під піковим трафіком. Це не відобразилося в середній латентності, лише у хвостах. Ретрансмити трохи зросли, але не настільки, щоб підняти наявні алерти. Сервіс здавався здоровим у більшості дашбордів, саме так хвостова латентність любить працювати: ховатися в середніх як професіонал.
На уражених хостах rx_missed_errors повільно росли. Softnet drops стрибали під час мікросплесків. NIC не був «занадто інтерруптивним». Він виконував свою роботу. Нові налаштування coalescing відкладали обробку RX достатньо, щоб кільця переповнювалися під час коротких сплесків. Оптимізація працювала для графіків CPU і провалила користувацький досвід.
Виправлення — відкат до adaptive coalescing з консервативними межами і помірне збільшення RX ring size. Також додали моніторинг softnet drops і NIC missed errors, бо «я зменшив інтеррупти» не є SLO, орієнтованим на користувача.
Міні-історія 3: Нудна, але правильна практика, що врятувала день
Фінансово орієнтована організація працювала набір Ubuntu 24.04 KVM гіпервізорів з критичними внутрішніми навантаженнями. Надходили скарги від декількох орендаторів: коротка втрата пакетів, інколи TCP зупинки, нічого послідовного. Мережна команда готова була звинуватити віртуальний свічинг. Платформна команда — ToR комутатори. Усі були готові звинуватити всіх.
Що врятувало їх — не геній. Це дисципліна. У них була постійна практика: кожен хост відправляв логи ядра, статистику NIC та softnet counters у центральну систему з кроком 30 секунд, і зберігали кілька днів високої роздільності. Ніякого геройського дебагу не треба було. Дані вже були.
Коли виникали інциденти, вони корелювали три сигнали: (1) AER скориговані PCIe помилки в journalctl, (2) повідомлення NIC “Reset adapter”, і (3) короткі падіння пропускної здатності гостів. Шаблон повторювався на підмножині хостів — той самий модель обладнання, та сама версія BIOS.
Виявилось, що це проблема платформної прошивки в взаємодії з PCIe керуванням живленням. В певних станах NIC трохи гикав, скидався і відновлювався. Виправлення — оновлення прошивки від вендора плюс вимкнення конкретного PCIe ASPM параметра в BIOS як тимчасова міра. Жодних перемикань оффлоадів. Жодних нічних замін кабелів. Просто нудні докази і вікно змін.
Найкраще: вони могли довести, що виправлення спрацювало, бо ті самі сигнали втихомирилися. Ніяких закриттів на основі відчуттів.
Поширені помилки: симптом → корінна причина → виправлення
-
Симптом: «Мережеві розриви», і
journalctl -kпоказує NIC Link is Down/Up.
Корінна причина: Фізичний флап лінку (поганий кабель/DAC, оптика, автонег, помилки порту комутатора, EEE).
Виправлення: Перевіритиethtool -Sна CRC/symbol помилки, вимкнути EEE для тесту, замінити кабель/оптику, валідувати конфіг порту комутатора. -
Симптом: Лінк залишається up, але ви бачите Detected Tx Unit Hang / Reset adapter.
Корінна причина: Баг драйвера/NIC прошивки, PCIe/AER проблеми або крайовий випадок черг/інтерруптів під навантаженням.
Виправлення: Зібрати кортеж драйвера/прошивки, корелювати з AER логами, оновити прошивку, тестувати новіше kernel/HWE, налаштувати coalescing/rings, розглянути vendor driver. -
Симптом: Немає флапу лінку, немає CRC помилок, але TCP таймаути і ретрансмити стрибають.
Корінна причина: Хост дропає (softnet drops, RX ring overflow, голодування CPU), або upstream мікросплески.
Виправлення: Перевірити/proc/net/softnet_stat,ethtool -Smissed errors, тюнити rings/queues/IRQ affinity, валідувати буферизацію комутатора. -
Симптом: Маленькі пакети працюють, великі трансфери зависають; пінги успішні; SSH “іноді зависає”.
Корінна причина: Невідповідність MTU або PMTU blackhole (ICMP заблоковано).
Виправлення: Аудит MTU кінець в кінець; запускping -M do; дозволити ICMP fragmentation-needed; встановити коректний MTU на тунелях та VLAN. -
Симптом: Тільки деякі потоки фейляться, особливо за bonding; проблеми виглядають «випадковими» серед клієнтів.
Корінна причина: LACP хешування спрямовує деякі потоки на пошкоджений член; churn/несумісність партнера.
Виправлення: Інспектувати/proc/net/bonding; перевірити LACP на боці комутатора і політику хешування; перевірити помилки членів; розглянути видалення проблемного члена до виправлення. -
Симптом: Захоплення показує «погану суму» і люди панікують.
Корінна причина: Артефакт checksum offload у шляху захоплення.
Виправлення: Перевірити on-wire capture (SPAN/TAP) або тимчасово вимкнути TX checksum offload для дебагу. -
Симптом: Вимкнення GRO «вирішує» проблему, але CPU взлітає і пропуск падає.
Корінна причина: Ви замаскували глибшу проблему (баг драйвера або перевантаження), змінивши поведінку батчінгу.
Виправлення: Розглядайте це як діагностичну підказку; рухайтеся до driver/firmware/kernel виправлень або корекції coalescing/rings; тримайте GRO вимкненим лише як документовану міру.
Чеклісти / покроковий план
Чекліст A: Збирайте докази під час наступного інциденту (15 хв, без гадань)
- Зафіксуйте часове вікно симптомів (початок/кінець). Якщо вікна немає — інциденту немає.
- Зберіть повідомлення ядра:
cr0x@server:~$ sudo journalctl -k --since "30 minutes ago" > /tmp/kern.logРішення: Флап лінку проти скидання проти нічого в логах вказує, куди рухатись далі.
- Зробіть знімок лічильників NIC до і після відтворення:
cr0x@server:~$ sudo ethtool -S eno1 > /tmp/eno1.stats.beforecr0x@server:~$ sleep 60; sudo ethtool -S eno1 > /tmp/eno1.stats.afterРішення: Зростання CRC/symbol помилок = фізичний; зростання missed/no_buffer = приймальний шлях хоста.
- Знімок softnet статистики:
cr0x@server:~$ cat /proc/net/softnet_stat > /tmp/softnet.beforecr0x@server:~$ sleep 60; cat /proc/net/softnet_stat > /tmp/softnet.afterРішення: Зростання дропів/time_squeeze означає, що ядро не встигає.
- Перевірте ретрансмити/таймаути:
cr0x@server:~$ nstat -az | egrep -i "TcpRetransSegs|TcpTimeouts" TcpTimeouts 18 TcpRetransSegs 3490Рішення: Якщо TCP це бачить — це реальні втрати/затримки, а не баг аплікації.
Чекліст B: Зміни оффлоадів і тюнінгу без погіршення
- Робіть одну зміну за раз. Необговорюване правило.
- Перед зміною зафіксуйте поточні налаштування:
cr0x@server:~$ sudo ethtool -k eno1 > /tmp/eno1.offloads.beforecr0x@server:~$ sudo ethtool -c eno1 > /tmp/eno1.coalesce.beforecr0x@server:~$ sudo ethtool -g eno1 > /tmp/eno1.rings.beforeРішення: Тепер ви можете відкотити зміни і порівняти.
- Оберіть найменшу релевантну зміну (наприклад, відключити GRO, а не «всі оффлоади»).
- Відтворіть під схожим навантаженням і порівняйте лічильники та симптоми.
- Якщо зміна допомагає — вирішіть, чи це міграція або остаточне рішення. Міграції треба документувати і мати план видалення.
Чекліст C: Фізична і комутаторна валідація, яку можна попросити точково
- Надайте команді комутатора: timestamps, серверний інтерфейс, переговорену швидкість/дуплекс і чи Linux логував link down/up.
- Запитайте: лічильники помилок порту (CRC/FCS), статистику FEC, історію повторних переговорів лінку, стан LACP і лічильники буферів/дропів.
- План мінімального swap-тесту: перемістіть кабель/оптику на відомо робочий порт або поміняйте оптику між гарним і поганим хостом.
- Після swap перевірте, чи помилки пішли з компонентом або залишилися на порту.
FAQ
1) Чому моя аплікація каже «відключено», хоча інтерфейс ніколи не падав?
Тому що TCP може таймаутити без флапу лінку. Втрати пакетів, мікросплески, переповнення RX-кілець або PMTU blackhole можуть зупинити потоки настільки, що аплікація здаться. Перевірте ретрансмити (nstat), softnet drops і NIC missed errors.
2) Чи варто вимикати GRO/TSO/checksum offloads, щоб виправити випадкові дропи?
Не як перший крок. Якщо є флап лінку або фізичні помилки, оффлоади не мають значення. Якщо підозрюєте баг оффлоада — вимикайте одну функцію тимчасово і доводьте ефект лічильниками і логами. Утримуйте увагу на вартості CPU.
3) tcpdump показує погані контрольні суми. Чи NIC псує пакети?
Часто ні. З checksum offload ядро передає пакети NIC до обчислення контрольної суми; tcpdump може спостерігати їх «до чексума». Підтвердіть on-wire capture або тимчасово вимкніть TX checksum offload для дебагу.
4) Який найшвидший спосіб відрізнити «кабель/комутатор» від «налаштування хоста»?
CRC/alignment/symbol помилки та явні повідомлення link down/up — швидкі індикатори фізики. Missed errors, softnet drops і стабільний лінк вказують на приймальний шлях хоста і тюнінг CPU/IRQ/rings.
5) Чому я бачу дропи, але немає помилок в ip -s link?
ip -s link не завжди показує драйвер-специфічні причини дропів. Використовуйте ethtool -S для детальних лічильників і /proc/net/softnet_stat для дропів ядра.
6) Чи може irqbalance викликати випадкові розриви?
Воно може сприяти, якщо інтеррути зосереджуються або прив’язуються погано на NUMA системі, особливо під навантаженням. Рідко — єдина причина, але може перетворити «гарно» в «нестабільно», коли маржа малий. Перевірте розподіл черг через /proc/interrupts.
7) Я використовую bonding (LACP). Чому зачіпаються тільки деякі клієнти?
Через хешування. Деякі потоки потрапляють на поганий член лінку, інші — на здоровий. Перевірте /proc/net/bonding/bond0 на churn і підтвердіть конфіг LACP на боці комутатора та помилки членів.
8) Як зробити, щоб ethtool налаштування зберігалися після перезавантаження в Ubuntu 24.04?
Не покладайтеся на ручні команди. Використовуйте systemd unit, udev правило або нативні хуки вашого мережевого менеджера, щоб застосовувати ethtool -K, -G, -L і -C при піднятті інтерфейсу. Точний метод залежить від того, чи ви використовуєте NetworkManager, systemd-networkd або netplan.
9) Чи часто оновлення ядра в Ubuntu 24.04 викликають нестабільність NIC?
Може бути, але «часто» — перебільшення. Частіше оновлення змінюють таймінги (інтеррути, батчинг, дефолти управління живленням) і виявляють маргінальний фізичний рівень або баг прошивки. Ставте оновлення ядра як кореляцію, потім доводьте механізм логами і лічильниками.
10) Що робити, якщо все виглядає чистим, але користувачі все одно повідомляють про зависання?
Тоді ваша видимість недостатня. Додайте метрики з вищою роздільністю: softnet drops, NIC missed errors, ретрансмити і дропи на стороні комутатора. Багато проблем відбуваються в субхвилинних сплесках, які 5-хвилинні усереднення ввічливо згладжують.
Висновок: наступні кроки, які можна впровадити цього тижня
Випадкові розриви не випадкові. Вони просто відбуваються в розриві між вашими припущеннями й доказами. Закрийте розрив — і проблема зазвичай зникає.
- Інструментуйте спочатку: почніть збирати витяги
journalctl -k,ethtool -Sлічильники та знімки/proc/net/softnet_statнавколо інцидентів. - Класифікуйте режим відмов: флап лінку vs NIC reset vs host drops vs MTU/PMTU vs LACP/бріджинг.
- Робіть одну зміну за раз: розміри кілець, кількість черг, coalescing або один оффлоад. Вимірюйте до/після через лічильники і ретрансмити.
- Ескалюйте з доказами: якщо є CRC/symbol помилки або LACP churn — віднесіть це в команду комутатора з часовими мітками. Ви не «просите мережу глянути», ви подаєте справу.
- Стабілізуйте надовго: узгодьте оновлення драйверів/прошивок з оновленнями ядра і моніторьте лічильники, що реально прогнозують біль (missed errors, softnet drops, ретрансмити, події лінку).
Якщо зробите хоча б одну річ: перестаньте ставитися до оффлоадів як до ритуалу. Ставтеся до них як до експерименту. Мережа поважатиме вас більше. І ваш пейджер теж.