nohang/README.md

99 lines
10 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

The No Hang Daemon
==================
`Nohang` - аналог [earlyoom](https://github.com/rfjakob/earlyoom) с поддержкой `zram` и `SIGTERM`. При дефиците доступной памяти `nohang` корректно завершает наиболее прожорливые процессы сигналом `SIGTERM`, тем самым препятствуя зависанию, а также избыточному убийству процессов ядерным `OOM killer`'ом.
### Зачем это нужно?
Затем, что этот демон реализует востребованный функционал. Судите сами:
"А можете рассказать, как сделать OOM Killer более агрессивным? Например, в ситуации, когда приложение открыло/создало множество мелких файлов и держит их в памяти, при внезапной нехватке памяти ядро пытается высвободить эти файловые страницы, что вешает систему намертво со 100%-м дисковым I/O на несколько (десятков) минут. А ведь зачастую гораздо проще просто грохнуть само приложение с дальнешим его перезапуском."
https://habr.com/company/flant/blog/348324/#comment_10659202
"Говно какое-то этот оом-киллер, нихрена не работает.
Но чтобы это нормально работало, я думаю, нужен какой-то демон, который постоянно мониторит потребление памяти и прибивает тот процесс, который резко начинает набирать обороты. В общем сам этот демон будет проц грузить, хотя можно ограничить процессы, которые он будет проверять только пользовательскими процессами, добавить black-white list ну и настраиваемый интервал проверки.
Короче если кто-то напишет будет круто."
https://www.linux.org.ru/forum/general/13074074#comment-13074864
"Сегодня скормил пикарду 100-дисковое издание Бетховена и тот сожрал 16 гб памяти вместе с 8 гб zram (коэффициент сжатия был 3.5). Со swappiness 100 zram начал наполняться на 80% памяти, а когда сам достиг 80%, то сжатие продолжилось с новой силой и полной загрузкой ядра. По окончанию банкета система встала колом, потому что киллер опять сцуко не пришел (ждал 10 минут)."
https://www.linux.org.ru/forum/general/13074074/page1?lastmod=1481740875388#comment-13077387
"Система таки становится неюзабельной если продолжать стараться забивать ее вплоть до исчерпания RAM+ZRAM. Ничего неудивительного, памяти то нет. Но в случае с дисковым свопом ты начинаешь заранее замечать что дело плохо. По ощущениям ZRAM не тормозит вообще, потому ты ничего не подозреваешь до часа икс и система становится колом."
https://www.linux.org.ru/forum/talks/12684213?lastmod=1466676523241#comment-12684906
"И IRL ты никогда не знаешь, в какой момент момент твои данные перестанут умещаться в оперативку. Потому zram -- удел embedded систем, где это может быть детерминировано."
https://2ch.hk/s/res/2310304.html#2311483, https://archive.li/idixk
`Nohang` позволяет избавиться от перечисленных выше проблем, корректно завершая наиболее прожорливые процессы сигналом `SIGTERM` не дожидаясь когда система "встанет колом". `Nohang` позволяет не бояться зависаний при использовании `zram`.
### Зачем нужен nohang, если уже есть earlyoom?
- `earlyoom` завершает (точнее убивает) процессы исключительно с помощью сигнала `SIGKILL`, в то время как `nohang` дает возможность сначала отправлять `SIGTERM`, и только если процесс не реагирует на `SIGTERM` - отправляется сигнал `SIGKILL`.
- `earlyoom` не поддерживает работу со `zram` и не реагирует на общую долю `zram` в памяти (`mem_used_total`). Это может привести к тому, что система все также встанет колом, как если бы `earlyoom` и не было (если `disksize` большой, а энтропия сжимаемых данных велика). `Nohang` позволяет избавиться от этой проблемы. По умолчанию если доля `zram` достигнет 60% памяти - будет отправлен сигнал `SIGTERM` процессу с наибольшим `oom_score`.
### Особенности
- задача - препятствовать зависанию системы при нехватке доступной памяти, а также корректное завершение процессов с целью увеличения объема доступной памяти
- демон на Python 3, VmRSS около 12 MiB
- требуется `Linux 3.14+` и `Python 3.4+`
- периодически проверяет размеры доступной памяти, при дефиците памяти отправляет `SIGKILL` или `SIGTERM` процессу с наибольшим `oom_score`
- поддержка работы со `zram`, возможность реакции на `mem_used_total`
- удобный конфиг с возможностью тонкой настройки
- возможность раздельного задания уровней `MemAvailable`, `SwapFree`, `mem_used_total` для отпраки `SIGTERM` и `SIGKILL`, возможность задания в процентах (%), кибибайтах (K), мебибайтах (M), гибибайтах (G)
- возможность снижения `oom_score_adj` процессов, чьи `oom_score_adj` завышены (актуально для `chromium`)
- лучший алгоритм выбора периодов между проверками доступной памяти: при больших объемах доступной памяти нет смысла проверять ее состояние часто, поэтому период проверки уменьшается по мере уменьшения размера доступной памяти
- интенсивность мониторинга можно гибко настраивать (параметры конфига `rate_mem`, `rate_swap`, `rate_zram`)
- по умолчанию память заблокирована с помощью `mlockall()` для предотвращения своппинга процесса
- по умолчанию высокий приоритет процесса `nice -20`, может регулироваться через конфиг
- предотвращение самоубийства с помощью `self_oom_score_adj = -1000`
- возможность задания `oom_score_min` для предотвращения убийства невиновных
- `min_delay_after_sigkill` для предотвращения массовых убийств
- наличие `man` страницы
- наличие установщика для пользователей `systemd`
- протестировано на `Debian 9 x86_64`, `Debian 8 i386`, `Fedora 28 x86_64`
- пример вывода с отчетом об успешной отпраке сигнала:
```
MemAvail: 0M 0.0%, SwapFree: 985M 8.4%, MemUsedZram: 625M 10.6%
MemAvail: 0M 0.0%, SwapFree: 962M 8.2%, MemUsedZram: 626M 10.6%
MemAvail: 9M 0.1%, SwapFree: 939M 8.0%, MemUsedZram: 626M 10.7%
MemAvailable 9M < 353M and SwapFree 939M < 940M
Try to send signal 15 to process python3, Pid 3392, oom_score 818
Success
MemAvail: 29M 0.5%, SwapFree: 2866M 24.4%, MemUsedZram: 582M 9.9%
MemAvail: 77M 1.3%, SwapFree: 5037M 42.9%, MemUsedZram: 532M 9.1%
MemAvail: 168M 2.9%, SwapFree: 8956M 76.2%, MemUsedZram: 441M 7.5%
MemAvail: 5006M 85.2%, SwapFree: 10632M 90.5%, MemUsedZram: 356M 6.1%
MemAvail: 5000M 85.1%, SwapFree: 10633M 90.5%, MemUsedZram: 356M 6.1%
```
### Установка и удаление для пользователей systemd
```bash
git clone https://github.com/hakavlad/nohang.git
cd nohang
```
Установка
```bash
sudo ./install.sh
```
Удаление вместе с конфигом
```bash
sudo ./purge.sh
```
Удалить всё, кроме конфига
```bash
sudo ./uninstall.sh
```
### Настройка
`Nohang` настраивается с помощью [конфига](https://github.com/hakavlad/nohang/blob/master/nohang.conf), расположенного после установки
по адресу
```
/etc/nohang/nohang.conf
```
К опциям прилагается описание. Отредактируйте значения параметров в соответствии с вашими предпочтениями.
### Известные баги
Известных нет, если найдете - пишите в [Issues](https://github.com/hakavlad/nohang/issues).