Linux cgroups

Чтобы ограничить ресурсы с помощью cgroup не обязательно заводить отдельное окружение (lxc-контейнер). Достаточно завести свою группу, выставить ей нужные лимиты и приписать свой процесс туда.

Пример:

$ cgcreate -g memory:/myGroup
$ echo $(( 500 * 1024 * 1024 )) > /sys/fs/cgroup/memory/myGroup/memory.limit_in_bytes
$ echo $(( 5000 * 1024 * 1024 )) > /sys/fs/cgroup/memory/myGroup/memory.memsw.limit_in_bytes

$ cgexec -g memory:myGroup myProgramm

Утилиты для работы входят в пакет libcgroup-tools (для CentOS). При желании таким же макаром можно прописать ограничения для системных пользователей или групп.

Собственно контейнера lxc по такому принципу и работают.

https://habrahabr.ru/post/266083/#comment_8560049

CGroups: Лимит на разделение ресурсов, а не на ограничение

Linux_kernel_unified_hierarchy_cgroups_and_systemd.svg

В отличие от CentOS у Debian 7 Wheezy фактически нет нормального мейнтенера подсистемы cgroups, поэтому обойтись установкой пары пакетов и правкой 1-2х конфигов не получится.

apt-get install -y cgroup-bin libcgroup1

 

Копируем примеры конфигов:

cp /usr/share/doc/cgroup-bin/examples/cgconfig.conf /etc/cgconfig.conf
cp /usr/share/doc/cgroup-bin/examples/cgconfig.sysconfig /etc/default/cgconfig
zcat /usr/share/doc/cgroup-bin/examples/cgconfig.gz > /etc/init.d/cgconfig
chmod +x /etc/init.d/cgconfig

 

Создаем спец-папку (без нее поймаем ошибку «touch: cannot touch /var/lock/subsys/cgconfig: No such file or directory [FAIL] Failed to touch /var/lock/subsys/cgconfig … failed!»):

mkdir -p /var/lock/subsys

 

Теперь добавляем cgroup для тестов, пусть это будет cpuacct, так как она не приводит к деградациям и ее можно использовать безвредно и на боевом ПО.

Добавляем в конфиг: /etc/cgconfig.conf следующие строки:

mount {
cpuacct = /mnt/cgroups/cpuacct;
}
group wwwdata {
cpuacct {
}
}

 

Теперь попробуем стартануть его:

/etc/init.d/cgconfig restart

 

Убеждаемся, что cgroup была корректно смонтирована:

cat /proc/mounts |grep cgroup
cgroup /mnt/cgroups/cpuacct cgroup rw,relatime,cpuacct 0 0

 

А сама папка выглядит примерно так:

ls -al /mnt/cgroups/cpuacct/
total 4.0K
drwxr-xr-x. 3 root root 0 Feb 5 14:04 .drwxr-xr-x. 3 root root 4.0K Feb 5 14:04 ..-rw-r--r--. 1 root root 0 Feb 5 14:04 cgroup.clone_children
--w--w--w-. 1 root root 0 Feb 5 14:04 cgroup.event_control
-rw-r--r--. 1 root root 0 Feb 5 14:04 cgroup.procs
-r--r--r--. 1 root root 0 Feb 5 14:04 cpuacct.stat
-rw-r--r--. 1 root root 0 Feb 5 14:04 cpuacct.usage
-r--r--r--. 1 root root 0 Feb 5 14:04 cpuacct.usage_percpu
-rw-r--r--. 1 root root 0 Feb 5 14:04 notify_on_release
-rw-r--r--. 1 root root 0 Feb 5 14:04 release_agent
-rw-r--r--. 1 root root 0 Feb 5 14:04 tasks
drwxr-xr-x. 2 root root 0 Feb 5 14:04 wwwdata

 

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

Снова копируем конфиги:

cp /usr/share/doc/cgroup-bin/examples/cgrules.conf /etc/cgrules.conf
cp /usr/share/doc/cgroup-bin/examples/cgred /etc/init.d/cgred
cp /usr/share/doc/cgroup-bin/examples/cgred.conf /etc/default/cgred.conf
chmod +x /etc/init.d/cgred

 

Далее правим баги мейнтейнеров Debian:

sed -i 's/sysconfig/default/' /etc/init.d/cgconfig

 

Потом добавялем туда (/etc/cgrules.conf) одну строчку в самый низ:

@www-data cpuacct wwwdata/

 

Далее отключаем создание дефалт группы (в которую система будет помещать все процессы кроме тех, которые помещены в иные группы):

vim /etc/default/cgconfig
CREATE_DEFAULT=no

 

Таким образом мы настраиваем помещение всех процессов пользователя www-data в группу с именем wwwdata.

После этого несколько раз (потому что что-то в скриптах не то и с первого раза у него не выходит размонтировать cgroup) дергаем команду:

/etc/init.d/cgconfig stop

 

И потом запускаем:

/etc/init.d/cgconfig start

 

После этого настраиваем демона cgred, который, собственно, должен распихивать процессы по cgroup:

/etc/init.d/cgred start

 

Но нас постигнет ужасное разочарование — init скрипт тупо взят из RedHat без должной доработки под особенности Debian (впрочем, в /etc/init.d/cgconfig примерное тоже самое — там вместо /etc/default используется путь /etc/sysconfig):

/etc/init.d/cgred: line 43: /etc/rc.d/init.d/functions: No such file or directory
Starting CGroup Rules Engine Daemon: /etc/init.d/cgred: line 85: daemon: command not found

Чтобы исправить это открываем /etc/init.d/cgred и комментируем 43ю строку с кодом: «/etc/rc.d/init.d/functions».

Потом ищем строку

daemon --check $servicename --pidfile $pidfile $CGRED_BIN $OPTIONS

и заменяем на:

start-stop-daemon --start --quiet --pidfile $pidfile --exec $CGRED_BIN -- $OPTIONS

 

Далее правим:

sed -i 's/sysconfig/default/' /etc/init.d/cgred

 

Еще нужно исправить группу, от имени которой будет работать демон:

vim /etc/default/cgred.conf

 

и заменяем SOCKET_GROUP=»cgred» на SOCKET_GROUP=»»

Далее нам нужно создать папку для нашей cgroup:

mkdir /mnt/cgroups/cpuacct/wwwdata

 

Итак, запускаем демона:

/etc/init.d/cgred start

 

После этого нужно инициировать перезапуск процессов, которые нам интересно поместить в cgroup, в моем случае это nginx работающий от имени пользователя www-data:

/etc/init.d/nginx reload

 

Все, теперь убеждаемся, что процессы попали в нужную cgroup:

cat /mnt/cgroups/cpuacct/wwwdata/tasks
28623
28624
28625
28626