OOM Killer в Linux: как он работает и как защитить приложения
OOM (Out Of Memory) — это состояние, когда системе не хватает оперативной памяти для выполнения новых аллокаций.
Когда:
- RAM полностью занята
- swap исчерпан или отключён
- ядро не может освободить память
Linux запускает механизм OOM Killer.
Его задача — убить один или несколько процессов, чтобы освободить память и не допустить полного зависания системы.
Это не баг. Это механизм защиты.
Что происходит при нехватке памяти
Упрощённая цепочка событий:
- Процесс запрашивает память
- Ядро не может её выделить
- Попытка reclaim (очистка page cache, slab, anonymous pages)
- Если reclaim не помогает → OOM
- Запускается OOM Killer
- Выбирается «жертва»
- Процесс получает 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 сервис
Причины:
- Процесс использует shared memory
- У него выше реальное потребление RSS
- У него не настроен oom_score_adj
- Включены 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 kill2) Проверить текущую память
free -m3) Найти самых «жирных»
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 станет не врагом, а страховкой от полного краша системы.
Настроить мониторинг за 30 секунд
Надежные оповещения о даунтаймах. Без ложных срабатываний