Что такое OOM Killer в Linux?

Ответ

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

Как он выбирает "жертву"? Алгоритм основывается на оценке oom_score для каждого процесса. Чем выше оценка, тем выше вероятность завершения. На неё влияют:

  • Объем потребляемой памяти.
  • Приоритет процесса (oom_score_adj).
  • Время работы процесса.
  • Привилегии пользователя.

Практический пример настройки: Чтобы защитить критически важный процесс (например, базу данных), можно понизить его oom_score.

# Узнаем PID процесса
pgrep postgres
# Защищаем процесс от OOM Killer, установив минимальный корректирующий коэффициент
echo -1000 > /proc/$(pgrep postgres)/oom_score_adj
# Проверяем текущий oom_score
cat /proc/$(pgrep postgres)/oom_score

Мониторинг и диагностика: После инцидента OOM проверьте логи ядра.

# Поиск записей об OOM в логах ядра
dmesg -T | grep -i "killed process"
# Или в системном журнале
journalctl --since "2 hours ago" | grep -i oom

Профилактика в DevOps-контексте:

  1. Настройка политики overcommit: Параметр vm.overcommit_memory (0 – эвристическая, 1 – всегда, 2 – не превышать сумму RAM + swap). Для предсказуемости в продакшене часто используют 2.
  2. Управление памятью в контейнерах: Всегда задавайте лимиты памяти (-m, --memory-reservation) в Docker/Kubernetes, чтобы контейнер не мог исчерпать память хоста.
  3. Адекватный размер swap: Наличие swap-раздела даёт системе буфер и время для реакции, хотя и снижает производительность.
  4. Мониторинг: Используйте Prometheus с Alertmanager для отслеживания использования памяти и прогнозирования OOM.

Ответ 18+ 🔞

А, слушай, вот эта штука — OOM Killer. Представь себе, у тебя сервак, а на нём памяти, как у золотой рыбки — три секунды, и всё забыл. И вот когда эта память кончается нахуй, ядро линукса начинает паниковать. А паникует оно своеобразно: берёт и начинает прибивать процессы, чтобы хоть как-то выжить. Это и есть тот самый убийца, OOM Killer. Не спрашивает, не предупреждает — просто бах, и твой постгрес лежит, как убитый. Ёперный театр, да?

Как он, этот маньяк, выбирает, кого завалить? У него там своя хитрая система баллов, oom_score называется. Чем процесс памяти больше хавает и чем он менее важный (с точки зрения системы, конечно, она ж не в курсе, что это твоя основная база), тем выше у него балл. А высокий балл — это как мишень на лбу. На этот счёт влияет куча всего: сколько оперативки жрёт, какой у него приоритет, давно ли запущен, под кем работает. Если процесс от рута — шансов выжить чуть больше, но не факт.

Вот тебе практический пример, как отмазать своего любимца от расстрела. Допустим, у тебя там постгрес крутится, и ты не хочешь, чтобы его внезапно накрыли медным тазом. Делаешь так:

# Узнаем PID процесса
pgrep postgres
# Вмандячиваем ему защиту, выставив минимальный коэффициент. Минус тысяча — это типа "не трогай его, ёпта!"
echo -1000 > /proc/$(pgrep postgres)/oom_score_adj
# Проверяем, какой теперь у него балл смертности
cat /proc/$(pgrep postgres)/oom_score

Вот после этого у убийцы доверия к этому процессу — ноль ебать, и он будет искать другую жертву.

А если уже всё ебнулось и надо понять, кто виноват? Лезишь в логи и начинаешь шарить.

# Роемся в сообщениях ядра, ищем трупы
dmesg -T | grep -i "killed process"
# Или в системном журнале копаемся
journalctl --since "2 hours ago" | grep -i oom

Там обычно всё написано: кто, когда и за что получил пулю. Иногда ни хуя себе откроешь — оказывается, какой-нибудь забытый скрипт память сожрал овердохуища.

Ну и как не доводить до такого пиздеца, особенно если ты девопс?

  1. Настройка политики overcommit (vm.overcommit_memory). Это такая фигня, где система решает, давать ли процессам память в долг. Вариант 2 (не превышать сумму RAM + swap) — самый строгий и предсказуемый. Никаких "ой, я думал, мне хватит". Не хватит — получи отказ, а не внезапную смерть соседа.
  2. Контейнеры — их надо в узде держать. Когда запускаешь в Docker или Kubernetes, всегда ставь лимиты памяти (-m, --memory-reservation). Иначе один контейнер устроит хиросиму на всём хосте. Это прям must, чувак.
  3. Своп — он как подушка безопасности. Да, с ним медленнее, но он даёт системе время сообразить, что пора начинать убивать, а не просто падать в обморок. Без свопа волнение ебать — всё происходит мгновенно.
  4. Мониторинг, блядь! Не жди, пока гром грянет. Настрой Prometheus с Alertmanager, чтобы он орал тебе, когда память на 85% заполнена. Прогнозировать OOM — это гораздо проще, чем потом объяснять, почему всё легло в самый неподходящий момент. Э бошка думай наперёд!