Date

Out of memory

OOM Killer

На самом деле, это очень крутой тип, который приходит когда нужно, делает свое дело, и по-тихому уходит, наделав кучу плохих вещей. Ну или не плохих. Суть вот в чем: к примеру, у нас есть гвноапликейшн (ну или новый билд в CI) который, в процессе своей гвноработы бесконечно аллоцирует память. Грубо говоря, в бесконечном цикле делает malloc(). К чему это приведет? Правильно, к тому что память физичски закончится, приложение умрет, повесит за собой операционную систему, и будет в состоянии HLT висеть, пока кто-нибудь не сделает хард резет. Почему хард резет? Как правило, если состояние очень трагичное - ОС не может форкнуть процесс (просто некуда) и открыть хоть какую-то консоль (неважно, tty или ssh). И тут то появляется OOM Killer

OOM Killer, что ты наделал?

По сути, OOM Killer - это способ ядра своими силами решить проблему утечки памяти. Конечно, лучше привести девелоперов на инквизицию, которые такое написали - но этого уже Linux сделать не сможет. Очевидно, что у этого Стэтхема есть свой алгоритм, по которому он определяет, кого кильнуть, а кого оставить. Работает он так:

  1. Он берет размер памяти процесса (из total_vm), и записывает себе в блокнот.

  2. Если это родительский процесс, то добавляет к верхнему числу total_vm/2 + 1 для всех порожденных.

  3. Делит на user/system time процесса - int_sqrt((utime+stime)/10

  4. Если niceness больше 0, умножает очки на 2 - тут подразумевается, что если приоритет у процесса больше 0 (это значит меньше для ОС: читать nice), то выполнение этого процесса не критично

  5. Если есть CAP_SYS_ADMIN, CAP_SYS_RESOURCE, CAP_SYS_RAWIO - делит на 4

  6. Умножает очки на oom_adj из /proc/$PID/oom_score_adj

Тот последний, у кого будет больше всего очков и будет убит. Сразу после этого в dmesg и /var/log/kern.log будет Killed process. Тот который попал под раздачу будет убит через SIGKILL.

Понятно, что делать?

Сначала желательно почитать логи. Возможно проблема описана в них, и дев сможет пофиксить за 1 секунду благодаря логам? В этом поможет ELK Stack.

Если не помогло - есть варианты закостылить параметры для процессов, которые обязательно должны работать при любых обстоятельствах: echo -17 > /proc/[pid]/oom_adj #исключает процесс из выборки OOM Killer

renice -n -20 $PID #почти 100% уменьшает вероятность попасть под OOM Killer

В таком случае прогнозируемо, что апп с мемори ликом подвесит ОС. Этот вариант подходит для быстрых фиксов, грубо говоря "приклеить пластырь на танк". Адекватными действиями в данной ситуации будет считаться тюнинг оверкомитмента.

Overcommit

Оверкомитмент - это политики ядра, которые регулируют действия ОС в случаях, когда оперативной памяти не хватает. Эти очень важные темы настраиваются в /etc/sysctl.conf

Есть 2 параметра, которые нужно затюнить:

  1. vm.overcommit_memory - стратегия оверкомитмента

  2. vm.overcommit_ratio - уровень оверкомитмента, работает только с OVERCOMMIT_NEVER

Оверкомит мема принимает такие параметры:

  1. OVERCOMMIT_GUESS 0 - анализ памяти и умное распределение.

  2. OVERCOMMIT_ALWAYS 1 - память есть всегда

  3. OVERCOMMIT_NEVER 2 - память есть только тогда, когда она есть.

Значение 0 включено по умолчанию. Для быстрого фикса аппа ставим 1, для очень суровых парней, у которых нет девушек - ставим 2.

Мониторинг

Оттрекать плохое поведение программы поможет любой мониторинг. Если на графике занятая оперативная память медленно, но уверенно лезет вверх, без никакой чистки, без Z-образных скачков - это мемори лик. Поздравляю.

Важность

Иногда, лучшим способом исправить Out of memory является тихий и уютный разговор с человеком, который забывает за собой чистить память. Что-то типа "Вася, у тебя бесконечный цикл, все сейчас упадет" - и человек ооочень быстро хотфиксит то, что должно быть запилено нормально сразу. Конечно, для того, чтобы вовремя определить и выявить проблему такого характера нужен базовый мониторинг (Graphite + Grafana + Beacon, или что-то похожее). Но и быстро временно пофиксить проблему, отсрочив Out of memory error - это тоже возможно.


Comments

comments powered by Disqus