Google Analytics

воскресенье, 24 апреля 2011 г.

Управление ресурсами с помощью cgroups

Cgroups(Control Groups) - обеспечивают механизм для агрегирования множества задач и их будущих потомков в иерархические группы с определенным поведением. Так начинается документация посвященная cgroups поставляемая с ядром Linux. Собственно это и есть достаточно ёмкое описание технологии. Но конечно же его недостаточно.
Небольшое отступление, необходимо привести конфигурацию программного обеспечения на которой выполнялись примеры - это ОС Debian GNU/Linux 6.0.1.

Как правило новые технологии изучают либо в случае поиска инструментов необходимость в которых уже назрела, либо в качестве знакомства с инструментами и потенциальной возможности их дальнейшего применения. В первом случае ответ на вопрос "Для чего это нужно?" уже получен, во втором нет. Тем не менее я приведу ответ на этот вопрос. Cgroups - это технология обеспечивающая контроль за распределением различных ресурсов доступных операционной системе между группами процессов. Что это дает? Это дает возможность при высоких нагрузках распределять ресурсы по заранее заданным правилам между группами процессов. Плюс к этом существует возможность собирать статистику по потребленным ресурсам с помощью специальной подсистемы. Где это может применяться? В любой ситуации, где необходимо распределить ресурсы между конкурирующими процессами и в которой не хватает таких механизмов как nice и т.д.

Какое описание технологии может обойтись без терминологии.

Задача(task) - процесс ОС привязанный к определенной группе, все его потомки тоже будут наследовать привязку к группе родителя.
Подсистема(subsystem) - это модуль, который позволяет использовать некоторые услуги для группу задач. Каждая подсистема может быть прикреплена только к одной иерархии.
Настраиваемый параметр(tunable parameter) - это некая сущность(представлена файлом в виртуальной ФС cgroups) с помощью которой осуществляется взаимодействие с подсистемой.
Иерархия групп(hierarchy) - это множество групп расположенных в виде дерева, так что каждая задача в системе находится точно в одной группе в иерархии и с заданным множеством(set) подсистем. Каждая группа имеет свои настраиваемые параметры, которые соответствуют множеству подсистем специфичному для данной иерархии.

Пора переходить к практике. Как это не банально, но чтобы начать работать с cgroups необходимо установить приложения для userspace.
aptitude install cgroup-bin
Теперь всё готово, чтобы использовать cgroups. Есть несколько способов управлять cgroups: набор специфичных утилит, работа стандартными средствами с виртуальной ФС, из собственного программного обеспечения через библиотеку. Наиболее подходящий для первоначального знакомства это набор специфичных утилит. Конечно можно использовать и стандартные средства и взаимодействовать с системой через файлы в виртуальной ФС (echo, cat, mount, и т.д.)

Небольшое отступление. Для того чтобы перейти к практике необходимо определить некую "сферическую задачу в вакууме". Такая задача будет звучать так: есть система с запущенными веб-контейнером Tomcat и СУБД PostgreSQL, необходимо чтобы в момент пиковой нагрузки вычислительные ресурсы CPU распределялись по заданным правила (Tomcat - 40%, PostgreSQL - 50%, оставшаяся система 10%).

Как уже было упомянуто, есть несколько подходов в работе с cgroups. Мы будем использовать специфические утилиты. Для реализации текущей задачи необходимо построить иерархию групп, где можно будет настроить распределение вычеслительных ресурсов CPU. Настройка иерархии осуществляется в файле /etc/cgconfig.conf (на самом деле её можно производить на запущенной системе, либо специфичными утилитами, либо стандартным походом с mount). Настройки из этого файла применяются при старте сервиса cgconfig. Это просто удобный способ восстанавливать иерархию cgroups после перезагрузки системы. Итак, конфигурация для текущей задачи выглядит следующим образом:
group default {
        perm {
                task {
                        uid = root;
                        gid = root;
                }
                admin {
                        uid = root;
                        gid = root;
                }
        }
        cpu {
                cpu.shares = 10;
        }
}

group daemons/tomcat {
        perm {
                task {
                        uid = root;
                        gid = root;
                }
                admin {
                        uid = root;
                        gid = root;
                }
        }
        cpu {
                cpu.shares = 40;
        }
}

group daemons/postgres {
        perm {
                task {
                        uid = root;
                        gid = root;
                }
                admin {
                        uid = root;
                        gid = root;
                }
        }
        cpu {
                cpu.shares = 50;
        }
}

mount {
        cpu = /mnt/cgroups/cpu;
        cpuacct = /mnt/cgroups/cpu;
}
Секция mount описывает подключение двух подсистем cpu и cpuacct к иерархии /mnt/cgroups/cpu. Секции group настраивают конкретные группы для всей системы(sysdefault), tomcat и postgres. В данном случае задаются права для административных функций и добавления задач admin и task соответственно. Единственный настраиваемый параметр это cpu.shares из подсистемы cpu, который определяет долю вычислительных ресурсов CPU, которые достаются группе. Теперь можно перезапускать сервис cgconfig в /mnt/cgroups, должна быть следующая иерархия.
/mnt/cgroups/
└── cpu
    ├── cgroup.procs
    ├── cpuacct.stat
    ├── cpuacct.usage
    ├── cpuacct.usage_percpu
    ├── cpu.shares
    ├── daemons
    │   ├── cgroup.procs
    │   ├── cpuacct.stat
    │   ├── cpuacct.usage
    │   ├── cpuacct.usage_percpu
    │   ├── cpu.shares
    │   ├── notify_on_release
    │   ├── postgres
    │   │   ├── cgroup.procs
    │   │   ├── cpuacct.stat
    │   │   ├── cpuacct.usage
    │   │   ├── cpuacct.usage_percpu
    │   │   ├── cpu.shares
    │   │   ├── notify_on_release
    │   │   └── tasks
    │   ├── tasks
    │   └── tomcat
    │       ├── cgroup.procs
    │       ├── cpuacct.stat
    │       ├── cpuacct.usage
    │       ├── cpuacct.usage_percpu
    │       ├── cpu.shares
    │       ├── notify_on_release
    │       └── tasks
    ├── notify_on_release
    ├── release_agent
    ├── default
    │   ├── cgroup.procs
    │   ├── cpuacct.stat
    │   ├── cpuacct.usage
    │   ├── cpuacct.usage_percpu
    │   ├── cpu.shares
    │   ├── notify_on_release
    │   └── tasks
    └── tasks
Теперь необходимо чтобы процессы запущенные в системе распределялись по нужным группам. Это можно сделать с помощью менеджера правил cgred, конфигурационный файл которого расположен в /etc/cgrules.conf. Конфигурация для нашей задачи представлена ниже:
<user>         <controllers>   <destination>
*:tomcat        cpu             daemons/tomcat/
*:postgres      cpu             daemons/postgres/
*               cpu             default/
Данные правила переносят все процессы с именем tomcat запущенных любым пользователем в группу daemons/tomcat, все процессы postgres в группу daemons/postgres и все остальные в default. Тем самым обеспечивая выполнения поставленной задачи.

Для решения задачи использовалась только одна подсистема cpu, которая отвечает за распределение вычислительных ресурсов по группам. Кроме неё в debian по умолчанию доступны следующие группы: cpuacct - для отображения потребленных ресурсов CPU; cpuset - привязывает группу к конкретному процессору; ns - обеспечивает создание именованных пространств в которых допускается взаимодействие между процессами и запрещается взаимодействие между процессами из разных пространств; devices - позволяет ограничивать доступ к устройствам; freezer - позволяет приостанавливать выполнение задач; net_cls - тегирует сетевые пакеты, и далее с помощью traffic controller реализуются различные правила для этих пакетов.

Конечно это только поверхностный обзор cgroups. Но его должно хватить для формирования представления о технологии. При наличии вопросов, добро пожаловать в комментарии.

Дополнительные источники

http://www.kernel.org/doc/Documentation/cgroups/cgroups.txt
Resource Management Guide

4 комментария:

  1. Огромнейшее спасибо за статью!

    ОтветитьУдалить
  2. Анонимный1 мая 2012 г., 23:14

    А как проверить, что всё это дело реально работает?
    Настроил по аналогии: умолчаниям выделил 70, виртуальной машине 30. Перезапустил сервисы cgconfig и cgred. Запустил через virsh виртуальную машину. В системном мониторе процесс запущенной виртуалки при запуске более 50% ЦПУ показал. Такое ощущение, что нифига не ограничивается этими группами. Или я чего-то не понимаю.

    ОтветитьУдалить
  3. Анонимный2 мая 2012 г., 18:08

    Лимит задается не жестко. Предполагается, что процессор будет использоваться на 100% (зачем чтобы он простаивал), поэтому видимо виртуальная машина и съела 50%. В случае если загрузка возрастет доступ к процессору она будет получать меньше

    ОтветитьУдалить
  4. Совершенно верно! Лимит на разделение ресурсов, а не на ограничение.

    ОтветитьУдалить