Найти тему
1,2K подписчиков

Как работает OOM Killer

220 прочитали
Сегодня на повестке у нас с тобой OOM Killer. Давай разбираться как оно работает на самом деле и какие есть нюансы.

Сегодня на повестке у нас с тобой OOM Killer. Давай разбираться как оно работает на самом деле и какие есть нюансы.

Out of Memory Killer (OOM Killer) – это механизм ядра Linux, который освобождает оперативную память при ее исчерпании за счет принудительного завершения некоторых запущенных процессов.

Погнали разбираться как это работает и как его можно обуздать.

Когда оперативная память в ос linux заканчивается, происходят забавные вещи, ядро вызывает «кракена» OOM Killer. В свою очередь «кракен» прогоняет процесс по определенным правилам и убивает его.

Бытует ошибочное мнение, что OOM Killer берет самый жирный процесс и киляет его. Это не так. Создатели этого механизма знатно упоролись.

OOM Killer использует достаточно сложный анализ и присваивает каждому процессу очки негодности (badness). При исчерпании памяти, будет убит именно самый негодный процесс. Некий естественный отбор. Процесс убивается сигналом SIGKILL и не предоставляет приложению корректно завершиться. Вызывается функция out_of_memory, а далее select_bad_process.

После убийства, в системном журнале появится строчка:

Out of Memory: Killed process 2256 (mysql) score 907 or sacrifice child

А это уже не шутки. Если к тебе стал приходить OOM Killer, значит в какой-то момент на сервере, что-то пошло не так и нужно разобраться.

Очки негодности могут принимать значение от -1000 до +1000. Соответственно чем выше это значение, тем вероятнее, что процесс будет убит. А процесс со значением -1000 будет по логике — бессмертным.

Посмотреть репутацию процесса, можно командой:

cat /proc/<PID>/oom_score

Где PID это идентификатор процесса, узнать можешь командой:

ps ax | grep postfix

В результатах ты увидишь число, к примеру: 826, это и есть очки негодности.

Как вычисляются очки негодности

За основу берется процент физической памяти используемой процессом и умножается на 10, таким образом получаем базовое значение. 1000 очков = 100%. После того к базовому значению начинают применяться различные модификаторы.

Подпишись на BashDays в телеграм

- Прибавляется половина очков от всех дочерних процессов, которые имеют собственную виртуальную память.

- Если приоритет процесса > 0, то очки умножаются на 2. Приоритет процесса может иметь значения от -20 до +20. В данном случае +20 это самый низкий приоритет.

- Очки делятся на коэффициент, связанный с процессорным временем, чем более активнее процесс и чем больше процессорного времени он использует, тем больше будет его коэффициент.

- Очки делятся на коэффициент, связанный с временем жизни процесса, чем больше времени прошло с момента запуска, тем выше будет это значение.

- Для процессов, запущенных от имени root, служебных учеток или процессов ввода-вывода очки делятся на 4.

- Для процесса, при выделении памяти у которого произошла ошибка out of memory и процессам имеющим с ним общую память, очки делятся на 8.

- Все что получилось выше умножается на 2^oom_adj. Где oom_adj это специальный коэффициент, имеющий значения от -17 до +15, при -17 процесс никогда не будет убит.

TL;DR Если подытожить, то OOM Killer убьет самый «жирный» процесс, который наименее активен в системе и имеет самое короткое время жизни.

Как обуздать OOM Killer?


Можно вообще его отключить! Но по понятным причинам, это все равно что отключить жизненно важный орган у человека. Какое-то время он еще проживет, но потом обязательно сдохнет в kernel panic.

Отключается командой:

sudo echo 1 > /proc/sys/vm/panic_on_oom

По умолчанию 0 (то есть включено). Я ни разу не встречал, чтобы кто-то отключил этот функционал, но достаточно много раз сталкивался с забиваем костылей в сами процессы.

Можно повысить или понизить репутацию для процесса, добавив в файл oom_adj значение от -17 до +15. Для повышения репутации выполняем команду:

sudo echo -6 > /proc/<PID>/oom_adj

Не забываем подставить в PID, идентификатор нужного процесса.

Для отключения OOM Killer для определенного процесса, выставляем репутацию -17. Теперь этот процесс в «домике» и его никакая собака не посмеет тронуть.

sudo echo -17 > /proc/<PID>/oom_adj

Но если ты рестартанешь процесс, у него изменится PID. А репутация, которую ты ему уже накрутил, может примениться к совсем другому процессу таким же PID.

Также можно динамически определять PID процесса и менять ему репутацию. Закинуть это в крон и прыгать от счастья:

pgrep -f "/usr/sbin/sshd" | while read PID; do echo -17 > /proc/$PID/oom_adj; done

Но правильнее задать очки в самом systemd, в юните для сервиса, этот параметр:

[Service]
OOMScoreAdjust=-500


Собственно это база. По опыту скажу так — если к тебе пришел OOM Killer, сервак можно смело перезагружать. Ничего там уже не работает, несмотря на всякие очки и коэффициенты. Перезагрузиться будет намного эффективнее, чем пытаться поднять что-то. Поднял, а потом уже по горячим следам и логам, дебаж.

Поздравляю, ты только что прокачался еще на один уровень. Увидимся

Рекомендую почитать