Лимиты ресурсов в Linux

Случилась одна непонятная ситуация с контейнером и разбирательства ушли в исследование лимитов.

Проблема была связана с java. Через какое-то время в логах появлялись ошибки:

java.lang.OutOfMemoryError: unable to create native thread: possibly out of memory or process/resource limits reached

Если гуглить эту ошибку, то везде советую проверить и изменить лимиты, если такое требуется. Однако, у меня вроде всё было безлимитно (что надо), а какие-либо манипуляции не особо помогали.

Отмечу, что ошибка выше как пишут в интернете, не всегда относится именно к нехватки памяти.

Информация в интернете оказалась для мня очень разрозненной и совсем не собранной, а зачастую и копированной от статьи к статье. Делаю выдержку со всем, что накопал и что пригодилось.

nano /etc/systemd/user.conf

Ссылку на этот файл при установки лимитов нашёл далеко не срезу. Ниже пояснения к содержанию файла и установки лимитов.

Directive        ulimit equivalent     Unit
LimitCPU=        ulimit -t             Seconds      
LimitFSIZE=      ulimit -f             Bytes
LimitDATA=       ulimit -d             Bytes
LimitSTACK=      ulimit -s             Bytes
LimitCORE=       ulimit -c             Bytes
LimitRSS=        ulimit -m             Bytes
LimitNOFILE=     ulimit -n             Number of File Descriptors 
LimitAS=         ulimit -v             Bytes
LimitNPROC=      ulimit -u             Number of Processes 
LimitMEMLOCK=    ulimit -l             Bytes
LimitLOCKS=      ulimit -x             Number of Locks 
LimitSIGPENDING= ulimit -i             Number of Queued Signals 
LimitMSGQUEUE=   ulimit -q             Bytes
LimitNICE=       ulimit -e             Nice Level 
LimitRTPRIO=     ulimit -r             Realtime Priority  
LimitRTTIME=     No equivalent

Сервисы запущенны при помощи systemd игнорируют файл /etc/security/limits.conf. Очень много вопросов по форумам, почему установка лимитов в этом файле не приводит к желаемому результатов и про systemd там никто не пишет. Для таких сервисов надо указывать лимиты в конфиге /etc/systemd/system.conf или их файле запуска:

[Unit]
Description=Some Daemon
After=syslog.target network.target

[Service]
Type=notify
LimitNOFILE=20000
ExecStart=/usr/sbin/somedaemon

[Install]
WantedBy=multi-user.target

Посмотреть лимит на конкретный сервис по PID: cat /proc/PID/limits.

ulimit -c 0 # Запрещаем создавать core файлы
ulimit -d 48000 # Ограничиваем максимальный размер сегмента данных в 48 MB
ulimit -s 8192  # Ограничиваем максимальный размер стэка в 8 MB
ulimit -m 48000 # Ограничиваем максимальный размер резидентной части процесса (находящейся в ОЗУ) в  48 MB
ulimit -u 64    # Ограничиваем максимальное число запущенных этим пользователем процессов.
ulimit -n 128   # Ограничиваем максимальное число открытых файлов.
ulimit -f 100000 # Ограничиваем максимальный размер создаваемого файла в 100 MB
ulimit -v 100000 # Ограничиваем максимальный размер используемой виртуальной памяти в 100 MB

Посмотреть общее кол-во тредов в системе:

ps -elfT | wc -l

А вот скрипт, который показывает использование некоторых лимитов в процентах.

#!/bin/bash
paste <(grep 'open files\|processes\|pending signals' /proc/self/limits | cut -c27-38) <(i=`whoami` ; lsof -n -u $i 2> /dev/null | tail -n +2 | awk {'print $9'} | wc -l; 
ps --no-headers -U $i -u $i u | wc -l ; 
ps -u $i -o pid= | xargs printf "/proc/%s/status\n" |
xargs grep -s 'SigPnd' |
sed 's/.*\t//' | paste -sd+ | bc ; ) <(grep 'open files\|processes\|pending signals' /proc/self/limits | cut -c1-19) | 
while read a b name ; do printf '%3i%% %s\n' $((${b}00/a)) "$name" ; done

Вот результат его работы:

0% Max processes
14% Max open files
0% Max pending signals

# cat /proc/sys/fs/file-nr

Пример вывода:

2208 0 13061774

Первое число — общее количество занятых/используемых на данный момент времени файловых дескрипторов.
Второе число — количество выделенных процессам, но не используемых в данный момент дескрипторов.
Третье число — максимальное количество открытых дескрипторов


Open files
посмотреть hard и soft лимиты
ulimit -Hn
ulimit -Sn
Это лимиты для КАЖДОГО пользователя.

/proc/sys/fs/file-max — это лимит открытых файлов для ВСЕХ пользовалей
cat /proc/sys/kernel/pid_max — This is the maximum number of unique process identifiers your system can support


В системе есть параметр DefaultTask или DefaultTasksMax (в зависимости от версии systemd). Проверить чему он равен можно следующей командой:

systemctl show --property=DefaultTasksMax

Так на Debian 9 он у меня был равен DefaultTasksMax=4915 (и в некоторых случая это может привести к ошибкам работы программ, если это prodaction решения). На CentOS7 (OpenVZ), например, результат был DefaultTasksMax=18446744073709551615.

Чтобы изменить этот параметр или сделать его безлимитным, надо в файле /etc/systemd/system.conf найти строчку DefaultTasksMax и привести к виду:

DefaultTasksMax=infinity

После чего выполнить:

systemctl daemon-reload


Ссылки на использованный материал:

linoxide.com/limit-processes-user-level-linux/

wiki.it-kb.ru/unix-linux/linux-cli-tools/how-to-check-all-open-files-by-process-or-user-in-linux

 

Добавить комментарий