Налаштування Swap і OOM Killer для керування пам'яттю

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

Налаштування swap Linux: чому сервіс падає під час піку пам'яті

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

Це не помилка графіків: нестача оперативної пам'яті проявляється не в загальному обсязі, а в доступності сторінок у потрібній зоні та в здатності ядра виділити безперервну ділянку. У логах Linux це виглядає так: oom killer завершив процес, а супервізор підняв його знову.

Жертву ядро обирає за oom_score з поправкою oom_score_adj, і найчастіше нею стає основний робочий процес, а не той, хто накопичив витік: у довгоживучого сервісу вище споживання — вищий і шанс потрапити під завершення.

Перезапуск повертає з'єднання, але втрачає недописані транзакції, а за кілька хвилин картина повторюється, якщо причину не усунули.

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

vm.swappiness визначає, наскільки охоче витісняються анонімні сторінки, а ліміти cgroup і режим vm.overcommit_memory — кому й скільки взагалі дозволено зайняти.

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

Ефект керованої підкачки: відгук і стабільність

Ефект керованої підкачки видно не за графіком вільної пам'яті, а за кількістю інцидентів.

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

  • Аварійні перезапуски. Кількість падінь процесів через нестачу пам'яті падає на порядок: замість десятків подій залишаються поодинокі, і кожна розбирається як аномалія, а не як фон.
  • Передбачувана деградація. Під піком зростає час відповіді, але черги не рвуться: холодні сторінки йдуть у підкачку, гарячий робочий набір залишається в пам'яті, відмова сервісу не настає.
  • Рівний відгук на сплесках. Поріг вільних сторінок і агресивність витіснення виставлені під навантаження, тому короткі bursts проходять без провалів — сервіс сповільнюється плавно, а не обривається.
  • Ізоляція наслідків. Ліміти пам'яті для груп процесів і ранній вбивця за тиском на пам'ять розбираються лише з проблемним сервісом; сусіди на тій самій машині не втрачають доступність.
  • Знятий клас інцидентів. Нічні підняття та сторінки чергового через падіння за пам'яттю зникають із потоку — залишаються завдання на планове розширення, а не на гасіння.
  • Швидке повернення. Після піку сервіс входить у робочий режим за десятки секунд, без повторного прогріву кешу та ручного втручання.

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

Способи організації підкачки: порівняння та обмеження

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

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

Варіант Коли підходить Обмеження
Swap-файл на локальному накопичувачі Швидко розгорнути, змінити розмір, додати другу область Потребує вільного місця у файловій системі, під час зміни розміру фрагментується
Окремий розділ підкачки Передбачувана затримка, сервери без гібернації, СУБД Розмір фіксується під час розмітки, змінюється лише перерозбиттям
Стиснена підкачка в оперативній пам'яті Малопам'ятні віртуальні машини, вузли без локального диска Витрачає такти процесора, не рятує за справжнього дефіциту пам'яті, не переживає перезавантаження
Том на менеджері логічних томів Потрібно змінювати розмір на ходу без зупинки служб Додатковий шар абстракції, снапшоти непомітно з'їдають місце
Область на віддаленому блоковому пристрої Кластери без локальних дисків, аварійний резерв Мережева затримка робить її марною під навантаженням

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

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

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

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

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

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

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

Комплект документів і конфігурацій після впровадження

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

Кожен розрахований на чергового інженера, який відкриє його в момент інциденту, а не «колись прочитаємо».

  • Конфігурація підкачки — файл або розділ із записом у fstab, значення vm.swappiness, overcommit і cache_pressure, поруч коментар: чому вибрано таку поведінку і що зміниться за повернення до значень за замовчуванням.
  • Політики за сервісами — ліміти пам'яті в cgroup і пріоритети oom_score_adj: хто отримує шанс вижити під тиском, кого ядро звільняє першим.
  • Схема розміщення — на якому вузлі та носії лежить область підкачки, як вона співвідноситься з томами даних і де вузькі місця за дисковими операціями.
  • Регламент чергової зміни — покрокові дії за зростання споживання пам'яті та спрацювання OOM Killer: що дивитися, що перезапускати, коли викликати старшого інженера.
  • Документація з пам'яті — профіль споживання за сервісами, межі норми, типові причини зростання та журнал змін налаштувань.
  • Перевірки та план відкату — метрики, оповіщення й команди діагностики в готовому вигляді плюс порядок повернення попереднього профілю, якщо зміни погіршили поведінку сервісу.

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

Кейс: усунення аварійних перезапусків під час піків

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

Підсумок: сім інцидентів на місяць, кожен із ручним розбором; відновлення займало до 45 хвилин, і частина запитів у це вікно губилася.

Що змінили

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

Для контейнерів задали жорсткі ліміти та порядок завершення — першим іде фоновий обробник, фронтальний сервіс залишається в строю.

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

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

Показник До Після
Аварійні перезапуски сервісу 7 на місяць 1 за квартал
Час відновлення сервісу до 45 хвилин вручну до 3 хвилин автоматично
Піки, поглинуті підкачкою не вимірювалися 9 з 10
Нічні виклики чергового 4–6 на місяць 0

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

Чим swap-файл відрізняється від окремого розділу?

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

Виділений розділ — заздалегідь відрізаний шматок розмітки. Ядро звертається до нього напряму, без прошарку файлової системи, тому накладні витрати на введення-виведення нижчі, а поведінка під навантаженням передбачуваніша.

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

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

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

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

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

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

Часті запитання щодо поведінки системи за нестачі пам'яті

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

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

Як зрозуміти, що сервіс упав саме через пам'ять?

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

Чи потрібна підкачка, якщо оперативної пам'яті достатньо?

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

Чи не стане сервіс працювати повільніше?

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

Як це працює в контейнерах і чи застосовується без перезавантаження?

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

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

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

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

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

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

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

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

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

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

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