Налаштування ядра Linux для високонавантажених серверів

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

Налаштування ядра Linux: де впирається навантажений сервер

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

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

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

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

Стрибкоподібні затримки на піках — це про планувальник завдань і розподіл мережевих переривань по ядрах.

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

Окремо перевіряємо таблицю з'єднань: при її переповненні ядро починає втрачати пакети вже встановлених сесій.

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

Що дає налаштоване ядро під піковим навантаженням

Ядро Linux за замовчуванням розраховане на універсальне навантаження: черги з'єднань, ліміти дескрипторів, поведінка планувальника та підсистеми пам'яті підібрані під усереднений профіль.

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

Затримка відгуку. Коли параметри приймання з'єднань і мережеві буфери приведені до реального профілю, частина очікування на вході в застосунок зникає — запити не стоять у переповненій черзі.

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

Пропускна здатність на тому самому залізі зростає без заміни серверів — завдяки розкладці потоків по ядрах, планувальника введення-виведення під профіль диска та осмислених лімітів пам'яті.

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

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

Порівняння підходів до налаштування ядра

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

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

Варіант Коли підходить Обмеження
Типовий набір параметрів Типовий сервіс без виражених піків, потрібен передбачуваний старт Не враховує профіль застосунку: частина значень не дає ефекту, частина зміщує баланс між пам'яттю та диском. Зміни погано пояснювані під час розбору збою
Точкове налаштування під сервіс Відомі вузькі місця: черги з'єднань, час відгуку, зростання кількості відкритих файлів Крихкість: зміна версії застосунку або схеми роботи ламає припущення. Потрібна повторна ревізія при кожному великому оновленні
Повний розбір з навантажувальною перевіркою Критичний контур, де помилка коштує простою; є стенд і відтворюваний профіль навантаження Довше за термінами та дорожче за часом команди; виміри недійсні, якщо стенд не зіставний з продакшеном

Що враховувати при виборі

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

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

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

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

  1. Аудит сервера та зняття метрик. Збираємо базову лінію під реальним навантаженням: завантаження процесорів, черги на диск, розподіл пам'яті, мережеві переривання, кількість з'єднань. Виміри робимо на піку, а не в спокійні години — інакше вузьке місце не проявиться.
  2. Пошук вузького місця. Зіставляємо метрики і визначаємо, де втрачається продуктивність: пам'ять витісняється на диск, черга введення-виведення не встигає, обробка переривань лягає на одне ядро.
  3. Схема змін. Фіксуємо, які параметри ядра змінюємо, у яких межах і що це дає за розрахунком. Поруч — план відкату та список того, що свідомо не чіпаємо, щоб не платити за приріст нестабільністю.
  4. Впровадження. Правки вносимо частинами й оборотно, вихідні конфігурації зберігаємо, де можливо — без перезавантаження. Після кожного кроку звіряємося з метриками і зупиняємося, якщо ефект не підтверджується.
  5. Перевірка на навантаженні. Проганяємо той самий профіль трафіку і порівнюємо до/після: час відгуку, пропускну здатність, поведінку на піку та при відмові сусіднього сервісу. Дивимося не лише середні, а й хвіст затримок.
  6. Передача регламенту. Віддаємо документ: що змінено і чому, які значення вихідні, як відкочувати, які метрики та пороги тримати на моніторингу. Далі сервер веде ваша команда.

Конфігурації, схеми та регламенти на виході

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

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

  • Файли конфігурації — параметри ядра, ліміти процесів і правила мережевих черг розкладені за призначенням (sysctl.d, limits.d, налаштування планувальника введення-виведення), а не звалені в один загальний файл, де правка одного сервісу змінює поведінку інших.
  • Карта сервісів — що за процес, які порти й сокети тримає, до яких черг оброблюваних подій і дескрипторів звертається, якою службою піднімається і з чим пов'язаний за залежностями.
  • Опис лімітів — таблиця «параметр — вибране значення — обґрунтування — межа деградації»: видно, звідки взялося число і що зміниться при зсуві вгору або вниз.
  • Інструкція з відкату — покрокове повернення до попереднього профілю: який файл відновити, яку команду застосувати, за якими ознаками переконатися, що стенд повернувся в робочий стан.
  • Регламент обслуговування — що і з якою періодичністю перевіряється, які зміни проходять погодження, як ведеться історія правок і хто відповідає за вузол у чергуванні.
  • Профілі під ролі — окремі набори для балансувальника, бази даних і вузла застосунків, щоб правки під одне навантаження не ламали інше.
  • Скрипти застосування та звірки — розгортання конфігурації з репозиторію зі збереженням знімка фактичних значень до і після; повторний запуск не змінює результат, розбіжності видно відразу.

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

Кейс: зняли деградацію під піковим навантаженням

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

Деградація йшла через мережевий стек, а не через логіку застосунку.

Частка клієнтів, які не дочекалися встановлення з'єднання, зросла з 0,2% до 7%, час відповіді на 99-му процентилі — вчетверо, а хвіст помилок після піку тримався ще близько двадцяти хвилин: черга на приймання не встигала розсмоктуватися, робочі процеси впиралися в ліміт дескрипторів, частина сокетів застрягала в очікуванні закриття.

Налаштували приймання з'єднань під фактичну довжину черги: підняли net.core.somaxconn і tcp_max_syn_backlog, розширили діапазон локальних портів і включили перевикористання сокетів в очікуванні закриття.

Далі — fs.file-max і ліміти дескрипторів для робочих процесів, вимкнені прозорі величезні сторінки, помірний скид пам'яті замість агресивного swap і мережеві переривання, розкладені по ядрах замість обробки на одному.

Як підтвердили результат

Прогнали той самий профіль трафіку двічі, порівнюючи розподіл часу відповіді, а не середнє.

Відмови з'єднання пішли в нуль, 99-й процентиль повернувся до рівня звичайного навантаження, хвіст після піку скоротився з двадцяти хвилин до хвилини, а сам пік система тримає з чотириразовим запасом за з'єднаннями.

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

Чим відрізняється налаштування ядра Linux від типових шаблонів?

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

Для застосунку з довгими з'єднаннями і холодним кешем такий набір нешкідливий, а в бази з гарячим робочим набором у пам'яті він прискорює дисковий введення-виведення і роздуває хвостову затримку.

Тому першим кроком іде профіль навантаження, а не правка параметрів ядра: скільки з'єднань за секунду відкривається і закривається, яка частка часу проходить в очікуванні мережі, чи є сплески за пам'яттю і записом на диск.

Звідси вже видно, що чіпати — чергу вхідних з'єднань, перевикористання сокетів у стані TIME_WAIT, пороги скидання брудних сторінок або розмір huge pages.

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

Вимкнення прозорих huge pages знімає залипання в одних баз і додає накладні витрати на трансляцію адрес в інших; агресивне скидання брудних сторінок укорочує сплески запису, але б'є по послідовних потоках. Параметр, вирваний з контексту, легко перетворюється на джерело відмов під піком.

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

Технічні сумніви перед стартом робіт

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

Наскільки безпечно змінювати параметри ядра на живому сервері?

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

Чи потрібен простій сервісу?

Як правило, ні: мережеві буфери, ліміти дескрипторів і планувальник введення-виведення налаштовуються без розриву з'єднань. Вікно потрібне лише параметрам завантаження ядра.

Як відкочуються налаштування, якщо стало гірше?

Зміни вносимо файлом конфігурації, а не разовими командами, тому відкат — повернення попередньої версії. Попередній стан зберігаємо, поки новий режим не переживе пікові години.

Чи збережуться налаштування після оновлення системи?

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

Як зрозуміти, що вузьке місце саме в ядрі?

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

Обговоримо задачу і повернемося з оцінкою та планом

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

Чим повніші вхідні дані, тим менше ітерацій йде на уточнення і тим конкретнішим виходить план робіт.

До звернення достатньо додати:

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

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

Наші компетенції:

Останні роботи

  • Розробка сайту компанії B2B ADVANCE
    Розробка сайту компанії B2B ADVANCE
    1542
  • Розробка веб-додатків для компанії FEEDME
    Розробка веб-додатків для компанії FEEDME
    1393
  • Розробка веб-сайту для компанії БЕЛФІНГРУП
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    1081
  • Розробка інтернет магазину для компанії FURNORO
    Розробка інтернет магазину для компанії FURNORO
    1368
  • Розробка логотипу компанії B2B Advance
    Розробка логотипу компанії B2B Advance
    815
  • Розробка веб-додатків для компанії Enviok
    Розробка веб-додатків для компанії Enviok
    1139