OOM Killer в Linux: как он работает и как защитить приложения

5 минут чтения
Средний рейтинг статьи — 4.8

OOM (Out Of Memory) — это состояние, когда системе не хватает оперативной памяти для выполнения новых аллокаций.

Когда:

  • RAM полностью занята
  • swap исчерпан или отключён
  • ядро не может освободить память

Linux запускает механизм OOM Killer.

Его задача — убить один или несколько процессов, чтобы освободить память и не допустить полного зависания системы.

Это не баг. Это механизм защиты.

Что происходит при нехватке памяти

Упрощённая цепочка событий:

  1. Процесс запрашивает память
  2. Ядро не может её выделить
  3. Попытка reclaim (очистка page cache, slab, anonymous pages)
  4. Если reclaim не помогает → OOM
  5. Запускается OOM Killer
  6. Выбирается «жертва»
  7. Процесс получает SIGKILL

В логах это выглядит так:

dmesg | grep -i oom

Типичный вывод:

Out of memory: Kill process 1234 (java) score 947 or sacrifice child
Killed process 1234 (java) total-vm:...

Как OOM выбирает процесс и как этим управлять

OOM Killer не убивает случайный процесс.
Он рассчитывает OOM score.

Каждый процесс имеет:

  • oom_score (динамический)
  • oom_score_adj (настройка приоритета)

Посмотреть можно так:

cat /proc/<pid>/oom_score  
cat /proc/<pid>/oom_score_adj

Чем выше score — тем выше шанс быть убитым.

Факторы влияния:

  • объём используемой памяти
  • процент от общей RAM
  • privileged ли процесс
  • выставленный oom_score_adj

Диапазон:

-1000  → никогда не убивать
0      → стандартное поведение
+1000  → убить в первую очередь

Пример защиты процесса:

echo -1000 > /proc/<pid>/oom_score_adj

В systemd это настраивается так:

OOMScoreAdjust=-1000

Почему OOM может «убить не того»

Иногда кажется, что OOM ведёт себя странно:

  • убил nginx, а не runaway Python
  • убил postgres, а не memory leak сервис

Причины:

  1. Процесс использует shared memory
  2. У него выше реальное потребление RSS
  3. У него не настроен oom_score_adj
  4. Включены cgroups

OOM и cgroups: global vs container-level

В современных системах (Docker, Kubernetes, systemd) память часто ограничивается через cgroups.

В этом случае есть два уровня OOM:

1) Global OOM

Когда заканчивается память всей системы.

2) cgroup OOM

Когда процесс превысил лимит памяти контейнера.

В Docker:

docker run -m 512m ...

Если процесс внутри контейнера превышает 512MB — его убьёт cgroup OOM, даже если на хосте ещё есть память.

В логах Kubernetes это выглядит как:

OOMKilled

vm.overcommit_memory

Linux не всегда строго проверяет доступность памяти.

Есть параметр:

sysctl vm.overcommit_memory

Режимы:

0 — эвристика (по умолчанию)  
1 — всегда разрешать overcommit  
2 — строгий режим

Overcommit означает, что система разрешает процессам зарезервировать больше памяти, чем реально есть.

Это ускоряет работу, но увеличивает риск OOM.

Типичные сценарии OOM

Memory leak

Процесс постепенно съедает всю память.

Fork-бомба

Массовое создание процессов.

Большой batch / миграция

Запуск тяжёлой операции без лимитов.

Неправильные лимиты в Kubernetes

container limit < реального потребления.

Как диагностировать OOM

1) Проверить логи

dmesg -T | grep -i oom  
journalctl -k | grep -i kill

2) Проверить текущую память

free -m

3) Найти самых «жирных»

ps aux --sort=-%mem | head

или

top  
htop

4) Проверить cgroup-лимиты

cat /sys/fs/cgroup/memory.max

(в cgroup v2)

Как защитить приложения

✅ 1. Настроить лимиты

  • systemd → MemoryMax=
  • Docker → -m
  • Kubernetes → requests / limits

Лимит лучше, чем падение всей системы.

✅ 2. Настроить oom_score_adj

Критичные сервисы:

  • база данных
  • etcd
  • kube-apiserver

должны иметь пониженный score.

✅ 3. Использовать swap аккуратно

Swap:

  • снижает риск мгновенного OOM
  • увеличивает latency

На продакшене часто ставят небольшой swap как «предохранитель».

✅ 4. Мониторинг

Нужно отслеживать:

  • RSS
  • cache
  • swap usage
  • page faults
  • memory pressure (PSI)

Особенно полезен:

cat /proc/pressure/memory

✅ 5. Memory requests в Kubernetes

Если request слишком маленький — scheduler может разместить слишком много подов на одной ноде.

Это гарантированный путь к OOM.

Что важно запомнить

OOM Killer — это не ошибка.

Это:

  • механизм выживания ядра
  • способ сохранить систему
  • крайняя мера

Если OOM срабатывает регулярно — проблема не в OOM.

Проблема в архитектуре, лимитах или утечках памяти.

Вывод

OOM Killer:

  • анализирует потребление памяти
  • рассчитывает score
  • выбирает жертву
  • освобождает ресурсы

Чтобы не страдать от неожиданных падений:

  • выставляйте лимиты
  • настраивайте приоритеты
  • мониторьте память
  • тестируйте нагрузку

И тогда OOM станет не врагом, а страховкой от полного краша системы.

5 минут чтения
Средний рейтинг статьи — 4.8

Настроить мониторинг за 30 секунд

Надежные оповещения о даунтаймах. Без ложных срабатываний