Что такое OOM Killer в Linux?
OOM Killer (Out-Of-Memory Killer) — это механизм ядра Linux, который активируется, когда система исчерпала всю доступную оперативную память (RAM) и swap-пространство, и не может выделить память для нового запроса. Его задача — принудительно завершить один или несколько процессов, чтобы освободить память и предотвратить полный крах системы.
Механизм работает на основе алгоритма выбора жертвы, который оценивает каждый процесс по баллам (oom_score). Процесс с наивысшим баллом считается наименее важным и выбирается для завершения.
Как работает OOM Killer?
- Критическая нехватка памяти: Ядро определяет, что свободной памяти (включая swap) недостаточно для удовлетворения запроса.
- Вычисление баллов: Для каждого процесса рассчитывается
oom_scoreна основе:- Объёма используемой памяти (RSS).
- Приоритета процесса (nice value).
- Времени работы (новые процессы могут иметь преимущество).
- Является ли процесс дочерним для
init(PID 1) — такие процессы менее подвержены убийству. - Настройки
oom_score_adj(ручная корректировка).
- Выбор и убийство: Процесс с максимальным баллом получает сигнал
SIGKILLи завершается. - Логирование: Событие записывается в системный журнал ядра (
dmesg).
Как диагностировать срабатывание OOM Killer?
1. Проверка системного журнала
Ищите записи, содержащие ключевые слова:
dmesg | grep -i "killed process"
# Пример вывода:
# [12345.678] Out of memory: Kill process 1234 (some_process) score 500 or sacrifice child
# [12345.679] Killed process 1234 (some_process) total-vm:123456kB, anon-rss:98765kB, file-rss:1234kB
Также проверьте логи:
grep -i "oom" /var/log/syslog /var/log/messages
journalctl -k | grep -i "oom"
2. Анализ баллов (oom_score)
Посмотреть текущий балл для всех процессов:
for pid in $(ps -e -o pid=); do
echo "PID $pid ($(ps -p $pid -o comm=)): score $(cat /proc/$pid/oom_score 2>/dev/null || echo N/A)"
done | sort -k3 -n -r | head -20
Как предотвратить срабатывание OOM Killer?
1. Увеличение доступных ресурсов
- Добавление RAM — физическое расширение памяти.
- Настройка swap:
sudo fallocate -l 8G /swapfile # Создать файл подкачки 8 ГБ sudo chmod 600 /swapfile sudo mkswap /swapfile sudo swapon /swapfile echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab - Настройка параметров
vm.swappiness(в/etc/sysctl.conf):
Применить:vm.swappiness=10 # Резерв RAM до начала использования swap (по умолчанию 60)sudo sysctl -p
2. Настройка приоритетов процессов
Временная корректировка через /proc
# Уменьшить шансы быть убитым для PID 1234 (значение от -1000 до 1000)
echo -500 | sudo tee /proc/1234/oom_score_adj
Постоянная настройка через systemd
Для сервиса, управляемого systemd:
# /etc/systemd/system/myservice.service.d/oom.conf
[Service]
OOMScoreAdjust=-900
Перезагрузить: sudo systemctl daemon-reload && sudo systemctl restart myservice
3. Контроль потребления памяти
- Используйте
cgroups(v2) для ограничения памяти контейнеров/процессов. - Настройте лимиты в приложениях (например,
JAVA_OPTSдля Java,worker_processesдля Nginx). - Отключите ненужные сервисы.
4. Мониторинг и алерты
Настройте оповещения при достижении порога (например, 80% использования RAM+swap):
- Инструменты:
netdata,prometheus+alertmanager,zabbix. - Простой скрипт-чек:
#!/bin/bash USAGE=$(free | awk '/Mem:/ {printf("%.0f"), $3/$2 * 100}') if [ $USAGE -gt 85 ]; then echo "Внимание: использование памяти ${USAGE}%" | wall # Дополнительные действия: отправка email, перезапуск сервиса fi
5. Настройка поведения ядра (экспертно)
vm.overcommit_memory:0(по умолчанию) — heuristic overcommit.1— всегда разрешать overcommit (риск OOM).2— не разрешать overcommit, если не хватаетvm.overcommit_ratio(рекомендуется для критичных систем).
sudo sysctl -w vm.overcommit_memory=2 sudo sysctl -w vm.overcommit_ratio=50 # Разрешить overcommit только на 50% RAM+swapvm.panic_on_oom:0(по умолчанию) — запускать OOM Killer.1— паника ядра при OOM (требует перезагрузки).2— паника ядра всегда, но только еслиpanic_on_oom=2(редко используется).
Продвинутые инструменты
1. systemd-oomd (современная альтернатива)
В современных дистрибутивах (Ubuntu 22.04+, Fedora) может работать демон systemd-oomd, который более интеллектуально управляет памятью и может завершать процессы до срабатывания ядерного OOM Killer. Настройка через /etc/systemd/oomd.conf.
2. earlyoom
Простой демон, который мониторит память и RAM+swap, и убивает процессы при достижении порогов (например, 90% и 80% соответственно). Установка:
sudo apt install earlyoom # Debian/Ubuntu
sudo systemctl enable --now earlyoom
Настройка через аргументы в /etc/default/earlyoom или systemd-юнит.
3. ps_mem — анализ использования памяти
Установите утилиту для точного учёта памяти процессами:
sudo apt install ps_mem # Debian/Ubuntu
ps_mem
Частые ошибки и их решения
| Симптом | Возможная причина | Решение |
|---|---|---|
OOM Killer убивает mysqld или postgres | Слишком большой буферный пул, нехватка RAM | Уменьшить innodb_buffer_pool_size (MySQL) или shared_buffers (PostgreSQL), добавить RAM. |
| OOM Killer срабатывает при компиляции | make -j использует много памяти | Ограничить количество параллельных задач: make -j$(nproc --all) → make -j2 или make -j$(($(nproc --all)/2)). |
| Нет swap, система "зависает" перед OOM | Ядро не может выделить память и блокирует | Добавить swap-файл/раздел. |
Неправильный oom_score у процесса | Ручная настройка oom_score_adj или cgroups | Проверить значения: cat /proc/<PID>/oom_score_adj. Установить адекватные значения. |
Заключение
OOM Killer — это последний рубеж защиты системы от полного истощения памяти. Хотя его срабатывание может казаться катастрофой, оно предотвращает тотальный крах. Ключевые шаги для работы с ним:
- Мониторинг: отслеживайте использование памяти.
- Профилактика: настройте swap, ограничьте потребление приложений.
- Настройка: используйте
oom_score_adjдля защиты критичных процессов. - Анализ: всегда изучайте логи после срабатывания.
Помните: лучшая защита — это иметь достаточное количество RAM + swap и контролировать поведение приложений.