Управління пам'яттю в Linux: Swap, OOM Killer та Cgroups
12 хв читання - 31 травня 2026 р.

Як працює Linux swap, OOM killer та cgroups - з прикладами конфігурацій для баз даних, веб-серверів та багатокористувацьких VPS-хостів.
Пояснення управління пам'яттю в Linux: swap, OOM killer та cgroups
Linux обробляє пам'ять інакше, ніж більшість операційних систем. Високе використання оперативної пам'яті не завжди є проблемою — ядро активно використовує вільну пам'ять для кешування, щоб пришвидшити читання з диска. Але коли виникає реальне навантаження на пам'ять, спрацюють три механізми: swap, OOM killer та cgroups. Розуміння того, як кожен з них працює та як їх налаштовувати, є різницею між сервером, який плавно сповільнюється під навантаженням, та тим, що виходить з ладу без попередження.
Як Linux управляє сторінками пам'яті
Кожен процес працює у власному віртуальному адресному просторі, розмір якого на 64-бітних системах може досягати 128 ТБ. Ядро відображає ці віртуальні адреси на фізичну оперативну пам'ять за допомогою таблиць сторінок, а буфер перегляду перекладу (TLB) кешує останні запити. Збіг у TLB займає близько 1 наносекунди; промах коштує 20–100 наносекунд, що накопичується у ресурсоємних робочих навантаженнях, таких як бази даних.
Фізична пам'ять поділяється на сторінки розміром 4 КБ, і ядро розділяє їх на дві категорії:
- Сторінки, підкріплені файлами — пов'язані з файлами на диску. Ядро може видаляти чисті або очищати забруднені без необхідності використання підкачки.
- Анонімні сторінки — пам'ять купи та стека без файлу-підкладки. Їх необхідно записати в обмінну пам'ять, перш ніж ядро зможе їх звільнити.
На серверах з високими вимогами до пам'яті велика частка анонімних сторінок означає, що своп задіюється на ранньому етапі. Слідкуйте за si (swap in) та so (swap out) у vmstat 1 — постійні значення, відмінні від нуля, є першим сигналом того, що система перебуває під навантаженням.
Для моніторингу використовуйте відповідний інструмент:
| Інструмент | Найкраще підходить для | Ключовий показник |
|---|---|---|
free -h | Швидкий знімок всієї системи | available колонка |
vmstat 1 | Моніторинг обміну та вводу-виводу в режимі реального часу | si, so |
htop | Інтерактивний перегляд за процесами | Смуги пам'яті, список процесів |
smem | Точне використання пам'яті для кожного процесу | USS (розмір унікального набору) |
/proc/meminfo | Деталі на рівні ядра | MemAvailable, Dirty, Slab |
Одна поширена помилка: перегляд стовпчика free за стовпцем free -h і панікувати. available — ось що має значення. Вона включає пам'ять, яку ядро може звільнити з кешу за запитом. Сервер, який показує лише 512 МБ вільного простору, але 5 ГБ доступного, не має проблем.
Коли обсяг пам'яті падає нижче порогового значення, kswapd демон ядра починає звільняти сторінки у фоновому режимі. Якщо цього недостатньо, ядро переходить до режиму прямого звільнення, блокуючи процеси доти, доки сторінки не будуть звільнені. Саме звідси беруться стрибки затримки. Налаштуйте сповіщення, коли MemAvailable опускається нижче 10–15% від загального обсягу оперативної пам'яті, щоб у вас був час зреагувати.
Налаштування свопу
Своп — це область диска (розділ або файл), куди ядро переміщує неактивні анонімні сторінки, коли оперативна пам'ять заповнюється. Різниця у швидкості є значною: оперативна пам'ять DDR4 має затримку приблизно 100 нс, тоді як SSD-накопичувачі NVMe — близько 100 000 нс, а SSD-накопичувачі SATA — близько 500 000 нс. Обмінна пам'ять є буфером безпеки, а не додатковою оперативною пам'яттю. Сервер, який постійно покладається на обмінну пам'ять, має проблему з пам'яттю, яку збільшення обмінної пам'яті не вирішить.
Використовуйте файл swap замість розділу. Його простіше змінювати за розміром, і для цього не потрібно перерозподіляти розділи.
sudo fallocate -l 2G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfileДодайте файл, щоб /etc/fstab , щоб зберегти дані після перезавантаження. chmod 600 крок є обов'язковим — будь-які дані, вивантажені з оперативної пам'яті, доступні для читання зі swap, тому файл не повинен бути загальнодоступним для читання.
Після створення свопу налаштуйте vm.swappiness. Значення за замовчуванням 60 є агресивним. Для більшості робочих навантажень хостингу бажано, щоб ядро надавало перевагу оперативній пам'яті та використовувало файл підкачки лише як крайній захід:
| Роль сервера | vm.swappiness | vm.vfs_cache_pressure |
|---|---|---|
| Загальний веб-сервер | 10–20 | 50 |
| База даних (MySQL/PostgreSQL) | 1–5 | 50 |
| За замовчуванням (більшість дистрибутивів) | 60 | 100 |
Щодо розміру свопу: 1–2 ГБ достатньо для VPS на 2 ГБ, що обробляє періодичні піки трафіку. На системах з 8 ГБ або більше, фіксований своп розміром 2–4 ГБ зазвичай є достатнім. Мета полягає в тому, щоб надати ядру запобіжний клапан для холодних сторінок, а не розширити загальний обсяг адресованої пам'яті.
На серверах з обмеженим об'ємом оперативної пам'яті та потужним процесором zram створює стиснуту область підкачки в пам'яті, повністю уникаючи дискових операцій вводу-виводу. Це варто врахувати на багатокористувацьких VPS-хостах, де NVMe використовується спільно різними користувачами. Слідкуйте за конфліктами вводу-виводу, якщо підкачка розміщена на тому ж пристрої, що й файли бази даних — інтенсивна підкачка та запис на диск з високою пропускною здатністю погано поєднуються.
OOM-кілер
Коли ядро вичерпує оперативну пам'ять та обмінну зону і не може звільнити достатньо пам'яті іншими засобами, вступає в дію OOM-кілер. Він оцінює процеси за допомогою функції oom_badness() функції:
points = (rss_anon + rss_file + rss_shmem + swapents + pgtables_pages) + (oom_score_adj × totalpages / 1000)Процес із найвищим балом припиняється. Формула надає перевагу процесам, що споживають багато пам'яті, а ядро уникає припинення декількох процесів поспіль, перевіряючи, чи процес вже не був припинений протягом останніх 5 секунд.
У журналах з'являються два типи подій OOM:
- Global OOM — у всій системі закінчилися оперативна пам'ять та обмінний простір. Журнали мають префікс
Out of memory: - Cgroup OOM — контейнер або служба досягли свого
memory.max. Префікс у логахMemory cgroup out of memory:
Щоб переглянути минулі події OOM:
dmesg -T | grep -i "out of memory"
journalctl -k --grep="oom"Зверніть увагу на поле order поле в журналах OOM. Значення, більше за 0, вказує на фрагментацію пам'яті, а не на повне вичерпання — ядро не змогло знайти достатньо суміжних сторінок, навіть маючи вільну пам'ять.
Ви можете вплинути на те, на які процеси націлений OOM-кілер, налаштувавши /proc/<pid>/oom_score_adj. Діапазон значень — від -1000 (ніколи не вбивати) до +1000 (вбивати першими). Для служб, що керуються systemd, налаштуйте це назавжди у файлі модуля:
[Service]
OOMScoreAdjust=-1000Додаткові параметри sysctl для налаштування поведінки OOM:
| Параметр | Значення | Ефект |
|---|---|---|
vm.overcommit_memory | 0 | Режим евристичного перевантаження за замовчуванням |
vm.overcommit_memory | 2 | Строгий режим; запобігає виділенню пам'яті, що перевищує обсяг оперативної пам'яті × overcommit_ratio + swap |
vm.panic_on_oom | 1 | Перезавантаження замість завершення процесу |
vm.oom_kill_allocating_task | 1 | Закриває процес, що викликав OOM, а не найбільшого споживача |
Для проактивного моніторингу перевірте /proc/pressure/memory (Pressure Stall Information, доступно починаючи з ядра 4.20). Слідкуйте за some avg10 значення: нижче 5% — нормальний стан, якщо воно тривалий час перевищує 20%, це означає, що ймовірно наближається подія OOM. Зростаючий allocstall лічильника в /proc/vmstat є ще одним раннім сигналом — він підраховує прямі затримки відновлення пам'яті, які часто передують завершенням через OOM. Такі інструменти, як systemd-oomd або earlyoom можуть реагувати на порогові значення PSI до того, як спрацює OOM-кілер ядра.
Cgroups та обмеження пам'яті
Групи контролю (cgroups) дозволяють організовувати процеси в групи та застосовувати жорсткі обмеження ресурсів. Впроваджені в Linux 2.6.24, вони є основою середовищ виконання контейнерів, включаючи Docker, Podman, Kubernetes та LXC. Ядро відстежує використання пам'яті для кожної cgroup, охоплюючи анонімну пам'ять, сторінки, підкріплені файлами, та об'єкти ядра. Якщо cgroup досягає свого обмеження, ядро звільняє пам'ять у межах цієї групи або запускає OOM-kill у межах cgroup.
Cgroup v1 та v2 відрізняються насамперед своєю структурою. V1 монтує кожен контролер (пам'ять, CPU, ввід-вивід) окремо під /sys/fs/cgroup/<controller>/, що призводить до непослідовного відстеження ресурсів. V2 використовує уніфіковану ієрархію на рівні /sys/fs/cgroup/. Kubernetes перейшов на v2 як стандарт у версії 1.25 і припинив підтримку v1 у 1.31.
Щоб перевірити, яку версію використовує ваша система:
stat -fc %T /sys/fs/cgroup/cgroup2fs означає v2; tmpfs зазвичай означає v1.
| Функція | Cgroup v1 | Cgroup v2 |
|---|---|---|
| Ієрархія | Багаторівнева, для кожного контролера | Один, уніфікований |
| Жорстке обмеження пам'яті | memory.limit_in_bytes | memory.max |
| М'який ліміт пам'яті | memory.soft_limit_in_bytes | memory.high (обмеження) |
| Відстеження використання | memory.usage_in_bytes | memory.current |
| Показники навантаження | Обмежено | Інтегрований PSI |
Ключові елементи керування пам'яттю в cgroup v2:
| Параметр | Тип | Опис |
|---|---|---|
memory.max | Жорстке обмеження | Перевищення цього значення запускає OOM-кілер |
memory.high | М'яке обмеження | Обмежує виділення пам'яті та запускає звільнення пам'яті до досягнення жорсткого обмеження |
memory.low | М'який захист | Пам'ять нижче цього порогу звільняється останньою |
memory.min | Жорсткий захист | Пам'ять нижче цього рівня ніколи не звільняється |
memory.swap.max | Обмеження обміну | Встановіть значення 0, щоб вимкнути обмін для цієї групи cgroup |
memory.oom.group | Логічне значення | Якщо увімкнено, OOM одночасно завершує всі процеси в cgroup |
Практичне правило: встановіть memory.high приблизно на 10–20% нижче memory.max , щоб дати ядру простір для відновлення пам'яті до досягнення жорсткого обмеження. При визначенні розміру memory.max, додайте 20–30% понад пікове використання додатка, щоб врахувати кеш сторінок, який враховується у загальному обсязі пам’яті cgroup.
Керуйте cgroups через systemd, а не записуючи безпосередньо у файлову систему cgroup. Використовуйте директиви файлів одиниць, такі як MemoryMax=, MemoryHigh=, та MemoryMin= для постійних обмежень. Для швидких тестів:
systemd-run --scope -p MemoryMax=512M <command>Для пулів робочих процесів веб-сервера налаштування memory.oom.group=1 забезпечує чисте завершення роботи, якщо один робочий процес перевищує свій ліміт — не залишається ніяких загублених процесів. Для механізмів баз даних memory.min захищає буферний пул від вивільнення під тиском на рівні всієї системи.
Конфігурація пам'яті залежно від ролі сервера
Правильні налаштування пам'яті залежать від того, що робить сервер. Застосування однакової конфігурації до бази даних та веб-сервера PHP зашкодить одному з них.
| Роль сервера | vm.swappiness | Стратегія OOM | Політика Cgroup |
|---|---|---|---|
| База даних | 1–5 | Захист (OOMScoreAdjust=-900) | Використовуйте memory.min для захисту буферного пулу |
| Веб-сервер/сервер додатків | 10–20 | За замовчуванням | Обмеження на пул робочих процесів через memory.max |
| Фоновий робочий процес | 60 | Можна завершити (OOMScoreAdjust=+200) | Регулювання через memory.high |
| Багатокористувацький VPS | 60 (з zram) | За замовчуванням | Жорстка ізоляція для кожного орендаря за допомогою memory.max |
Для MySQL та PostgreSQL виділіть 50–70% доступної оперативної пам’яті для innodb_buffer_pool_size, вимкніть Transparent Huge Pages, щоб зменшити стрибки затримки, та захистіть процес за допомогою OOMScoreAdjust=-900 у файлі модуля systemd.
Для PHP-FPM розмір пулів робочих процесів слід підбирати відповідно до фактичного використання пам'яті. Кожен робочий процес зазвичай використовує 30–100 МБ. Розділіть виділену оперативну пам'ять на середній розмір робочого процесу, щоб отримати безпечне pm.max_children значення. Використовуйте memory.max в cgroups, щоб обмежити пул.
Для робочих навантажень з інтенсивним записом встановіть vm.dirty_ratio на рівні близько 10% та vm.dirty_background_ratio до 3%. Це прискорює очищення забруднених сторінок, запобігаючи значним затримкам вводу-виводу.
Зробіть налаштування ядра постійними, збереживши параметри у /etc/sysctl.d/90-memory.conf. Налаштування, застосовані під час виконання, втрачаються після перезавантаження.
Короткий огляд рекомендованих значень за ролями:
| Параметр | Веб-сервер/сервер додатків | Сервер бази даних |
|---|---|---|
vm.swappiness | 10–20 | 1–5 |
vm.vfs_cache_pressure | 50 | 50 |
vm.dirty_ratio | 15 | 10% |
vm.min_free_kbytes | 65536 | 65536 |
| Захист від OOM | За замовчуванням | OOMScoreAdjust=-1000 |
Якщо ви виконуєте робочі навантаження з високою щільністю і вам потрібен сервер з запасом потужності для належного застосування цих політик, варто звернути увагу на виділені сервери FDC.

Управління пам'яттю в Linux: Swap, OOM Killer та Cgroups
Як працює Linux swap, OOM killer та cgroups - з прикладами конфігурацій для баз даних, веб-серверів та багатокористувацьких VPS-хостів.
12 хв читання - 31 травня 2026 р.
Посібник з налаштування Prometheus та node_exporter
15 хв читання - 29 травня 2026 р.

Маєте запитання або потребуєте індивідуального рішення?
Гнучкі варіанти
Глобальне охоплення
Миттєве розгортання
Гнучкі варіанти
Глобальне охоплення
Миттєве розгортання