Страницы

Сохранить статью у себя в соцсети:

суббота, 7 июля 2012 г.

§ CGROUP Memory controller.

Информация о контроллере ограничения памяти CGROUPS.

Контроллер memory используется в целях ограничения использования памяти для приложения или группы приложений. Описываю особенности контроллера, краткое описание ключей и способ применения без использования libcgroup, способ хорош своей универсальностью, также расскажу как проверить и убедиться что ограничение в силе.
Особенности:
  • учет использования анонимной памяти (RSS), страничного кэша (Page Cache), своппинга;
  • в группах используются независимые основной системы LRU;
  • возможность обратного возврата памяти в систему;
  • дополнительная возможность совместного учета и ограничения памяти и свопа;
  • возможность лимитирования памяти для буферов tcp (начиная с ядра версии 3.3);
  • иерархический учет, наследование настроек родительских групп;
  • мягкое ограничение (soft limit);
  • использование уведомлений о превышении;
  • ограничение OOM_Killer. При выключенном OOM и превышении лимита, задачи будут находиться в зависшем или уснувшем состоянии пока у них не появится возможность получить память;
  • сбор статистики в том числе и связанной с NUMA;
  • корневая группа не может быть ограничена.
Опции необходимые в ядре для поддержки контроллера памяти CGROUPS

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. Наверное баг.
Таким образом, перед тем как поместить процесс в группу лучше отключить OOM_Killer через memory.oom_control. Если процесс уже в группе то можно записать "-17" в oom_adj принадлежащий этому процессу.
Вот и все.

На главную "Virtualizing Linux"

Комментариев нет:

Отправить комментарий

Популярные сообщения

Профиль в Google+ Яндекс цитирования Яндекс.Метрика