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

12 мин чтения - 8 июня 2026 г.

hero section cover
Содержание
  • Настройка Linux OOM killer для VPS
  • Как OOM-киллер выбирает жертву
  • Выявление перегрузки памяти до сбоя
  • Защита критически важных процессов с помощью oom_score_adj
  • Ограничение памяти с помощью cgroups и systemd
  • Чтение логов после события OOM
  • Заключение
Поделиться

Настройте 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=5s

MemoryHigh — это мягкое ограничение: ядро агрессивно извлекает страницы из 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: практическое руководство

Настройте Linux OOM killer на вашем VPS для защиты баз данных и SSH, блокировки бегущих процессов с помощью cgroups и предотвращения гибели неправильного сервиса.

12 мин чтения - 8 июня 2026 г.

Linux Traffic Control (tc): практическое руководство

12 мин чтения - 5 июня 2026 г.

Другие статьи
background image

У вас есть вопросы или вам нужно индивидуальное решение?

icon

Гибкие варианты

icon

Глобальный охват

icon

Мгновенное развертывание

icon

Гибкие варианты

icon

Глобальный охват

icon

Мгновенное развертывание