Failed with result oom-kill — Решение уничтожения служб по памяти в systemd
Архитектура ошибки и симптомы сбоя
Критический сбой службы «systemd: Failed with result 'oom-kill'» (или статус «Main process exited, code=killed, status=9/KILL (OOM-killed)») генерируется диспетчером systemd. Ошибка указывает на то, что процесс сервиса был принудительно уничтожен ядерным механизмом Out-Of-Memory (OOM) Killer либо пользовательским демоном systemd-oomd. Это происходит, когда процесс превысил жесткий лимит памяти своей контрольной группы (MemoryMax= / memory.max) либо на сервере полностью закончилась свободная физическая память и Swap.
Диагностическая таблица параметров сбоя
| Параметр | Значение | Инженерный смысл сбоя |
|---|---|---|
| MemoryMax (memory.max) | Bytes / Percentage | Жесткий лимит памяти для контрольной группы сервиса в cgroups v2. |
| OOMScoreAdjust | -1000 .. +1000 | Приоритет уничтожения процесса ядром (-1000 = запрет убийства OOM Killer). |
| systemd-oomd | Userspace OOM Daemon | Служба превентивного уничтожения cgroup при критическом росте PSI memory pressure. |
Пошаговое дерево решений и сценарии траблшутинга
Сценарий 1: Проверка факта и деталей OOM-уничтожения в системном журнале
# Поиск записей OOM Killer в логах ядра за последнюю загрузку:
sudo dmesg -T | grep -i -E "(killed process|oom_score_adj|Out of memory)"
# Проверка логов службы systemd-oomd:
sudo journalctl -u systemd-oomd -eСценарий 2: Увеличение лимита памяти службы в Systemd
Увеличьте лимит выделяемой памяти или снимите ограничение:
# Редактирование параметров юнита:
sudo systemctl edit service_name.service
# Добавьте в открывшуюся конфигурацию расширенные лимиты:
[Service]
MemoryMax=16G
MemoryHigh=14G
MemorySwapMax=4G
# Примените изменения:
sudo systemctl daemon-reload
sudo systemctl restart service_name.serviceСценарий 3: Защита критической службы от OOM Killer (OOMScoreAdjust)
Для критически важных демонов (например, SSHD, основной кластер СУБД) исключите их выбор жертвой OOM:
# В конфигурации юнита:
[Service]
OOMScoreAdjust=-1000
# Значение -1000 полностью запрещает ядру убивать данный процесс при OOM!Сценарий 4: Отключение или тонкая настройка systemd-oomd
Если агрессивный демон systemd-oomd убивает рабочие службы при кратковременных пиках нагрузки:
# Отключение systemd-oomd:
sudo systemctl disable --now systemd-oomd
# Либо исключение конкретного сервиса из-под контроля systemd-oomd:
[Service]
ManagedOOMMemoryPressure=ignoreITSTM проведет профилирование утечек памяти (Heap profiling), сайзинг пулов JVM/PostgreSQL и настройку отказоустойчивых политик OOM.
Частые вопросы (FAQ)
Как OOM Killer выбирает, какой именно процесс уничтожить?
Ядро рассчитывает oom_score для каждого процесса на основе объема потребляемой физической памяти (RSS) и скорректированного веса /proc/<PID>/oom_score_adj. Процесс с максимальным score уничтожается первым.
Чем системный OOM Killer отличается от Cgroup OOM Killer?
Системный OOM срабатывает при исчерпании всей оперативной памяти хоста и убивает самый «прожорливый» процесс в ОС. Cgroup OOM срабатывает, когда память исчерпана только внутри конкретного контейнера/сервиса (превышен MemoryMax), не затрагивая остальные службы хоста.
Почему добавление Swap-файла помогает предотвратить OOM Kill?
Swap дает ядру возможность вытеснять неактивные анонимные страницы памяти, освобождая физическую RAM для активных процессов и дискового кэша, предотвращая падение системы в OOM.
Как посмотреть текущий oom_score процесса?
Выполните команду: cat /proc/<PID>/oom_score. Значение варьируется от 0 до 1000.