Информация о контроллере ограничения памяти CGROUPS.
Контроллер memory используется в целях ограничения использования памяти для приложения или группы приложений. Описываю особенности контроллера, краткое описание ключей и способ применения без использования libcgroup, способ хорош своей универсальностью, также расскажу как проверить и убедиться что ограничение в силе.Особенности:
- учет использования анонимной памяти (RSS), страничного кэша (Page Cache), своппинга;
- в группах используются независимые основной системы LRU;
- возможность обратного возврата памяти в систему;
- дополнительная возможность совместного учета и ограничения памяти и свопа;
- возможность лимитирования памяти для буферов tcp (начиная с ядра версии 3.3);
- иерархический учет, наследование настроек родительских групп;
- мягкое ограничение (soft limit);
- использование уведомлений о превышении;
- ограничение OOM_Killer. При выключенном OOM и превышении лимита, задачи будут находиться в зависшем или уснувшем состоянии пока у них не появится возможность получить память;
- сбор статистики в том числе и связанной с NUMA;
- корневая группа не может быть ограничена.
CONFIG_CGROUPS=y
CONFIG_CGROUP_MEM_RES_CTLR=y
CONFIG_CGROUP_MEM_RES_CTLR_SWAP=y
CONFIG_CGROUP_MEM_RES_CTLR_KMEM=y
Ключи:
tasks # интерфейс управляющий принадлежностью процессов к группе
cgroup.procs # показать список процессов
cgroup.event_control # интерфейс для event_fd()
memory.usage_in_bytes # показать текущее использование счетчика использования памяти (RSS)
memory.memsw.usage_in_bytes # показать текущее значение счетчика использования памяти и свопа
memory.limit_in_bytes # показать/установить лимит использования памяти
memory.memsw.limit_in_bytes # показать/установить лимит использования памяти и свопа
memory.failcnt # показать количество попыток превышения лимита памяти
memory.memsw.failcnt # показать количество попыток превышения лимита памяти и свопа
memory.max_usage_in_bytes # показать зафиксированное значение максимального использования памяти
memory.memsw.max_usage_in_bytes # показать зафиксированное значение максимального использования памяти и свопа
memory.soft_limit_in_bytes # показать/установить мягкий лимит использования памяти
memory.stat # показать статистику
memory.use_hierarchy # показать/установить иерархический учет
memory.force_empty # триггер возврата страниц в родительскую группу (использовать когда группе не назначены процессы)
memory.swappiness # показать/установить значение swappiness для группы
memory.move_charge_at_immigrate # показать/установить возможность перемещения страниц
memory.oom_control # показать/установить настройки OOM
memory.numa_stat # показать статистики использования памяти для NUMA узлов
memory.kmem.tcp.limit_in_bytes # показать/установить жесткий лимит для памяти TCP-буферов
memory.kmem.tcp.usage_in_bytes # показать текущее количество выделенной памяти для TCP-буферов
Пример: создадим группу и поместим туда процесс, и посмотрим правда ли он ограничивается.
- создание cgroup
# mount -t tmpfs cgroup_root /sys/fs/cgroup
# mkdir /sys/fs/cgroup/memory
# mount -t cgroup -o memory memory /sys/fs/cgroup/memory
# mkdir /sys/fs/cgroup/memory/testgroup00
- создание лимита
# cd /sys/fs/cgroup/memory/testgroup00
# echo 100M > memory.limit_in_bytes
- помещение туда процесса, запускаем dd и сразу же помещаем его в группу
# dd if=/dev/urandom of=/var/tmp/test.img bs=1M count=1000 & echo $! > tasks
Проверка лимитирования осуществляется через ключ memory.usage_in_bytes и просмотр попыток превышения через memory.failcnt.
Вообще, в соседней консоли можно запустить watch -n 1 free, а в первой консоли менять лимит в memory.limit_in_bytes, то можно будет видеть как меняется значение cached в выводе free.
Если в группу поместить уже "зажравшийся" процесс, срабатывает ограничение и если OOM не выключен то есть риск принудительного завершения процесса. В таком случае предварительно нужно выключить OOM через memory.oom_control и только потом помещать процесс в группу. Для освобождения страничного кэша, занятого этим процессом, следует выполнить drop_caches (не буду лукавить, сбросятся кэши всех процессов). В таком случае освободится память используемая в качестве кэша. Также может быть такое что процессу будет недостаточно памяти для работы, в таком случае он остановится, а в таблице процессов у него будет состояние D. В этом случае нужно просто поднять планку memory.limit_in_bytes.
Неприятности которые могут случиться:
- Иногда при записи в memory.limit_in_bytes вылазит "echo: write error: Device or resource busy". Можно игнорировать и повторить попытку.
- Когда задача работает, если часто менять memory.limit_in_bytes то рано или поздно придет OOM_Killer.
- В процессе записи memory.oom_control = 1, задача работающая в группе может быть грохнута самим OOM_Killer. Наверное баг.
Вот и все.
На главную "Virtualizing Linux"
Комментариев нет:
Отправить комментарий