Управление памятью в Linux: Подкачка, убийца OOM и 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 нс. Своп — это буфер безопасности, а не дополнительная оперативная память. Сервер, который постоянно полагается на своп, имеет проблему с памятью, которую увеличение объема свопа не решит.
Используйте файл подкачки, а не раздел. Его проще изменять по размеру, и для этого не требуется переразбиение диска.
sudo fallocate -l 2G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfileДобавьте файл, чтобы /etc/fstab , чтобы сохранить его после перезагрузки. chmod 600 шаг обязателен — любые данные, выгруженные из ОЗУ, доступны для чтения из файла подкачки, поэтому файл не должен быть общедоступным для чтения.
После создания свопа настройте 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-убийство в пределах cgroup.
Cgroup v1 и v2 отличаются в первую очередь своей структурой. В версии v1 каждый контроллер (память, ЦП, ввод-вывод) монтируется отдельно под /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. Используйте директивы файла unit, такие как 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: Подкачка, убийца OOM и Cgroups
Как Linux swap, OOM killer и cgroups работают вместе - с примерами конфигурации для баз данных, веб-серверов и многопользовательских VPS-хостов.
12 мин чтения - 31 мая 2026 г.
Руководство по настройке Prometheus и node_exporter
15 мин чтения - 29 мая 2026 г.

У вас есть вопросы или вам нужно индивидуальное решение?
Гибкие варианты
Глобальный охват
Мгновенное развертывание
Гибкие варианты
Глобальный охват
Мгновенное развертывание