Как OOM Killer выбирает процессы в Linux
Порой мне кажется, что в выходные я устаю больше, чем за всю рабочую неделю. Но это скорее психологическая усталость, так как выпадаешь из рабочего ритма/потока и потом сложно обратно запрыгивать. Ладно, у нас тут не кружок психологии.
читать первым в телеграм читать первым в макс
Сегодня на повестке у нас с тобой OOM Killer.
Погнали разбираться, как это работает и как его можно обуздать.
Когда оперативная память в ОС 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, это и есть очки негодности.
Если интересно, как начисляются очки негодности, я вынес это в отдельный пост в Telegraph, чтобы не валить тебя скучной теорией. Почитать можешь тут.
Как обуздать 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 процесса и менять ему репутацию. Закинуть это в cron и прыгать от счастья:
pgrep -f "/usr/sbin/sshd" | while read PID; do echo -17 > /proc/$PID/oom_adj; done
Но правильнее задать очки в самом systemd, в юните для сервиса, этот параметр:
[Service]
OOMScoreAdjust=-500
Поздравляю, ты только что прокачался ещё на один уровень. Хорошего тебе понедельника, да и лёгкой рабочей недели! Увидимся!
