Вопрос или проблема
Сегодня мы столкнулись с интересной ошибкой. На наших серверах мы распределяем пользователей по папкам cgroup, чтобы контролировать и управлять использованием ресурсов, таких как процессор и память. Мы начали получать ошибки при попытке добавить пользовательские папки cgroup для памяти:
mkdir /sys/fs/cgroup/memory/users/newuser
mkdir: cannot create directory ‘/sys/fs/cgroup/memory/users/newusers’: Cannot allocate memory
Это выглядело немного странно, потому что на машине было достаточно свободной памяти и swap. Изменение значений sysctl
для vm.overcommit_memory
с 0 на 1 не дало никакого эффекта.
Мы заметили, что у нас было довольно много пользовательских подкаталогов (около 7000 на самом деле), и большинство из них были для пользователей, которые уже не запускали процессы на этой машине.
ls /sys/fs/cgroup/memory/users/ | wc -l
7298
Удаление неиспользуемых папок в иерархии cgroup фактически решило проблему
cd /sys/fs/cgroup/memory/users/
ls | xargs -n1 rmdir
# ошибки для используемых папок, успешное удаление для неиспользуемых
mkdir /sys/fs/cgroup/memory/users/newuser
# теперь работает нормально
Интересно, что проблема затронула только память cgroup. Cgroup для процессора/учета была в порядке, хотя в ней было больше пользователей в иерархии:
ls /sys/fs/cgroup/cpu,cpuacct/users/ | wc -l
7450
mkdir /sys/fs/cgroup/cpu,cpuacct/users/newuser
# все в порядке
Итак, что вызывало эти ошибки нехватки памяти? Имеет ли подсистема memory-cgroup какой-то свой лимит памяти?
Содержимое монтирования cgroup можно найти здесь
Действительно, существуют пределы для каждой cgroup, вы можете прочитать об этом на LWN.net:
Каждая cgroup имеет связанную с ней специфическую для контроллера памяти структуру данных (mem_cgroup).
…. Учет ведется по каждой cgroup.
Максимальное количество памяти хранится в /sys/fs/cgroup/memory/memory.limit_in_bytes. Если проблема, с которой вы столкнулись, действительно была связана с лимитом памяти cgroup, то /sys/fs/cgroup/memory/memory.max_usage_in_bytes должно быть близко к вышеперечисленному, что вы также можете проверить, изучив memory.failcnt, который фиксирует количество раз, когда ваше фактическое использование достигало указанного лимита.
Возможно, вы также можете проверить memory.kmem.failcnt и memory.kmem.tcp.failcnt для получения аналогичной статистики по памяти ядра и памяти буфера tcp.
Ответ или решение
Ваше описание проблемы с ошибкой "cannot allocate memory" при создании папок в иерархии cgroup связано с управлением ресурсами в системах на базе Linux. Давайте разберемся с возможными причинами и решениями.
Основные аспекты проблемы
Вы столкнулись с ошибкой «cannot allocate memory» при попытке создания новой папки для пользователей в иерархии memory cgroup, несмотря на наличие достаточного объема свободной оперативной памяти и swap. Изменение параметра vm.overcommit_memory
не оказало влияния на ситуацию. Основная проблема, как оказалось, была решена удалением неиспользуемых пользовательских папок в иерархии.
Анализ проблемы
-
Структура cgroup и учет памяти: Cgroup (Control Group) позволяет управлять и ограничивать использование ресурсов, таких как память и процессорное время, между группами процессов на уровне ядра. Для каждой cgroup подсистемы создается специфическая структура данных, которая учитывает потребление ресурсов. В вашем случае это мемори-контроллер, который имеет ассоциированную структуру данных
mem_cgroup
. -
Ограничения памяти: Как указывалось ранее, каждая cgroup имеет память, которая ограничена параметром
/sys/fs/cgroup/memory/memory.limit_in_bytes
, и ведется учет ее использования через/sys/fs/cgroup/memory/memory.max_usage_in_bytes
. Если значение второго параметра приближается к первому, появляется риск получить "out-of-memory" ошибки. Чтобы диагностировать такие ситуации, важно проверить счётчики отказов, такие какmemory.failcnt
,memory.kmem.failcnt
иmemory.kmem.tcp.failcnt
. -
Переполненная иерархия: В вашем случае проблема могла быть вызвана большим числом существующих поддиректорий в иерархии memory cgroup. Симптомы исчезли после удаления большинства неиспользуемых папок. Зависание именно на memory cgroup объясняется тем, что различным типам cgroup могут предаваться различные внутренние ограничения на количество элементов, которые они могут обрабатывать, в зависимости от системных настроек и специфики работы подсистем.
Рекомендации и решения
-
Мониторинг и очистка: Рекомендуется регулярно проводить мониторинг и чистку старых и неиспользуемых cgroup в системах. Удобнее организовать это как автоматизированную задачу, используя cron или систему мониторинга.
-
Изменение лимитов: Проверьте текущие ограничения на количество cgroup в системе и при необходимости обновите или измените их. Это можно сделать через соответствующие файлы настроек в
/sys/fs/cgroup
. -
Диагностика и анализ: Для более углубленной диагностики можно использовать инструменты анализа использования cgroup, такие как
cgget
илиcgroups-tools
, для получения более детальной информации о потреблении ресурсов и ограничениях. -
Оптимизация конфигурации cgroup: В некоторых случаях стоит рассмотреть использование объединённых контроллеров (например,
cgroup v2
), которые могут предложить более гибкое управление ресурсами и уменьшение накладных расходов.
Эти шаги помогут предотвратить появление аналогичных проблем в будущем и улучшить стабильность и управляемость ваших серверных систем.