Тюнинг Linux OOM Killer для VPS: практическое руководство
12 мин чтения - 8 июня 2026 г.

Настройте Linux OOM killer на вашем VPS для защиты баз данных и SSH, блокировки бегущих процессов с помощью cgroups и предотвращения гибели неправильного сервиса.
Настройка Linux OOM killer для VPS
Linux OOM killer — это крайняя мера ядра, когда заканчивается память: он выбирает процесс и завершает его, чтобы система продолжала работать. На VPS, где оперативной памяти мало и нет куда отступить, выбор по умолчанию часто оказывается неправильным. Ваша база данных завершается, долго работающий рабочий процесс выживает, и вам приходится выяснять, почему. В этом руководстве рассказывается, как OOM-киллер оценивает процессы, как настроить эту оценку в пользу ваших критически важных сервисов и как использовать cgroups, чтобы один сбежавший процесс не смог потянуть за собой остальную часть системы.
Как OOM-киллер выбирает жертву
Когда ядро не может освободить достаточно памяти путем вытеснения из кэша страниц или с помощью свопа, оно запускает OOM-киллер. У каждого процесса есть oom_score оценку от 0 до 1000, которая в основном определяется размером набора резидентных страниц (RSS) и использованием подкачки. Процесс с наибольшей оценкой получает сигнал SIGKILL.
RSS доминирует в расчете, поэтому убийство почти всегда ложится на крупнейшего потребителя памяти. Часто это ваша база данных, сервер приложений или любой долгоживущий процесс, выполняющий наиболее полезную работу. Процесс, который фактически инициировал выделение памяти, «вызывающий», редко оказывается тем, кого завершают.
Существует два типа событий OOM, которые необходимо различать:
- Глобальный OOM: у хоста (или вашего VPS в целом) закончилась оперативная память и своп. Ядро сканирует каждый процесс и убивает тот, у которого самый высокий балл.
- Cgroup OOM: конкретная cgroup достигла своего предела памяти. Ядро завершает только процессы внутри этой cgroup, даже если у остальной части системы есть свободная память.
Если вы настроили ограничения для модулей systemd или запускаете контейнеры, большинство ваших событий OOM будут OOM cgroup. Это хорошо: радиус воздействия ограничен.
Выявление перегрузки памяти до сбоя
События OOM почти никогда не возникают внезапно. Обычно сначала наблюдается период нарастания нагрузки, и цель мониторинга — зафиксировать это явление в пределах этого периода.
free -h показывает обзор системы. Важна колонка available, а не free: она учитывает освобождаемый кэш страниц и отражает то, что вы действительно можете выделить без подкачки. Держите MemAvailable на уровне примерно 10–15 процентов от MemTotal при пиковой нагрузке.
Для атрибуции по процессам отсортируйте по RSS:
ps aux --sort=-%mem | head -10Или используйте htop и отсортируйте по RES. Значения, которые вы видите здесь, напрямую влияют на оценку ядра, поэтому верхние записи являются наиболее вероятными объектами OOM.
В ядрах версии 4.20 и новее информация о задержках из-за нехватки памяти (Pressure Stall Information) представляет собой систему раннего предупреждения, которую стоит подключить к мониторингу:
cat /proc/pressure/memoryПоказатель some avg10 значение на графике — это процент времени, в течение которого хотя бы одна задача простаивала в ожидании памяти за последние десять секунд. Значение ниже 5 процентов — это нормально. Устойчивые значения выше 10 процентов означают, что система тратит реальное время, заблокированная на освобождении памяти, и вероятно завершение процесса из-за OOM.
Свап-трашинг отображается в vmstat 1 в виде ненулевого si и so колонках, сохраняющееся в течение длительного времени. Небольшой объем резидентной подкачки безвреден. Постоянные операции загрузки и выгрузки из подкачки — нет.
Защита критически важных процессов с помощью oom_score_adj
Оценка, вычисляемая ядром, может быть скорректирована для каждого процесса с помощью oom_score_adj, по шкале от -1000 (независимый) до +1000 (убить меня первым). Корректировка добавляется непосредственно к итоговой оценке.
Для однократного изменения в отношении запущенного процесса:
echo -500 | sudo tee /proc/$(pidof sshd)/oom_score_adjДля всего, что вы хотите сохранить после перезапусков, установите это в модуле systemd. Это подходящее место для sshd, вашей базы данных и всего остального, что вы не можете себе позволить потерять:
[Service]
OOMScoreAdjust=-900Разумные значения по умолчанию для начала:
- sshd: -1000. Если вы потеряете удаленный доступ во время кризиса памяти, восстановление станет гораздо сложнее.
- MySQL, PostgreSQL, Redis: от -800 до -900. Надежная защита, не делающая их полностью неприкосновенными в действительно катастрофической ситуации.
- Рабочие процессы приложений, пакетные задания, задачи cron: от +100 до +500. Это процессы, которые лучше убить, чем базу данных.
Не устанавливайте для всех значения -1000. Если ничего нельзя убить, ядро в конечном итоге перейдет в состояние паники или зависнет, что еще хуже.
Ограничение памяти с помощью cgroups и systemd
Настройка оценок влияет на то, кто будет завершен. Cgroups влияют на то, произойдет ли глобальное завершение вообще. Устанавливая для каждой службы жесткий верхний предел, вы переносите сбои памяти в одну cgroup, вместо того чтобы позволить одному процессу истощить весь VPS.
В файле модуля systemd:
[Service]
MemoryHigh=400M
MemoryMax=512M
OOMPolicy=stop
Restart=on-failure
RestartSec=5sMemoryHigh — это мягкое ограничение: ядро агрессивно извлекает страницы из cgroup выше этой отметки, но ничего не завершает. MemoryMax — это жесткий предел. Если cgroup пытается выделить память сверх этого предела, ядро завершает процесс внутри cgroup. С помощью Restart=on-failure сервис сразу же запускается заново.
В cgroup v2 (Ubuntu 22.04 и более поздние версии, последние версии Debian, RHEL 9), memory.oom.group убивает все процессы в cgroup одновременно, вместо того чтобы оставлять «сирот». Полезно для многопроцессных служб, таких как пулы PHP-FPM, где «наполовину убитая» группа будет вести себя некорректно.
Несколько примечаний, относящихся к конкретным приложениям, которые стоит применить:
- PHP-FPM: установите
pm = ondemandна небольших экземплярах VPS и размерpm.max_childrenотносительно среднего значения RSS на одного рабочего процесса, а не по умолчанию. Пул, рассчитанный на 4 ГБ запаса на VPS с 2 ГБ, вызовет OOM при первом же заполнении. - Node.js: ограничьте кучу V8 с помощью
--max-old-space-size=512(в МБ). Без этого Node будет спокойно расти, пока не вмешается ядро. - MySQL и PostgreSQL:
innodb_buffer_pool_sizeиshared_buffersдолжны оставлять достаточно свободного места для кэша страниц ОС, памяти соединений и любых других пользователей на сервере. Значения по умолчанию предполагают использование выделенного сервера.
Чтение логов после события OOM
Когда срабатывает OOM-киллер, ядро записывает подробный отчет в кольцевой буфер. Получите его с помощью:
dmesg -T | grep -iE 'killed process|out of memory'
journalctl -k --grep='Out of memory'Блок, который нужно внимательно прочитать, начинается с вызывающего процесса и заканчивается жертвой. Ядро выводит полный список задач с указанием RSS каждого процесса, использования свопа и окончательного oom_score_adj. Стоит проверить три вещи:
- Ограничение.
CONSTRAINT_NONEозначает глобальный OOM,CONSTRAINT_MEMCGозначает, что cgroup достиг своего предела. Решение в каждом случае свое Free swap. Если это0kB, то исчерпаны как ОЗУ, так и своп. Либо добавьте своп, либо увеличьтеMemoryMaxнагрузку на виновника, либо уменьшите параллелизм.- Оценка пострадавшего процесса по сравнению со всеми остальными. Если оценка пострадавшего процесса не намного выше, чем у следующих нескольких процессов, ваши
oom_score_adjзначения не выполняют достаточной работы. Увеличьте разрыв.
Что касается конкретно OOM в cgroup, счетчик kill находится memory.events внутри cgroup:
cat /sys/fs/cgroup/system.slice/mysql.service/memory.eventsУвеличение oom_kill значит, что сервис постоянно достигает своего лимита. Это сигнал к тому, чтобы увеличить MemoryMax, проанализировать рабочую нагрузку или перенести сервис на более мощный тарифный план, а не перезапускать его в бесконечном цикле.
Заключение
Настройка OOM-киллера не заключается в том, чтобы избавиться от него. Речь идет о том, чтобы контролировать, какой процесс понесет убытки при исчерпании памяти, и уменьшить масштаб последствий, когда это произойдет. Паттерн, который работает в производственной среде:
- Защитите с помощью Score те сервисы, которые вы не можете себе позволить потерять, особенно sshd и ваши базы данных.
- Ограничьте все остальное с помощью
MemoryMaxв модуле systemd, чтобы один сбой привел к одной перезагрузке, а не к отключению. - Следите за показателями PSI и
MemAvailableвместо того, чтобы ждатьdmesg, чтобы узнать о проблеме постфактум. - Оставьте 15–20 процентов ОЗУ в качестве запаса. Настройка не может компенсировать VPS, который просто слишком мал для рабочей нагрузки.
Если нагрузка на память носит структурный характер, а не зависит от конфигурации, вам потребуется больше ОЗУ или более быстрое хранилище с поддержкой свопа. Тарифные планы VPS от FDC Servers работают на процессорах AMD EPYC с хранилищем NVMe, что обеспечивает достаточно высокую скорость чтения из свопа, благодаря чему кратковременные всплески загрузки памяти не приводят к завершению процессов.

Тюнинг Linux OOM Killer для VPS: практическое руководство
Настройте Linux OOM killer на вашем VPS для защиты баз данных и SSH, блокировки бегущих процессов с помощью cgroups и предотвращения гибели неправильного сервиса.
12 мин чтения - 8 июня 2026 г.
Linux Traffic Control (tc): практическое руководство
12 мин чтения - 5 июня 2026 г.

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