Product SiteDocumentation Site

Fedora 17

Руководство по управлению ресурсами

Управление системными ресурсами в Fedora 17

Редакция 1

Martin Prpič

Red Hat Отдел инженерной документации

Rüdiger Landmann

Red Hat Отдел инженерной документации

Douglas Silas

Red Hat Отдел инженерной документации

Юридическое уведомление

Copyright © 2012 Red Hat, Inc and others.
The text of and illustrations in this document are licensed by Red Hat under a Creative Commons Attribution–Share Alike 3.0 Unported license ("CC-BY-SA"). An explanation of CC-BY-SA is available at http://creativecommons.org/licenses/by-sa/3.0/. The original authors of this document, and Red Hat, designate the Fedora Project as the "Attribution Party" for purposes of CC-BY-SA. In accordance with CC-BY-SA, if you distribute this document or an adaptation of it, you must provide the URL for the original version.
Red Hat, as the licensor of this document, waives the right to enforce, and agrees not to assert, Section 4d of CC-BY-SA to the fullest extent permitted by applicable law.
Red Hat, Red Hat Enterprise Linux, the Shadowman logo, JBoss, MetaMatrix, Fedora, the Infinity Logo, and RHCE are trademarks of Red Hat, Inc., registered in the United States and other countries.
For guidelines on the permitted uses of the Fedora trademarks, refer to https://fedoraproject.org/wiki/Legal:Trademark_guidelines.
Linux® is the registered trademark of Linus Torvalds in the United States and other countries.
Java® is a registered trademark of Oracle and/or its affiliates.
XFS® is a trademark of Silicon Graphics International Corp. or its subsidiaries in the United States and/or other countries.
MySQL® is a registered trademark of MySQL AB in the United States, the European Union and other countries.
All other trademarks are the property of their respective owners.
Аннотация
Управление системными ресурсами в Fedora 17.

Предисловие
1. Соглашения документа
1.1. Типографические соглашения
1.2. Соглашения по выделению текста
1.3. Примечания и предупреждения
2. Нам нужны ваши отзывы!
1. Введение в контрольные группы
1.1. Организация контрольных групп
1.2. Соотношение между подсистемами, иерархиями, контрольными группами и задачами
1.3. Последствия для управления ресурсами
2. Работа с контрольными группами
2.1. Служба cgconfig
2.1.1. Файл /etc/cgconfig.conf
2.2. Создание иерархии и подключение подсистем
2.3. Подключение и отключение подсистем от существующей иерархии
2.4. Отмонтирование иерархии
2.5. Создание контрольных групп
2.6. Удаление контрольных групп
2.7. Настройка параметров
2.8. Перенос процесса в контрольную группу
2.8.1. Служба cgred
2.9. Запуск процесса в контрольной группе
2.9.1. Запуск службы в контрольной группе
2.9.2. Поведение процесса в корневой контрольной группе
2.10. Создание файла /etc/cgconfig.conf
2.10.1. Занасение параметров в черный список
2.10.2. Занесение параметров в белый список
2.11. Получение информации о контрольных группах
2.11.1. Поиск процессов
2.11.2. Поиск подсистем
2.11.3. Поиск иерархий
2.11.4. Поиск контрольных групп
2.11.5. Просмотр параметров контрольных групп
2.12. Удаление контрольных групп
2.13. Дополнительные ресурсы
3. Подсистемы и параметры настройки
3.1. Подсистема blkio
3.1.1. Опции для распределении ресурсов пропорционально весу
3.1.2. Опции для торможения ввода-вывода
3.1.3. Общие конфигурационные опции
3.1.4. Пример использования
3.2. Подсистема cpu
3.3. Подсистема cpuacct
3.4. Подсистема cpuset
3.5. Подсистема devices
3.6. Подсистема freezer
3.7. Подсистема memory
3.8. Подсистема net_cls
3.9. Подсистема net_prio
3.10. Подсистема ns
3.11. Дополнительные ресурсы
4. Примеры использования
4.1. Приоритизация ввода-вывода базы данных
4.2. Распределение вычислительных ресурсов и памяти между группами
A. История изменений

Предисловие

1. Соглашения документа

В этом руководстве используются различные стили для выделения текста.
В PDF и бумажной версиях руководства используются шрифты семейства Liberation. Эти же шрифты будут использоваться для отображения HTML-версии, если они установлены в вашей системе. В противном случае будут использоваться аналогичные шрифты. Red Hat Enterprise Linux 5 и более поздние версии включают в свой состав комплект Liberation по умолчанию.

1.1. Типографические соглашения

Для выделения текста используются четыре стиля, которые будут перечислены далее.
Моноширинный жирный шрифт
Используется для выделения вводимого текста, включая команды оболочки, а также имен файлов, путей и комбинаций клавиш. Пример:
Чтобы просмотреть содержимое файла my_next_bestselling_novel в текущем каталоге, в строке приглашения оболочки введите cat my_next_bestselling_novel и нажмите Enter для выполнения этой команды.
Приведенный текст содержит имя файла, команду оболочки и имя клавиши, которые выделены моноширинным жирным шрифтом.
Для разделения клавиш в составе комбинаций используется дефис. Пример:
Нажмите Enter для исполнения команды.
Нажмите Ctrl+Alt+F2 для перехода в первый виртуальный терминал. Нажмите Ctrl+Alt+F1 , чтобы вернуться в сессию X-Windows.
В первом примере жирным шрифтом выделено название отдельной клавиши, во втором — комбинаций клавиш.
Этим же шрифтом выделяются имена классов, методов, функций, переменных и возвращаемые ими значения. Пример:
Классы файлов включают filesystem для файловых систем, file для файлов, dir для каталогов. Каждому классу соответствует набор разрешений.
Пропорциональный жирный
Выделяет системные слова и фразы, что включает имена приложений, текст диалогов, названия меню, текст кнопок, флажков и других элементов графического интерфейса. Пример:
В главном меню выберите СистемаПараметры Мышь для запуска утилиты Настройки мыши. На вкладке Кнопки установите флажок Настроить мышь под левую руку и нажмите кнопку Закрыть, чтобы настроить мышь для левши.
Чтобы вставить специальный символ в файл gedit, выберите ПриложенияСтандартные Таблица символов. Затем в меню выберите ПоискПоиск…, введите имя символа и нажмите кнопку Найти следующее. Найденный символ будет выделен в таблице символов. Дважды щелкните на этом символе, чтобы вставить его в поле Текст для копирования и нажмите кнопку Копировать. Теперь вернитесь к вашему документу и в меню выберите ПравкаВставить.
Приведенный выше текст содержит имя приложения, названия меню, кнопок и текста элементов графического интерфейса.
Моноширинный жирный курсив или пропорциональный жирный курсив
Оба типа выделения обозначают изменяемый или заменяемый текст. Курсив сообщает о том, что не следует вводить приведенный текст напрямую, а изменить в соответствии с вашими настройками. Пример:
Для подключения к удаленной машине с помощью SSH в строке приглашения выполните ssh имя_пользователя@имя_домена. Скажем, имя удаленной машины – example.com, а ваше имя пользователя – john, тогда команда будет выглядеть так: ssh john@example.com.
Команда mount -o remount файловая_система повторно подключит заданную файловую систему. Например, для /home команда будет выглядеть так: mount -o remount /home.
Чтобы просмотреть версию установленного пакета, выполните команду rpm -q пакет. Результат команды будет представлен в формате пакет-версия-выпуск.
В приведенных примерах жирным курсивом выделяются имя пользователя, имя домена, файловой системы, пакет, его версия и выпуск.
Также курсивом выделяются термины, которые встречаются в тексте документа впервые. Пример:
Publican — система публикации DocBook.

1.2. Соглашения по выделению текста

Вывод экрана и листинг исходного кода будут отделены от окружающего текста.
Для отображения текста, который вы увидите на экране, используется моноширинный шрифт:
books        Desktop   documentation  drafts  mss    photos   stuff  svn
books_tests  Desktop1  downloads      images  notes  scripts  svgs
Для отображения содержимого исходного кода используется моноширинный шрифт:
package org.jboss.book.jca.ex1;

import javax.naming.InitialContext;

public class ExClient
{
   public static void main(String args[]) 
       throws Exception
   {
      InitialContext iniCtx = new InitialContext();
      Object         ref    = iniCtx.lookup("EchoBean");
      EchoHome       home   = (EchoHome) ref;
      Echo           echo   = home.create();

      System.out.println("Created Echo");

      System.out.println("Echo.echo('Hello') = " + echo.echo("Hello"));
   }
}

1.3. Примечания и предупреждения

Наконец, чтобы привлечь внимание читателя к важной информации, используются три стиля.

Примечание

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

Важно

На информацию, отмеченную как важную, следует обратить особое внимание. Она может включать изменения настроек текущего сеанса или, например, перечень служб, которые нужно запустить, прежде чем обновления вступят в силу. Ознакомление с важной информацией значительно облегчит вашу работу.

Предупреждение

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

2. Нам нужны ваши отзывы!

Если вы нашли опечатку в этом руководстве, или у вас есть идеи по его усовершенствованию, мы будем рады их выслушать. Пожалуйста, оставьте сообщение в Bugzilla по адресу http://bugzilla.redhat.com/bugzilla/, выбрав компонент Fedora Documentation.
Не забудьте указать в запросе идентификатор данного руководства: resource-management-guide.
Если у вас есть предложения по улучшению этого руководства, постарайтесь описать их как можно подробнее. Если же вы нашли ошибку, пожалуйста, укажите номер раздела и окружающий текст, чтобы мы могли быстро ее найти.

Глава 1. Введение в контрольные группы

Fedora 17 предоставляет механизм управления ресурсами системы — контрольные группы или cgroups(от англ. control groups). Механизм контрольных групп позволяет распределять системные ресурсы между определнными пользователем группами задач (процессов). Такими ресурсами могут быть, например, процессорное время, оперативная память, доступ к сети или их некоторая комбинация. Настроив контрольные группы, можно следить за потреблением ими ресурсов, запрещать доступ к некоторым ресурсам со стороны определенных контрольных групп и динамически менять распределение ресурсов в работающей системе. С помощью системной службы cgconfig можно обеспечить сохранение конфигурации контрольных групп между перезагрузками.
Используя контрольные группы, администратор получает возможность тонкого контроля над распределением, приоритизацией и управлением системными ресурсами. Для повышения общей эффективности ресурсы оборудования могут быть точно поделены между задачами и пользователями.

1.1. Организация контрольных групп

Подобно процессам, контрольные группы организованы иерархически, и дочерние группы наследуют некоторые атрибуты родительских. Однако между этими двумя моделями существуют различия.

Модель организации процессов Linux

Все процессы в Linux имеют одного общего предка — процесс init, который создается ядром во время загрузки системы и запускает другие процессы (которые в свою очередь запускают свои собственные дочерние процессы). Поскольку все процессы происходят от одного предка, то модель органицации процессов Linux представляет собой единую иерархическую структуру или дерево.
Кроме того, все процессы в Linux за исключением процесса init наследуют параметры среды (переменную PATH и пр.)[1] и другие атрибуты родительского процесса (дескрипторы открытых файлов и т.п.).

Модель организации контрольных групп

Контрольные группы схожи с процессами в следующем:
  • они организованы иерархически;
  • дочерние группы наследуют некоторые атрибуты родительской группы.
Основное отличие заключается в том, что в системе одновременно может существовать множество независимых иерархий контрольных групп. Если модель организации процессов в Linux — это единое дерево, то модель организации контрольных групп — это одно или несколько отдельных, несвязанных деревьев задач (т.е. процессов).
Необходимость множества отдельных иерархий контрольных групп вызвана тем, что каждая иерархия подключается к одной или нескольким подсистемам. Подсистема[2] представляет собой отдельный тип ресурса, например, процессорное время или оперативную память. В Fedora 17 существует 9 подсистем, перечисленных ниже по именам и функциям.
Подсистемы доступные в Fedora
  • blkio: ограничивает доступ к вводу-выводу на блочные устройства (диски, USB и т.п.).
  • cpu: с помощью планировщика процессов предоставляет задачам контрольных групп доступ к процессору.
  • cpuacct: генерирует отчеты об использовании процессорных ресурсов задачами, входящими в контрольную группу.
  • cpuset: выделяет определенные процессоры и узлы памяти задачам контрольной группы.
  • devices: разрешает или запрещает доступ к устройствам со стороны задач контрольной группы.
  • freezer: приостанавливает или возобновляет задачи контрольной группы.
  • memory: устанавливает органичения и генерирует отчеты об использовании памяти задачами контрольной группы.
  • net_cls: присваивает сетевым пакетам идентификатор класса (classid), который позволяет контроллеру трафика tc отличать пакеты, поступающие из заданной контрольной группы.
  • net_prio: предоставляет способ динамически устанавливать значение сетевого приоритета в пакетах, отправляемых через разные сетевые интерфейсы.
  • ns: подсистема пространства имен.

Подсистемы также называют контроллерами ресурсов

Возможно, вы уже сталкивались с термином контроллер ресурса или просто контроллер в литературе по cgroups — в справочных страницах или документации по ядру. Оба термина являются синонимами термина «подсистема» и возникли потому, что подсистема обычно планирует порядок использования ресурса или накладывает ограничения на контрольные группы той иерархии, к которой она подключена.
Понятие подсистемы (контроллера ресурсов) является достаточно общим — это нечто, что воздействует на группу задач, т.е. процессов.

1.2. Соотношение между подсистемами, иерархиями, контрольными группами и задачами

Напомним, что системные процессы в терминологии контрольных групп называются задачами.
Ниже приведены несколько простых правил, устанавливающих соотношения между подсистемами, иерархиями контрольных групп и задачами.

Правило 1

К одной иерархии может быть подключена одна или несколько подсистем.
Например, подсистемы cpu и memory (а также любое число других подсистем) могут быть подключены к одной иерархии, если каждая из них уже не подключена к какой-либо другой иерархии, к которой уже подключены другие подсистемы (см. правило 2).
Правило 1
Подключение одной или нескольких подсистем к одной иерархии.
Рисунок 1.1. Правило 1

Правило 2

Любая подсистема (например, cpu) не может быть подключена к нескольким иерархиям, если хотя бы к одной из них уже подключена другая подсистема.
Таким образом, подсистема cpu не может быть подключена к двум иерархиям, если к одной из них уже подключена подсистема memory. Однако, одна и таже подсистема может быть подключена к двум иерархиям, если к обеим иерархиям подключена только эта подсистема.
Правило 2 — номера показывают последовательность подключения подсистем.
Подключение одной подсистемы к нескольким иерархиям.
Рисунок 1.2. Правило 2 — номера показывают последовательность подключения подсистем.

Правило 3

Каждый раз, когда в системе создается новая иерархия, все системные задачи вначале попадают в состав корневой контрольной группы данной иерархии. Каждая задача может принадлежать только одной группе в иерархии. Задача может принадлежать различным группам, если они расположены в разных иерархиях. Как только задача входит в состав новой группы из той же иерархии, она удаляется из исходной группы данной иерархии. Задача никогда не принадлежит двум контрольным группам одной иерархии.
Так, например, если подсистемы cpu и memory подключены к иерархии cpu_mem_cg, а подсистема net_cls подключена к иерархии net, то процесс httpd может принадлежать одной из контрольных групп в иерархии cpu_mem_cg и одной из контрольных групп в иерархии net.
Контрольная группа в иерархии cpu_mem_cg, к которой принадлежит процесс httpd, может ограничивать выделяемое ему процессорное время до половины того времени, которое выделяется другим процессам, а память — до 1024 МБ. Кроме того, контрольная группа в иерархии net, к которой тоже принадлежит процесс httpd, может ограничивать доступную ему скорость передачи данных до 30 МБ/с.
При создании первой иерархии все задачи системы принадлежат одной контрольной группе — корневой группе. В дальнейшем каждая задача всегда принадлежит хотя бы одной контрольной группе.
Правило 3
Задача не может принадлежать двум контрольным группам, входящим в одну иерархию.
Рисунок 1.3. Правило 3

Правило 4

Если процесс Linux (задача cgroups) создает дочерний процесс (задачу), то дочерняя задача наследует членство во всех контрольных группах родительской задачи. Впоследствии дочерние задачи можно перенести в другие контрольные группы. Как только родительский процесс создал дочерний, они полностью независимы.
Рассмотрим, например, задачу httpd, принадлежащую контрольной группе half_cpu_1gb_max из иерархии cpu_mem_cg и контрольной группе trans_rate_30 из иерархии net. Когда процесс httpd порождает дочерний процесс, то он автоматически попадает в члены контрольных групп half_cpu_1gb_max и trans_rate_30. Дочерняя задача наследует членство в тех же самых контрольных группах, что и родительская задача.
Начиная с этого момента, родительская и дочерняя задача полностью независимы друг от друга: изменение членства в контрольных группах одной задачи не затрагивает другую. Изменения контрольных групп родительской задачи никоим образом не влияют на ее потомков. Таким образом, любая дочерняя задача первоначально наследует членство в контрольных группах родительской задачи, но впоследствии это членство может быть изменено или отменено.
Правило 4 — номера показывают последовательность событий при порождении новой задачи.
Порожденная задача наследует членство в контрольных группах родительской задачи.
Рисунок 1.4. Правило 4 — номера показывают последовательность событий при порождении новой задачи.

1.3. Последствия для управления ресурсами

  • Так как задача может принадлежать лишь одной контрольной группе в иерархии, то каждая подсистема имеет возможность наложить на задачу лишь один набор ограничений или как-либо повлиять на задачу. Это логическое следствие, а не недостаток.
  • Несколько подсистем можно сгруппировать так, чтобы они влияли на все задачи в одной иерархии. Поскольку контрольные группы в данной иерархии имеют разный набор параметров, то эти задачи будут затронуты поразному.
  • Структура иерархии может меняться. Например, какая-то подсистема может быть отключена от одной иерархии с несколькими подсистемами и добавлена к новой, отдельной иерархии.
  • И наоборот, если необходимость в разделении подсистем по отдельным иерархиям отпала, то можно удалить одну иерархию и подключить ее подсистемы к другой.
  • Архитектура допускает простое использование механизма контрольных групп — например, установку нескольких параметров для отдельных задач в рамках одной иерархии, к которой подключены только подсистемы cpu и memory.
  • Архитектура также допускает создание очень точных настроек. Например, каждая задача (процесс) может быть членом всех иерархий, к каждой из которых подключена всего одна подсистема. Такая конфигурация предоставляет системному администратору полный контроль над всеми параметрами каждой отдельной задачи.


[1] Родительский процесс может изменить параметры среды до передачи их дочернему процессу.
[2] В документации и на справочных страницах, включенных в пакет libcgroup-tools, подсистемы также называются контроллерами ресурсов или просто контроллерами.

Глава 2. Работа с контрольными группами

Проще всего работать с контрольными группами с помощью утилит из пакета libcgroup-tools. В принципе, можно монтировать иерархии и устанавливать параметры контрольных групп в помощью обычных команд и утилит доступных в любой системе. Однако, использование утилит из пакет libcgroup-tools упрощает процесс и расширяет возможности. Поэтому в данном руководстве рассматриваются способы работы с использованием команд из libcgroup-tools. В большинстве случаев также приводятся эквивалентные команды оболочки, что должно помочь понять внутренний механизм работы. Тем не менее, мы рекомендуем использовать команды из пакета libcgroup-tools везде, где это возможно.

Установка пакета libcgroup-tools

Перед началом работы с контрольными группами убедитесь, что на систему установлен пакет libcgroup-tools. Выполните следующую команду как пользователь root:
~]# yum install libcgroup-tools

2.1. Служба cgconfig

Служба cgconfig устанавливатеся вместе с пакетом libcgroup-tools и рекомендуется для создания иерархий, подключения подсистем и управления контрольными группами.
В Fedora 17 служба cgconfig запускается по умолчанию. При загрузке системы или при перезапуске службы с помощью команды systemctl restart cgconfig.service она считывает файл /etc/cgconfig.conf, что позволяет ей воссоздавать конфигурацию контрольных групп, описанную в этом файле. В зависимости от содержания конфигурационного файла служба cgconfig может создавать иерархии, монтировать требуемые файловые системы, создавать контрольные группы и устанавливать параметры подсистем для каждой из них.
По умолчанию файл /etc/cgconfig.conf, поставляемый с пакетом libcgroup-tools, приводит к созданию и монтированию отдельных иерархий для каждой из подсистем, а затем к подключению каждой подсистемы к соответствующей иерархии.
При остановке службы cgconfig (с помощью команды systemctl stop cgconfig.service ) она отмонтирует все смонтированные ею иерархии.

2.1.1. Файл /etc/cgconfig.conf

Файл /etc/cgconfig.conf содержит два основных типа записей — mount и group. Записи mount указывают, какие иерархии должны быть созданы и смонтированы в качестве виртуальных файловых систем, и какие подсистемы должны быть к ним подключены. Используется следующая синтаксическая структура:
mount {
    <подсистема> = <путь>;
    …
}
Пример 2.1. Создание записи mount
Пример создания иерархии для подсистемы cpuset:
mount {
    cpuset = /cgroup/red;
}
Та же конфигурация с помощью обычных команд:
~]# mkdir /cgroup/red
~]# mount -t cgroup -o cpuset red /cgroup/red

Записи типа group содержат определения контрольных групп и параметры подсистем. Они имеют следующую синтаксическую структуру:
group <имя> {
    [<права>]
    <подсистема> {
        <параметр> = <значение>;
        …
    }
    …
}
Секция права не является обязательной. Для указания прав доступа используется следующий синтаксис:
perm {
    task {
        uid = <пользователь>;
        gid = <группа>;
    }
    admin {
       uid = <администратор>;
       gid = <административная группа>;
    }
}
Пример 2.2. Создание записи group
Приведенный ниже пример показывает создание контрольной группы для SQL-демонов, задачи в которую могут добавлять пользователи из группы sqladmin, а изменять параметры подсистем может пользователь root.
group daemons/sql {
    perm {
        task {
            uid = root;
            gid = sqladmin;
        } admin {
            uid = root;
            gid = root;
        }
    } cpu {
        cpu.shares = 100;
    }
}
В сочетании с приведенными выше командами монтирования (см. Пример 2.1, «Создание записи mount») эквивалентный набор команд будет выглядеть так:
~]# mkdir -p /cgroup/cpu/daemons/sql
~]# chown root:root /cgroup/cpu/daemons/sql/*
~]# chown root:sqladmin /cgroup/cpu/daemons/sql/tasks
~]# echo 100 > /cgroup/cpu/daemons/sql/cpu.shares

Перезапустите cgconfig, чтобы ввести в силу изменения

Необходимо перезапустить службу cgconfig, чтобы изменения, внесенные в файл /etc/cgconfig.conf, вступили в силу:
~]# systemctl restart cgconfig.service 
При установке пакета libcgroup-tools создается файл /etc/cgconfig.conf. Знаки # в начале строки обозначают комментарии, которые игнорируются службой cgconfig.

2.2. Создание иерархии и подключение подсистем

Влияние на работающую систему

Приведенные ниже инструкции, относящиеся к созданию новой иерархии и подключению к ней подсистем, подразумевают, что контрольные группы еще не настроены. В этом случае выполнение инструкций не повлияет на работу системы. Однако, изменение параметров контрольной группы может немедленно отразиться на входящих в нее задачах.
Если в системе уже настроены контрольные группы (вручную или с помощью службы cgconfig), то приведенные здесь команды могут не сработать. В этом случае вначале нужно отмонтировать существующие иерархии, что может повлиять на работу системы. Не рекомендуется экспериментировать с настройками на рабочих системах.
Для создания иерархии и подключения к ней подсистем добавьте записи в секцию mount в файле /etc/cgconfig.conf (в режиме root). Записи в секции mount имеют следующий формат:
подсистема = /cgroup/иерархия;
При следующем записке служба cgconfig создаст иерархию и подключит к ней подсистемы.
Приведенный ниже пример показывает создание иерархии cpu_and_mem и подключение к ней подсистем cpu, cpuset, cpuacct и memory.
mount {
    cpuset  = /cgroup/cpu_and_mem;
    cpu     = /cgroup/cpu_and_mem;
    cpuacct = /cgroup/cpu_and_mem;
    memory  = /cgroup/cpu_and_mem;
}

Альтернативный метод

Для создания иерархий и подключения подсистем можно использовать обычные команды и утилиты.
В режиме root создайте каталог с именем иерархии, который будет служить ее точкой монтирования:
~]# mkdir /cgroup/имя_иерархии
Например:
~]# mkdir /cgroup/cpu_and_mem
Затем, используя команду mount, смонтируйте иерархию и одновременно подключите к ней одну или несколько подсистем. Например:
~]# mount -t cgroup -o подсистемы имя_иерархии /cgroup/имя_иерархии
Здесь подсистемы — это список подсистем, разделенных запятой. Краткое описание всех доступных подсистем приведено в Подсистемы доступные в Fedora, а полное описание в Глава 3, Подсистемы и параметры настройки.
Пример 2.3. Подключение подсистем с помощью команды mount
В следующем примере в качестве точки монтирования новой иерархии будет использоваться уже существующий каталог /cgroup/cpu_and_mem. К иерархии cpu_and_mem будут подключены подсистемы cpu, cpuset и memory, а сама иерархия будет смонтирована в /cgroup/cpu_and_mem:
~]# mount -t cgroup -o cpu,cpuset,memory cpu_and_mem /cgroup/cpu_and_mem
Список всех доступных подсистем и их текущих точек монтирования (т.е. точек монтирования иерархий, к которым подключены соответствующие подсистемы) можно получить с помощью команды lssubsys[3]:
~]# lssubsys -am
cpu,cpuset,memory /cgroup/cpu_and_mem
net_cls
ns
cpuacct
devices
freezer
blkio
Вывод команды показывает, что:
  • подсистемы cpu, cpuset и memory подключены к иерархии смонтированной в /cgroup/cpu_and_mem, и
  • подсистемы net_cls, ns, cpuacct, devices, freezer и blkio пока не подключены ни к какой иерархии, о чем свидетельствует отсутствие соответствующих точек монтирования.

2.3. Подключение и отключение подсистем от существующей иерархии

Чтобы добавить, удалить или переместить подсистему в другую иерархию, надо внести изменения в секцию mount в файле /etc/cgconfig.conf (см. Раздел 2.2, «Создание иерархии и подключение подсистем»). Изменения вступят в силу после перезапуска службы cgconfig.

Альтернативный метод

Для того, чтобы добавить неподключенную подсистему к существующей иерархии, надо перемонтировать ее. В список опций команды mount нужно добавить опцию remount и название подсистемы.
Пример 2.4. Перемонтирование иерархии для добавления подсистемы
Вывод команды lssubsys показывает, что к иерархии cpu_and_mem подключены подсистемы cpu, cpuset и memory:
~]# lssubsys -am
cpu,cpuset,memory /cgroup/cpu_and_mem
net_cls
ns
cpuacct
devices
freezer
blkio
Перемонтируем иерархию cpu_and_mem с опцией remount и добавим cpuacct в список подсистем:
~]# mount -t cgroup -o remount,cpu,cpuset,cpuacct,memory cpu_and_mem /cgroup/cpu_and_mem
Вывод команды lssubsys теперь показывает, что подсистема cpuacct подключена к иерархии cpu_and_mem:
~]# lssubsys -am
cpu,cpuacct,cpuset,memory /cgroup/cpu_and_mem
net_cls
ns
devices
freezer
blkio

Аналогичным образом можно отключить подсистему от иерархии. Для этого нужно перемонтировать иерархию, опустив название подсистемы из списка параметров после опции -o. Например, отключить подсистему cpuacct можно так:
~]# mount -t cgroup -o remount,cpu,cpuset,memory cpu_and_mem /cgroup/cpu_and_mem

2.4. Отмонтирование иерархии

Для отмонтирования иерархии контрольных групп используется команда umount:
~]# umount /cgroup/имя_иерархии
Например:
~]# umount /cgroup/cpu_and_mem
Пустая иерархия (т.е. иерархия, содержащая только корневую контрольную группу) деактивируется после отмонтирования. Если же она содержит другие группы, то она остается активной на уровне ядра даже после отмонтирования на уровне файловой системы.
Перед отмонтированием иерархии надо либо убедиться, что все дочернии контрольные группы удалены, либо использовать команду cgclear, которая способна деактивировать даже непустую иерархию (см. Раздел 2.12, «Удаление контрольных групп»).

2.5. Создание контрольных групп

Для создания контрольных групп используется команда cgcreate. Синтаксис команды:
cgcreate -t uid:gid -a uid:gid -g подсистемы:путь
где
  • -t (необязательный) — определяет пользователя (uid) и группу (gid), которым будет принадлежать псевдофайл tasks создаваемой контрольной группы. Этот пользователь сможет добавлять задачи в контрольную группу.

    Удаление задач

    Удалить задачу из контрольный группы можно только переместив ее в другую группу. При этом пользователь должен обладать правами записи в ту группу, куда перемещается задача, а правда записи в исходную группу не требуются.
  • -a (необязательный) — определяет пользователя (uid) и группу (gid), которым будут принадлежать все остальные псевдофайлы контрольной группы кроме псевдофайла tasks. Этот пользователь может изменять уровень доступа к системным ресурсам со стороны задач данной контрольной группы.
  • -g — определяет одну или несколько иерархий, в которых должна быть создана контрольная группа. Иерархии задаются как параметр подсистемы, в виде разделенного запятыми списка подсистем. Если входящие в список подсистемы подключены к разным иерархиям, то контрольная группа создается в каждой из них. Список завершается двоеточием, после которого следует путь к группе относительно вершины иерархии, причем точка монтирования иерархии не указывается.
    Например, контрольная группа в каталоге /cgroup/cpu_and_mem/lab1/ обозначается просто как lab1. Путь к ней определяется однозначно, так как для заданной подсистемы существует только одна иерархия. Группа контролируется всеми подсистемами в иерархиях, где она создана, даже если некоторые подсистемы не перечислены явно в команде cgcreate (см. Пример 2.5, «Использование cgcreate»).
Поскольку все контрольные группы в иерархии имеют одни и те же контроллеры, то дочерние группы имеют те же контроллеры, что и родительские группы.
Пример 2.5. Использование cgcreate
Представим, что подсистемы cpu и memory вместе подключены к иерархии cpu_and_mem, а подсистема net_cls — к иерархии net. Выполним команду:
~]# cgcreate -g cpu,net_cls:/test-subgroup
Команда cgcreate создаст две группы с именем test-subgroup — одну в иерархии cpu_and_mem, а другую в иерархии net. Группа test-subgroup в иерархии cpu_and_mem будет контролироваться подсистемой memory, хотя она и не указана в команде cgcreate.

Альтернативный метод

Для создания дочерней контрольной группы можно использовать команду mkdir:
~]# mkdir /cgroup/иерархия/имя/новая_группа
Например:
~]# mkdir /cgroup/cpuset/lab1/group1

2.6. Удаление контрольных групп

Для удаления контрольных групп служит команда cgdelete. По синтаксису она похожа на команду cgcreate:
cgdelete подсистемы:путь
где
  • подсистемы — разделенный запятыми список подсистем.
  • путь — путь к контрольной группе от корня иерархии.
Например:
~]# cgdelete cpu,net_cls:/test-subgroup
Команда cgdelete с опцией -r осуществляет рекурсивное удаление всех подгрупп.
При удалении контрольной группы ее задачи перемещаются в родительскую группу.

2.7. Настройка параметров

Пользователь с правами модификации контрольной группы может менять параметры подсистем с помощью команды cgset. Например, если существует группа /cgroup/cpuset/group1, то чтобы разрешить ей доступ к заданым процессорам, следует выполнить команду:
cpuset]# cgset -r cpuset.cpus=0-1 group1
Команда cgset имеет следующий синтаксис:
cgset -r параметр=значение путь_к_контрольной_группе
где
  • параметр — устанавливаемый параметр, которому соответствует файл в каталоге контрольной группы;
  • значение — присваемое параметру значение;
  • путь — путь к контрольной группе от корня иерархии. Например, команда установки параметра в корневой группе (если существует файл /cgroup/cpuacct/) будет выглядеть так:
    cpuacct]# cgset -r cpuacct.usage=0 /
    Поскольку знак . указывает положение относительно корня иерархии (т.е. соответствует корневой группе), то команда может выглядеть так:
    cpuacct]# cgset -r cpuacct.usage=0 .
    Предпочтительнее использовать синтаксис со знаком /.

    Установка параметров в корневой группе

    Только небольшое число параметров может быть установлено в корневой группе (например, приведенный выше параметр cpuacct.usage). Это объясняется тем, что корневой группе принадлежат все ресурсы, поэтому изменение настроек на этом уровне ограничит все существующие процессы, что нецелесообразно.
    Следующая команда устанавливает параметр в контрольной группе group1, которая является подгруппой корневой группы:
    cpuacct]# cgset -r cpuacct.usage=0 group1
    Добавление знака косой черты после названия группы (cpuacct.usage=0 group1/) необязательно.
Значения параметров, которые можно устанавливать с помощью команды cgset, зависят от значений параметров на верхних уровнях иерархии. Например, если группе group1 доступен только процессор 0, то подгруппе group1/subgroup1 нельзя разрешить использовать процессоры 0 и 1 или только процессор 1.
С помощью команды cgset можно копировать параметры из одной контрольной группы в другую. Например:
~]# cgset --copy-from group1/ group2/
Синтаксис команды копирования:
cgset --copy-from откуда куда
где
  • откуда — путь к исходной контрольной группе, чьи параметры должны быть скопированы, указанный относительно корневой группы иерархии;
  • куда — путь к контрольной группе, куда должны быть скопированы параметры, указанный относительно корневой группы иерархии.
Прежде чем приступать к копированию, необходимо убедиться, что все обязательные параметры подсистем установлены. В противном случае, команда копирования не сработает (см. Обязательные параметры).

Альтернативный метод

Установить параметры контрольной группы можно напрямую, указав значения параметров как вывод команды echo и перенаправив его в псевдофайл соответствующей подсистемы. Ниже приведен пример установки значения 0-1 в псевдофайле cpuset.cpus контрольной группы group1:
~]# echo 0-1 > /cgroup/cpuset/group1/cpuset.cpus
При установке таких значений задачам этой контрольной группы будет разрешено использовать только процессоры 0 и 1.

2.8. Перенос процесса в контрольную группу

Процесс можно перенести в контрольную группу командой cgclassify:
~]# cgclassify -g cpu,memory:group1 1701
Синтаксис команды cgclassify:
cgclassify -g подсистемы:путь процессы
где
  • подсистемы — разделенный запятыми список подсистем или символ *, означающий, что процессы следует запустить во всех иерархиях, связанных со всеми доступными подсистемами. Если в нескольких иерархиях существуют контрольные группы с тем же именем, то при использовании опции -g процессы будут помещены во все эти группы. Следует убедиться, что указанная контрольная группа существует во всех иерархиях, чьи подсистемы перечислены в команде;
  • путь — путь к контрольной группе внутри иерархии;
  • процессы — разделенный пробелами список идентификаторов процессов.
Кроме этого, если перед списком параметров процессы добавить опцию --sticky, то все дочерние процессы будут оставаться в той же контрольной группе. Если эта опция не используется, но при этом работает служба cgred, то дочерние процессы будут перераспределены в контрольные группы в соответствии с правилами, указанными в файле /etc/cgrules.conf. Родительский процесс, тем не менее, будет оставаться в первоначально указанной контрольной группе.
С помощью команды cgclassify можно сразу переместить несколько процессов. Например, следующая команда переместит процессы 1701 и 1138 в контрольную группу group1/:
~]# cgclassify -g cpu,memory:group1 1701 1138
Отметим, что список идентификаторов процессов разделяется пробелами, и что указанные группы должны находиться в разных иерархиях.

Альтернативный метод

Чтобы напрямую переместить процесс в контрольную группу, нужно записать его идентификатор в файл tasks этой группы. Например, чтобы переместить процесс 1701 в контрольную группу /cgroup/lab1/group1/:
~]# echo 1701 > /cgroup/lab1/group1/tasks

2.8.1. Служба cgred

Служба cgred, запускающая демон cgrulesengd, отвечает за перемещение задач в контрольные группы в соответствии с параметрами, заданными в файле /etc/cgrules.conf. Записи в файле /etc/cgrules.conf имеют одну из двух форм:
  • пользователь  подсистемы  контрольная_группа
  • пользователь:команда  подсистемы   контрольная_группа
Например:
maria			devices		/usergroup/staff
Эта запись показывает, что все процессы, принадлежащие пользователю maria, имеют доступ к подсистеме devices в соответствии с параметрами, установленными в контрольной группе /usergroup/staff. Чтобы сопоставить отдельные команды контрольным группам, нужно указать их после имени пользователя:
maria:ftp		devices		/usergroup/staff/ftp
Теперь, если пользователь maria запускает команду ftp, то соответствующий процесс будет автоматически помещен в контрольную группу /usergroup/staff/ftp в иерархии, содержащей подсистему devices. Стоит отметить, что перенос процесса осуществляется только после выполнения заданного условия. Поэтому, процесс ftp какое-то короткое время может исполняться в не той группе. Более того, если процесс быстро порождает потомков, пока он еще находится не в той группе, то нет гарантии, что потомки будут корректно перемещены.
Записи в файле /etc/cgrules.conf могут включать следующие дополнительные обозначения:
  • @ перед именем пользователя обозначает не отдельного пользователя, а группу. Например, значение @admins включает всех пользователей в группе admins.
  • * обозначает "все". Так, знак * в поле подсистема обозначает все подсистемы.
  • % копирует элемент из предыдущей строки. Например:
    @adminstaff		devices		/admingroup
    @labstaff		%		%
    

2.9. Запуск процесса в контрольной группе

Обязательные параметры

Некоторые подсистемы имеют обязательные параметры, которые должны быть установлены до того, как задачу можно будет переместить в контрольную группу, использующую любую из этих подсистем. Например, прежде, чем перемещать задачу в контрольную группу, использующую подсистему cpuset, необходимо определить значения cpuset.cpus и cpuset.mems.
Приведенные в этой секции примеры показывают правильный синтаксис команд, но будут работать только при условии, что заданы обязательные параметры используемых контроллеров. Если контроллеры еще не настроены, то приведенные примеры работать не будут.
Описание того, какие из параметров подсистем являются обязательными, приведено в Глава 3, Подсистемы и параметры настройки.
Для запуска процессов в контрольной группе используется команда cgexec. Ниже приведен пример запуска браузера lynx в пределах группы group1, на которую накладываются ограничения подсистемой cpu:
~]# cgexec -g cpu:group1 lynx http://www.redhat.com
Команда cgexec имеет следующий синтаксис:
cgexec -g подсистемы:путь команда аргументы
где
  • подсистемы — разделенный запятыми список подсистем или символ *, означающий, что процесс следует запустить во всех иерархиях, связанных со всеми доступными подсистемами. Так же, как и в случае команды cgset (см. Раздел 2.7, «Настройка параметров»), если в нескольких иерархиях существуют контрольные группы с тем же именем, то при использовании опции -g процесс будет помещен в каждую из них. Следует убедиться, что указанная контрольная группа существуют во всех иерархиях, чьи подсистемы перечислены в команде;
  • путь — путь к контрольной группе от вершины иерархии;
  • команда — команда, которая должна быть запущена;
  • аргументы — любые аргументы команды.
Кроме этого, если перед параметром процессы добавить опцию --sticky, то все дочерние процессы будут оставаться в той же контрольной группе. Если эта опция не используется, но при этом работает служба cgred, то дочерние процессы будут перераспределены в контрольные группы в соответствии с правилами, указанными в файле /etc/cgrules.conf. Родительский процесс, тем не менее, будет оставаться в той контрольной группе, где он был изначально запущен.

Альтернативный метод

Новый процесс наследует контрольную группу родительского процесса. Поэтому, чтобы запустить процесс в выбранной контрольной группе, вначале можно перенести в эту группу процесс интерпретатора команд (см. Раздел 2.8, «Перенос процесса в контрольную группу») и уже затем запустить процесс из под интерпретатора. Например:
~]# echo $$ > /cgroup/lab1/group1/tasks
lynx
Отметим, что даже после окончания работы lynx интерпретатор команд остается в контрольной группе group1. Поэтому еще лучше следующий способ:
~]# sh -c "echo \$$ > /cgroup/lab1/group1/tasks && lynx"

2.9.1. Запуск службы в контрольной группе

Можно сконфигурировать некоторые службы так, чтобы они запускались в контрольной группе. Службы, которые пока не перешли на использование конфигурационных файлов systemd, должны удовлетворять следующим условиям:
  • использовать файл /etc/sysconfig/имя_службы;
  • для запуска процесса службы использовать функцию daemon() из /etc/init.d/functions.
Чтобы сделать так, что удовлетворяющая условиям служба запускалась в контрольной группе, надо добавить запись CGROUP_DAEMON="подсистема:группа" в ее конфигурационный файл в каталоге /etc/sysconfig. Параметр подсистема — это подсистема, подключенная к какой-либо иерархии, а параметр группа — это контрольная группа в этой иерархии. Например:
CGROUP_DAEMON="cpuset:daemons/sql"

2.9.2. Поведение процесса в корневой контрольной группе

Некоторые параметры подсистем blkio и cpu иначе влияют на процессы (задачи), работающие в корневой контрольной группе, нежели на процессы в подгруппах. Рассмотрим следующий пример:
  1. Две подгруппы созданы под одной корневой группой: /rootgroup/red/ и /rootgroup/blue/
  2. В каждой подгруппе и в корневой группе определен параметр cpu.shares, и ему присвоено значение 1.
Если при таких условиях поместить по одному процессу в каждую группу (т.е. иметь по одной задаче в /rootgroup/tasks, /rootgroup/red/tasks и /rootgroup/blue/tasks), то каждый процесс будет потреблять по 33.33% времени центрального процессора:
Процесс в /rootgroup/:      33.33%
Процесс в /rootgroup/blue/: 33.33%
Процесс в /rootgroup/red/:  33.33%
Если в подгруппы blue и red поместить другие процессы, то они будут делить между собой те 33.33% времени центрального процессора, которые были выделены каждой подгруппе.
Однако, если поместить несколько процессов в корневую группу, то ресурсы центрального процессора будут делиться по процессами, а не по группам. Например, если в корневой группе /rootgroup/ находится три процесса, а в подгруппах /rootgroup/red/ и /rootgroup/blue/ — по одному, и параметр cpu.shares имеет значение 1 во всех группах, то ресурсы процессора поделятся следующим образом:
Процессы в /rootgroup/:      20% + 20% + 20%
Процессы в /rootgroup/blue/: 20%
Процессы в /rootgroup/red/:  20%
Поэтому при использовании подсистем blkio и cpu рекомендуется переместить все процессы из корневой группы в подгруппы, где потребление ресурсов можно регулировать с помощью весовых коэффициентов или процентных долей (например, cpu.shares или blkio.weight). Перемещение всех задач из корневой группы в одну из подгрупп, можно выполнить так:
rootgroup]# cat tasks >> red/tasks
rootgroup]# echo > tasks

2.10. Создание файла /etc/cgconfig.conf

Конфигурация для файла /etc/cgconfig.conf может быть сгенерирована из текущей конфигурации контрольных групп с использованием утилиты cgsnapshot. Эта утилита фиксирует текущее состояние всех подсистем и контрольных групп и возвращает результат в таком виде, который можно использовать в файле /etc/cgconfig.conf. Пример 2.6, «Использование утилиты cgsnapshot» показывает пример использования утилиты cgsnapshot.
Пример 2.6. Использование утилиты cgsnapshot
Создадим конфигурацию контрольных групп с помощью следующих команд:
~]# mkdir /cgroup/cpu
~]# mount -t cgroup -o cpu cpu /cgroup/cpu
~]# mkdir /cgroup/cpu/lab1
~]# mkdir /cgroup/cpu/lab2
~]# echo 2 > /cgroup/cpu/lab1/cpu.shares
~]# echo 3 > /cgroup/cpu/lab2/cpu.shares
~]# echo 5000000 > /cgroup/cpu/lab1/cpu.rt_period_us
~]# echo 4000000 > /cgroup/cpu/lab1/cpu.rt_runtime_us
~]# mkdir /cgroup/cpuacct
~]# mount -t cgroup -o cpuacct cpuacct /cgroup/cpuacct
Приведенные выше команды подключают две подсистемы и создают две контрольных группы для подсистемы cpu со специфическими значениями для некоторых ее параметров. Выполнив команду cgsnapshot (с опцией -s и пустым файлом /etc/cgsnapshot_blacklist.conf[4]), получим следующий вывод:
~]$ cgsnapshot -s
# Configuration file generated by cgsnapshot
mount {
        cpu = /cgroup/cpu;
        cpuacct = /cgroup/cpuacct;
}

group lab2 {
        cpu {
                cpu.rt_period_us="1000000";
                cpu.rt_runtime_us="0";
                cpu.shares="3";
        }
}

group lab1 {
        cpu {
                cpu.rt_period_us="5000000";
                cpu.rt_runtime_us="4000000";
                cpu.shares="2";
        }
}
В приведенном выше примере команда cgsnapshot используется с опций -s, что позволяет ей игнорировать все предупреждения о том, что некоторые параметры не определены в «черном» или «белом» списке утилиты cgsnapshot (см. Раздел 2.10.1, «Занасение параметров в черный список» и Раздел 2.10.2, «Занесение параметров в белый список»).

По умолчанию утилита cgsnapshot направляет результат в стандартный вывод. Используя опцию -f, можно перенаправить вывод в файл. Например:
~]$ cgsnapshot -f ~/test/cgconfig_test.conf

Опция -f приводит к перезаписи указанного файла

При использовании опции -f вывод утилиты cgsnapshot перезаписывает содержимое указанного файла. Поэтому, не рекомендуется направлять вывод прямо в файл /etc/cgconfig.conf.
Утилита cgsnapshot может создавать конфигурационные файлы для отдельных подсистем. Если указать имя подсистемы в качестве параметра команды, то вывод будет содержать только конфигурационные параметры данной подсистемы:
~]$ cgsnapshot cpuacct
# Configuration file generated by cgsnapshot
mount {
        cpuacct = /cgroup/cpuacct;
}

2.10.1. Занасение параметров в черный список

Утилита cgsnapshot позволяет заносить параметры в черный список. Если параметр занесен в черный список, то он не попадает в вывод, генерируемый утилитой cgsnapshot. По умолчанию каждый параметр проверяется на наличие в черном списке в файле /etc/cgsnapshot_blacklist.conf. Если параметр не указан в черном списке, то проверяется белый список. Чтобы указать другой черный список, используется опция -b. Например:
~]$ cgsnapshot -b ~/test/my_blacklist.conf

2.10.2. Занесение параметров в белый список

Дополнительно утилита cgsnapshot позволяет заносить параметры в белый список. Если параметр занесен в белый список, то он появляется в выводе, генерируемом утилитой cgsnapshot. Если параметра нет ни в черном, ни в белом списках, то появляется предупреждение:
~]$ cgsnapshot -f ~/test/cgconfig_test.conf
WARNING: variable cpu.rt_period_us is neither blacklisted nor whitelisted
WARNING: variable cpu.rt_runtime_us is neither blacklisted nor whitelisted
По умолчанию файл с белым списком отсутствует. Для указания файла с белым списком используется опция -w. Например:
~]$ cgsnapshot -w ~/test/my_whitelist.conf
Указание опции -t заставляет утилиту cgsnapshot генерировать конфигурацию с параметрами только из белого списка.

2.11. Получение информации о контрольных группах

2.11.1. Поиск процессов

Чтобы посмотреть, какой контрольной группе принадлежит процесс, выполните:
~]$ ps -O cgroup
Если известен идентификатор процесса (PID), то можно выполнить команду
~]$ cat /proc/PID/cgroup

2.11.2. Поиск подсистем

Для получения информации о подсистемах, поддерживаемых ядром, и о том, как они подключены к иерархиям, выполните команду
~]$ cat /proc/cgroups
Чтобы получить информацию о точках подключения отдельных подсистем, выполните команду
~]$ lssubsys -m подсистемы
где подсистемы — это список некоторых подсистем. Отметим, что команда lssubsys -m возвращает для каждой иерархии только точки монтирования верхнего уровня.

2.11.3. Поиск иерархий

Иерархии рекомендуется монтировать в каталог /sys/fs/cgroup. Тогда список иерархий можно получить путем просмотра этого каталога. Если в системе установлена программа tree, то ее можно использовать, чтобы получить общее представление о всех иерархиях и созданных в них контрольных группах:
~]$ tree /sys/fs/cgroup/

2.11.4. Поиск контрольных групп

Чтобы вывести список существующих в системе контрольных групп, выполните команду
~]$ lscgroup
Вывод команды можно ограничить до отдельной иерархии, если указать ее контроллер и путь в формате подсистема:путь. Например:
~]$ lscgroup cpuset:adminusers
возвратит список подгрупп контрольной группы adminusers в иерархии, к которой подключена подсистема cpuset.

2.11.5. Просмотр параметров контрольных групп

Чтобы посмотреть параметры некоторых контрольных групп, выполните команду
~]$ cgget -r параметрr список_групп
где параметр — это псевдофайл с настройками подсистемы, а список_групп — это список контрольных групп, разделенных пробелами. Например:
~]$ cgget -r cpuset.cpus -r memory.limit_in_bytes lab1 lab2
показывает значения параметров cpuset.cpus и memory.limit_in_bytes в контрольных группах lab1 и lab2.
Если точные названия параметров неизвестны, то можно использовать команду так:
~]$ cgget -g cpuset /

2.12. Удаление контрольных групп

Эта команда удаляет все контрольные группы

Команда cgclear удаляет все контрольные группы во всех иерархиях. Если структура иерархий не сохранена в конфигурационном файле, то восстановить ее будет непросто.
Команда cgclear служит для очистки всей файловой системы контрольных групп.
Все задачи контрольных групп перемещаются в корневой узел иерархии, все контрольные группы удаляются, файловая система контрольных групп отмонтируется, и, таким образом, удаляются все смонтированные ранее иерархии. Наконец, сам каталог, куда была смонтирована файловая система контрольных групп, тоже удаляется.

Точный список всех смонтированных контрольных групп

Если контрольные группы создаются с помощью команды mount (а не с помощью службы cgconfig), то об этом остаются записи в файле /etc/mtab (в таблице смонтированных файловых систем). Факт монтирования также отражается в файле /proc/mounts. Однако, при удалении контрольных групп с помощью команды cgclear, а также при использовании других команд cgconfig, задействуется прямой интерфейс с ядром, который вносит изменения в файл /proc/mounts, но не изменяет файл /etc/mtab. Поэтому, после удаления контрольных групп командой cgclear, отмонтированные контрольные группы могут быть все еще видны в файле /etc/mtab и, следовательно, будут показываться командой mount. Для получения точного списка всех смонтированных контрольных групп нужно использовать данные из файла /proc/mounts.

2.13. Дополнительные ресурсы

Информацию о командах управления контрольными группами можно найти на справочных страницах, включенных в пакет libcgroup-tools. В приведенном ниже списке указаны номера секций, к которым относятся справочные страницы.
Справочные страницы libcgroup-tools
  • man 1 cgclassify — команда cgclassify осуществляет перемещение задач между контрольными группами.
    man 1 cgclear — команда cgclear удаляет все контрольные группы в иерархии.
    man 5 cgconfig.conf — конфигурация контрольных групп определяется в файле cgconfig.conf.
    man 8 cgconfigparser — команда cgconfigparser осуществляет разбор файла cgconfig.conf и монтирует иерархии.
    man 1 cgcreate — команда cgcreate создает в иерархиях новые контрольные группы.
    man 1 cgdelete — команда cgdelete удаляет указанные контрольные группы.
    man 1 cgexec — команда cgexec запускает задачи в указанных контрольных группах.
    man 1 cgget — команда cgget показывает значения параметров контрольных групп.
    man 1 cgsnapshot — команда cgsnapshot генерирует конфигурационный файл на основании текущего состояния подсистем.
    man 5 cgred.conf — файл cgred.conf содержит конфигурацию для службы cgred.
    man 5 cgrules.conf — файл cgrules.conf содержит правила, определяющие принадлежность задач к некоторым контрольным группам.
    man 8 cgrulesengd — служба cgrulesengd распределяет задачи по контрольным группам.
    man 1 cgset — команда cgset устанавливает значения параметров контрольных групп.
    man 1 lscgroup — команда lscgroup показывает список контрольных групп в иерархии.
    man 1 lssubsys — команда lssubsys показывает список иерархий, к которым подключены указанные подсистемы.


[3] Команда lssubsys входит в состав пакета libcgroup-tools. См. Глава 2, Работа с контрольными группами
[4] Обычно параметр cpu.shares по умолчанию указывается в файле /etc/cgsnapshot_blacklist.conf, что приводит к тому, что он не попадает в сгенерированный вывод команды cgsnapshot (Пример 2.6, «Использование утилиты cgsnapshot»). Поэтому, для иллюстрации в примере используется пустой файл /etc/cgsnapshot_blacklist.conf.

Глава 3. Подсистемы и параметры настройки

Подсистемы — это модули ядра с поддержкой механизма контрольных групп. Обычно они являются контроллерами ресурсов, то есть распределяют ресурсы между контрольными группами. Однако, подсистемы могут быть разработаны и для выполнения других функций. Например, в тех случаях, когда желательно влиять на поведение ядра и обращаться с какими-то группами процессов особым образом. Прикладной программный интерфейс (API, Application Programming Interface) для разработки новых подсистем описан в файле cgroups.txt в документации по ядру операционной системы. Этот файл поставляется в составе пакета kernel-doc и находится в каталоге /usr/share/doc/kernel-doc-kernel-version/Documentation/cgroups/. Последняя версия документации по контрольным группам доступна по адресу http://www.kernel.org/doc/Documentation/cgroups/cgroups.txt. Следует учитывать, что возможности, описанные в последней версии документации, могут отличаться от возможностей контрольных групп, поддерживаемых установленным в системе ядром.
Объекты состояния, содержащие параметры подсистем контрольной группы, представлены в виде псевдофайлов в виртуальной файловой системе контрольных групп. Проводить операции с псевдофайлами можно с помощью команд оболочки или эквивалентных системных вызовов. Например, cpuset.cpus — это псевдофайл, в котором указываются номера процессоров доступных контрольной группе. Если /cgroup/cpuset/webserver — это контрольная группа для web-сервера, то можно выполнить следующую команду:
~]# echo 0,2 > /cgroup/cpuset/webserver/cpuset.cpus
Значение 0,2, записанное в псевдофайл cpuset.cpus, разрешит всем процессам, чьи идентификаторы перечислены в /cgroup/cpuset/webserver/tasks, использовать только процессоры 0 и 2.

3.1. Подсистема blkio

Подсистема блочного ввода-вывода (blkio) управляет доступом задач контрольных групп к вводу-выводу на блочные устройства. Запись значений в некоторые из ее псевдофайлов ограничивает доступ или скорость доступа к устройствам, а чтение этих псевдофайлов предоставляет информацию об операциях ввода-вывода.
Подсистема blkio предоставляет два способа для управления доступом к вводу-выводу:
  1. Распределение ресурсов пропорционально весу — этот способ, реализованный в CFQ-планировщике[5] ввода-вывода, позволяет назначать контрольным группам весовые коэффициенты. Таким образом, за каждой контрольной группой резервируется какой-то процент от всех операций ввода-вывода пропорциональный весовому коэффициенту группы (см. Раздел 3.1.1, «Опции для распределении ресурсов пропорционально весу»).
  2. Торможение ввода-вывода (установка верхнего предела) — этот способ устанавливает верхний предел числа опареций ввода-вывода, выполняемых некоторым устройством. Это означает, что подсистема blkio ограничивает количество операций read и write, направляемых на исполнение драйверу устройства за единицу времени (см. Раздел 3.1.2, «Опции для торможения ввода-вывода»).

Операций записи с буферизацией

В настоящее время подсистема blkio не работает для операций записи с буферизацией. Главным образом она ориентирована на прямой ввод-вывод, хотя и работает для буферизованных операций чтения.

3.1.1. Опции для распределении ресурсов пропорционально весу

blkio.weight
Определяет относительную долю (вес в диапазоне от 100 до 1000), используемую по умолчанию при планировании доступа контрольной группы к блочным устройствам ввода-вывода. Значение для отдельных устройств может быть переопределено параметром blkio.weight_device. Пример присвоения значения 500 в качестве веса контрольной группы при доступе к блочным устройствам:
echo 500 > blkio.weight
blkio.weight_device
Определяет относительную долю (вес в диапазоне от 100 до 1000), используемую при планировании доступа к вводу-выводу на указанное блочное устройство со стороны контрольной группы. Этот параметр имеет приоритет над параметром blkio.weight. Значения параметра задаются в следующем формате: старший_номер:младший_номер  вес. Номера типов устройств представлены в списке устройств Linuxhttp://www.kernel.org/doc/Documentation/devices.txt. Например, чтобы присвоить контрольной группе вес 500 при доступе к устройству /dev/sda, надо выполнить:
echo 8:0 500 > blkio.weight_device
В списке устройств значение 8:0 соответствует /dev/sda.
blkio.time
Возвращает продолжительность времени, в течение которого контрольная группа пользовалась доступом к вводу-выводу перечисленных устройств. Каждая запись содержит три поля: старший_номер, младший_номер и время. Номера типов устройств определены в списке устройств Linux, а время указывается в миллисекундах.
blkio.sectors
Возвращает число секторов, переданных контрольной группой через перечисленные устройства. Каждая запись состоит из трех полей: старший_номер, младший_номер и число_секторов. Номера типов устройств определены в списке устройств Linux, а число_секторов — это число записанных и прочитанных секторов диска.
blkio.io_serviced
На основании данных CFQ-планировщика возвращает число операций ввода-вывода, выполненных контрольной группой на перечисленных устройствах. Каждая запись состоит из четырех полей: старший_номер, младший_номер, тип_операции и число. Номера типов устройств определены в списке устройств Linux, тип_операции — это один из типов: Read — чтение, Write — запись, Sync — операции синхронного ввода-вывода, Async — операции асинхронного ввода-вывода, Total — все операции, число — число операций, соответствующего типа.
blkio.io_service_bytes
На основании данных CFQ-планировщика возвращает число байт, переданных контрольной группой через перечисленные устройства. Каждая запись состоит из четырех полей: старший_номер, младший_номер, тип_операции и число_байт. Номера типов устройств определены в списке устройств Linux, тип_операции — это один из типов: Read — чтение, Write — запись, Sync — операции синхронного ввода-вывода, Async — операции асинхронного ввода-вывода, Total — все операции, число_байт — число переданных байтов, соответствующего типа.
blkio.io_service_time
На основании данных CFQ-планировщика возвращает для каждого устройства продолжительность времени, затраченного на выполнение операций ввода-вывода, инициированных котрольной группой, начиная с момента диспетчиризации запроса до его завершения. Каждая запись состоит из четырех полей: старший_номер, младший_номер, тип_операции и время. Номера типов устройств определены в списке устройств Linux, тип_операции — это один из типов: Read — чтение, Write — запись, Sync — операции синхронного ввода-вывода, Async — операции асинхронного ввода-вывода, Total — все операции, время — продолжительность времени в наносекундах. Время указывается в наносекундах, а не в более крупных единицах, так как это позволяет предоставлять полезную информацию даже для быстрых устройств, таких как SSD-диски.
blkio.io_wait_time
Возвращает совокупное время, проведенное в очередях планировщика операциями ввода-вывода, которые были инициированы контрольной группой. При интерпретации результатов следует учитывать следующее:
  • Показываемое время может превышать время, проведенное контрольной группой в состоянии ожидания завершения операций ввода-вывода, так как возвращаемое значение представляет собой сумму времен ожидания всех операций ввода-вывода контрольной группы. Время ожидания самой контрольной группы представлено параметром blkio.group_wait_time.
  • Если драйвер устройства поддерживает очередь запросов ввода-вывода длинной queue_depth > 1, то возвращаемое значение времени включает в себя только время, затрачиваемое на диспетчеризацию запросов, и не включает время ожидания обслуживания устройством.
Каждая запись состоит из четырех полей: старший_номер, младший_номер, тип_операции и время. Номера типов устройств определены в списке устройств Linux, тип_операции — это один из типов: Read — чтение, Write — запись, Sync — операции синхронного ввода-вывода, Async — операции асинхронного ввода-вывода, Total — все операции, время — продолжительность времени в наносекундах. Время указывается в наносекундах, а не в более крупных единицах, так как это позволяет предоставлять полезную информацию даже для быстрых устройств, таких как SSD-диски.
blkio.io_merged
Возвращает число выполненных слияний запросов ввода-вывода среди всех запросов, инициированных контрольной группой. Каждая запись состоит из четырех полей: старший_номер, младший_номер, тип_операции и число. Номера типов устройств определены в списке устройств Linux, тип_операции — это один из типов: Read — чтение, Write — запись, Sync — операции синхронного ввода-вывода, Async — операции асинхронного ввода-вывода, Total — все операции, число — число запросов ввода-вывода каждого типа, для которых было выполнено слияние.
blkio.io_queued
Возвращает число запросов ввода-вывода, инициированных контрольной группой, которые были поставлены в очередь. Каждая запись состоит из четырех полей: старший_номер, младший_номер, тип_операции и число. Номера типов устройств определены в списке устройств Linux, тип_операции — это один из типов: Read — чтение, Write — запись, Sync — операции синхронного ввода-вывода, Async — операции асинхронного ввода-вывода, Total — все операции, число — число запросов ввода-вывода каждого типа, поставленных в очередь.
blkio.avg_queue_size
Возвращает среднюю длину очереди запросов ввода-вывода контрольной группы за все время ее существования. Длина очереди замеряется каждый раз, когда система выделяет фрагмент времени на ее обработку. Данный параметр доступен только тогда, когда ядро системы скомпилировано с опцией CONFIG_DEBUG_BLK_CGROUP=y. В ядре, поставляемом с Fedora 17, эта опция не установлена.
blkio.group_wait_time
Возвращает общее время (в наносекундах), в течение которого контрольная группа ожидает предоставления фрагмента времени на обработку одной из своих очередей. Значение обновляется каждый раз, когда система выделяет фрагмент времени на обработку очереди контрольной группы. Таким образом, во время считывания значения из псевдофайла, соответствующего данному параметру, в нем не отражается время ожидания для операций ввода-вывода, которые в данный момент находятся в очереди. Данный параметр доступен только тогда, когда ядро системы скомпилировано с опцией CONFIG_DEBUG_BLK_CGROUP=y. В ядре, поставляемом с Fedora 17, эта опция не установлена.
blkio.empty_time
Возвращает общее время (в наносекундах), в течение которого контрольная группа не имеет запросов ввода-вывода в состоянии ожидания. Значение обновляется каждый раз, когда в очереди данной контрольной группы появляется запрос в состоянии ожидания. Таким образом, если во время считывания значения из псевдофайла, соответствующего данному параметру, контрольная группа не имеет запросов в состоянии ожидания, то в считанном значении не будет отражена текущая продолжительность времени нахождения контрольной группой в этом состоянии. Данный параметр доступен только тогда, когда ядро системы скомпилировано с опцией CONFIG_DEBUG_BLK_CGROUP=y. В ядре, поставляемом с Fedora 17, эта опция не установлена.
blkio.idle_time
Возвращает общее время (в наносекундах), которое планировщик проводит в ожидании более подходящего запроса ввода-вывода по сравнению с уже имеющимися запросами от данной контрольной группы или других групп. Значение обновляется каждый раз, когда планировщик прекращает свое ожидание. Таким образом, если считывать псевдофайл пока планировщик находится в ожидании, то в считанном значении не будет отражена текущая продолжительность времени нахождения планировщиком в этом состоянии. Данный параметр доступен только тогда, когда ядро системы скомпилировано с опцией CONFIG_DEBUG_BLK_CGROUP=y. В ядре, поставляемом с Fedora 17, эта опция не установлена.
blkio.dequeue
Возвращает число запросов ввода-вывода, инициированных контрольной группой, которые были удалены из очереди устройством. Каждая запись состоит из трех полей: старший_номер, младший_номер и число. Номера типов устройств определены в списке устройств Linux, а число — это число запросов ввода-вывода, удаленных из очереди. Данный параметр доступен только тогда, когда ядро системы скомпилировано с опцией CONFIG_DEBUG_BLK_CGROUP=y. В ядре, поставляемом с Fedora 17, эта опция не установлена.

3.1.2. Опции для торможения ввода-вывода

blkio.throttle.read_bps_device
Определяет верхний предел числа операций чтения, которые устройство может выполнять. Темп операций чтения указывается в байтах в секунду. Каждая запись состоит из трех полей: старший_номер, младший_номер и число_байт_в_сек. Номера типов устройств определены в списке устройств Linux, а число_байт_в_сек — это верхний предел темпа выполнения операций чтения. Например, ограничить скорость чтения с устройства /dev/sda до 10МБ/с можно так:
~]# echo "8:0 10485760" > /cgroups/blkio/test/blkio.throttle.read_bps_device
blkio.throttle.read_iops_device
Определяет верхний предел числа операций чтения, которые устройство может выполнять. Темп чтения указывается в числе операций в секунду. Каждая запись состоит из трех полей: старший_номер, младший_номер и число_операций_в_сек. Номера типов устройств определены в списке устройств Linux, а число_операций_в_сек — это верхний предел разрешенного темпа выполнения операций чтения. Например, ограничить скорость чтения с устройства /dev/sda до 10 операций в секунду можно так:
~]# echo "8:0 10" > /cgroups/blkio/test/blkio.throttle.read_iops_device
blkio.throttle.write_bps_device
Определяет верхний предел числа операций записи, которые устройство может выполнять. Темп операций заприси указывается в байтах в секунду. Каждая запись состоит из трех полей: старший_номер, младший_номер и число_байт_в_сек. Номера типов устройств определены в списке устройств Linux, а число_байт_в_сек — это верхний предел темпа выполнения операций записи. Например, ограничить скорость записи на устройство /dev/sda до 10МБ/с можно так:
~]# echo "8:0 10485760" > /cgroups/blkio/test/blkio.throttle.write_bps_device
blkio.throttle.write_iops_device
Определяет верхний предел числа операций записи, которые устройство может выполнять. Темп записи указывается в числе операций в секунду. Каждая запись состоит из трех полей: старший_номер, младший_номер и число_операций_в_сек. Номера типов устройств определены в списке устройств Linux, а число_операций_в_сек — это верхний предел разрешенного темпа выполнения операций записи. Например, ограничить скорость записи на устройство /dev/sda до 10 операций в секунду можно так:
~]# echo "8:0 10" > /cgroups/blkio/test/blkio.throttle.write_iops_device
blkio.throttle.io_serviced
На основании данных, собираемых механизмом торможения, возвращает число операций ввода-вывода, инициированных контрольной группой и выполненных перечисленными устройствами. Каждая запись состоит из четырех полей: старший_номер, младший_номер, тип_операции и число. Номера типов устройств определены в списке устройств Linux, тип_операции — это один из типов: Read — чтение, Write — запись, Sync — операции синхронного ввода-вывода, Async — операции асинхронного ввода-вывода, Total — все операции, число — число выполненных операций ввода-вывода.
blkio.throttle.io_service_bytes
Возвращает число байт, переданных контрольной группой через перечисленные устройства. Единственное отличие между blkio.io_service_bytes и blkio.throttle.io_service_bytes состоит в том, что последний параметр не обновляется каждый раз, когда CFQ-планировщик выполняет операции над очередью запросов ввода-вывода. Каждая запись состоит из четырех полей: старший_номер, младший_номер, тип_операции и число_байт. Номера типов устройств определены в списке устройств Linux, тип_операции — это один из типов: Read — чтение, Write — запись, Sync — операции синхронного ввода-вывода, Async — операции асинхронного ввода-вывода, Total — все операции, число_байт — число переданных байтов, соответствующего типа.

3.1.3. Общие конфигурационные опции

Следующие опции могут использоваться вместе с каждым из механизмов управления, реализованных в подсистеме blkio (см. Раздел 3.1, «Подсистема blkio»).
blkio.reset_stats
Сбрасывает статистику, представленную в других псевдофайлах. Запись целого числа в этот файл приводит к сбросу статистики работы контрольной группы.

3.1.4. Пример использования

Ниже представлен простой пример, основанных на выполнении двух процессов dd в двух контрольных группах с разными значениями параметра blkio.weight (см. Пример 3.1, «Распределение ресурсов подсистемой blkio пропорционально весовому коэффициенту»).
Пример 3.1. Распределение ресурсов подсистемой blkio пропорционально весовому коэффициенту
  1. Подключим подсистему blkio:
    ~]# mount -t cgroup -o blkio blkio /cgroup/blkio/
    
  2. Создадим две контрольных группы для подсистемы blkio:
    ~]# mkdir /cgroup/blkio/test1/
    ~]# mkdir /cgroup/blkio/test2/
    
  3. Установим весовые коэффициенты подсистемы blkio в созданных контрольных группах:
    ~]# echo 1000 > /cgroup/blkio/test1/blkio.weight
    ~]# echo 500 > /cgroup/blkio/test2/blkio.weight
    
  4. Создадим два файла:
    ~]# dd if=/dev/zero of=file_1 bs=1M count=4000
    ~]# dd if=/dev/zero of=file_2 bs=1M count=4000
    
    Приведенные выше команды создают два файла (file_1 и file_2) размером 4 ГБ.
  5. В каждой из тестовых контрольных групп выполним команды dd применительно к одному из больших файлов (каждая команда читает содержимое файла и выводит его в устройство /dev/null):
    ~]# cgexec -g blkio:test1 time dd if=file_1 of=/dev/null
    ~]# cgexec -g blkio:test2 time dd if=file_2 of=/dev/null
    
    По окончании работы обе команды выводят время своего исполнения.
  6. Скорость ввода-вывода двух процессов dd можно отслеживать с помощью утилиты iotop. Для ее установки надо выполнить в режиме root команду yum install iotop. Ниже приведен пример того, как может выглядеть вывод утилиты iotop во время работы процессов dd:
    Total DISK READ: 83.16 M/s | Total DISK WRITE: 0.00 B/s
        TIME  TID  PRIO  USER     DISK READ  DISK WRITE  SWAPIN      IO    COMMAND
    15:18:04 15071 be/4 root       27.64 M/s    0.00 B/s  0.00 % 92.30 % dd if=file_2 of=/dev/null
    15:18:04 15069 be/4 root       55.52 M/s    0.00 B/s  0.00 % 88.48 % dd if=file_1 of=/dev/null
    

Для того, чтобы Пример 3.1, «Распределение ресурсов подсистемой blkio пропорционально весовому коэффициенту» дал более точный результат, перед запуском процессов dd следует сбросить содержимое буферов файловой системы и освободить кэши страниц, каталогов и индексных дескрипторов файлов. Для этого надо выполнить следующие команды:
~]# sync
~]# echo 3 > /proc/sys/vm/drop_caches
Кроме этого, можно включить режим изоляции групп, обеспечивающий более строгую изоляцию между группами за счет снижения пропускной способности ввода-вывода. Когда изоляция групп выключена, то справедливое распределение ресурсов обеспечивается только для рабочей нагрузки с последовательным доступом. По умолчанию режим изоляции групп включен, что обеспечивает справедливое распределение ресурсов при вводе-выводе со случайным доступом. Для включения режима изоляции групп следует выполнить команду
~]# echo 1 > /sys/block/<диск>/queue/iosched/group_isolation
где <диск> — это имя устройства, например, sda.

3.2. Подсистема cpu

Подсистема cpu отвечает за управление доступом контрольных групп к процессорам. Планирование доступа осуществляется в зависимости от перечисленных ниже параметров, каждый из которых представлен в виде псевдофайла в файловой системе контрольных групп:
cpu.shares
Целое число, определяющее относительную долю процессорного времени, предоставляемого задачам контрольной группы. Например, задачи в двух контрольных группах, для которых значение cpu.shares равно 1, будут получать равное время доступа к процессору, а задачи в контрольной группе, где параметр cpu.shares имеет значение 2, будут получать в два раза больше времени.
cpu.rt_runtime_us
Значение этого параметра, заданное в микросекундах, определяет для задач контрольной группы, имеющих приоритет реального времени, максимальную продолжительность непрерывного использования ресурсов процессора. Установка этого параметра позволяет предотвратить монополизацию доступа к процессору со стороны задач одной контрольной группы. Если задачи контрольной группы должны иметь возможность получать доступ к процессору на 4 секунды каждые 5 секунд, то можно установить значение параметра cpu.rt_runtime_us равным 4000000, а параметра cpu.rt_period_us равным 5000000.
cpu.rt_period_us
Значение этого параметра, заданное в микросекундах, определяет для задач контрольной группы, имеющих приоритет реального времени, то, с какой регулярностью ресурсы процессора будут перераспределяться в их пользу. Если задачи контрольной группы должны иметь возможность получать доступ к процессору на 4 секунды каждые 5 секунд, то можно установить значение параметра cpu.rt_runtime_us равным 4000000, а параметра cpu.rt_period_us равным 5000000.

3.3. Подсистема cpuacct

Подсистема cpuacct создает очеты об использовании процессорных ресурсов задачами контрольной группы и дочерних подгрупп. Существует три типа отчетов:
cpuacct.usage
Возвращает суммарное время (в наносекундах), в течение которого процессорные ресурсы были заняты обработкой задач контрольной группы (включая задачи на нижних уровнях иерархии).

Сброс счетчика cpuacct.usage

Для того, чтобы сбросить счетчик cpuacct.usage, выполните следующую команду:
~]# echo 0 > /cgroups/cpuacct/cpuacct.usage
Эта команда также сбрасывает значение счетчика cpuacct.usage_percpu.
cpuacct.stat
Возвращает суммарное процессорное время, проведенное задачами контрольной группы (включая задачи на низких уровнях иерархии) в пользовательском и системном режимах. Отчет предоставляется в виде двух строк:
  • user — процессорное время, потребленное задачами в пользовательском режиме.
  • system — процессорное время, потребленное задачами в системном режиме (режиме ядра).
Процессорное время указывается в единицах, определенных переменной USER_HZ.
cpuacct.usage_percpu
Возвращает процессорное время (в наносекундах), потребленное задачами контрольной группы (включая задачи на нижних уровнях иерархии) на каждом процессоре.

3.4. Подсистема cpuset

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

Обязательные параметры

У некоторых подсистем существуют обязательные параметры. Если такая подсистема подключена к контрольной группе, то ее обязательные параметры необходимо определить до того, как в контрольную группу можно будет переносить задачи. Так, например, прежде чем переносить задачи в контрольную группу, использующую подсистему cpuset, в ней надо определить параметры cpuset.cpus и cpuset.mems.
cpuset.cpus (обязательный)
Определяет список процессоров, к которым имеют доступ задачи данной контрольной группы. Номера процессоров в списке разделяются запятой. Для обозначения диапазона используется дефис. Например, список
0-2,16
представляет процессоры 0, 1, 2 и 16.
cpuset.mems (обязательный)
Определяет список узлов памяти, к которым разрешен доступ задачам данной контрольной группы. Номера узлов в списке разделяются запятой. Для обозначения диапазона используется дефис. Например, список
0-2,16
представляет узлы памяти 0, 1, 2 и 16.
cpuset.memory_migrate
Содержит флаг (0 или 1), определяющий нужно ли переносить страницы памяти на другой узел при изменении значений в файле cpuset.mems. По умолчанию эта функциональность отключена (0) и страницы остаются на исходном узле, даже если узел не включен в обновленный список в файле cpuset.mems. Если же флаг установлен (1), то страницы будут перенесены на узлы памяти, перечисленные в новом списке из файла cpuset.mems. При этом по возможности будет поддерживаться их относительное размещение; так, например, при наличии свободного места страницы памяти со второго узла в исходном списке будут перенесены на второй узел в обновленном списке cpuset.mems.
cpuset.cpu_exclusive
Содержит флаг (0 или 1), исключающий возможность включения процессоров, перечисленных в cpuset.cpus, в какие-либо иные cpuset-наборы, отличные от данного, а так же его предков или потомков. По умолчанию (значение 0) процессоры могут включаться в разные cpuset-наборы.
cpuset.mem_exclusive
Содержит флаг (0 или 1), определяющий возможность включения узлов памяти, перечисленных в cpuset.mems, в какие-либо иные cpuset-наборы. По умолчанию (значение 0) узлы памяти могут входить в разные cpuset-наборы. Их резервирование для одного cpuset-набора (значение 1) функционально эквивалентно жесткому делению памяти с помощью установки флага в файле cpuset.mem_hardwall.
cpuset.mem_hardwall
Содержит флаг (0 или 1), запрещающий ядру выделять страницы памяти или буфера данных где-либо, кроме узлов памяти данного cpuset-набора. По умолчанию (значение 0) страницы и буфера данных могут совместно использоваться процессами, принадлежащими разным пользователям. В режиме жесткого деления памяти (значение 1) все выделение памяти для задач производится отдельно.
cpuset.memory_pressure
Этот файл доступен только для чтения и содержит среднее значение нагрузки на память, создаваемую процессами, работающими на данном наборе процессоров. Значение файла обновляется автоматически, если включен флаг cpuset.memory_pressure_enabled. В противном случае оно равно нулю.
cpuset.memory_pressure_enabled
Содержит флаг (0 или 1), определяющий должна ли система вычислять нагрузку на память, создаваемую процессами данной контрольной группы. Значения рассчитываются умножением числа попыток высвобождения занятой памяти в секунду на 1000 и становятся доступными через файл cpuset.memory_pressure.
cpuset.memory_spread_page
Содержит флаг (0 или 1), определяющий должно ли производиться равномерное распределение буферов файловой системы между всеми узлами памяти, выделенными данному cpuset-набору. По умолчанию (значение 0) равномерное распределение не выполняется, и буфера размещаются на том же узле памяти, где работает создающий их процесс.
cpuset.memory_spread_slab
Содержит флаг (0 или 1), определяющий должно ли производиться равномерное распределение в пределах cpuset-набора slab-кэшей ядра для поддержки операций ввода-вывода файлов. По умолчанию (значение 0) равномерное распределение не выполняется, и slab-кэши размещаются на том же узле памяти, где работает создающий их процесс.
cpuset.sched_load_balance
Содержит флаг (0 или 1), определяющий должна ли производиться балансировка нагрузки между процессорами, включенных в cpuset-набор. По умолчанию (значение 1) ядро равномерно распределяет нагрузку на все процессоры путем перемещения процессов на менее загруженные процессоры.
Отметим, что установка значения этого флага в контрольной группе не будет иметь никакого эффекта, если балансировка нагрузки включена в одной из ее родительских контрольных групп, так как в этом случае балансировка уже выполняется на более высоком уровне иерархии. Таким образом, чтобы отключить балансировку нагрузки в контрольной группе, необходимо отключить ее у всех предков данной контрольной группы. При этом следует оценить, нужна ли балансировка нагрузки в соседних контрольных группах на том же уровне иерархии.
cpuset.sched_relax_domain_level
Содержит целое значение от -1 до небольшого положительного числа, определяющее число процессоров, между которыми будет распределяться нагрузка. Это значение не используется, если отключен флаг cpuset.sched_load_balance.
Точное определение воздействия этого числа зависит от архитектуры, но приведенные ниже значения являются достаточно типичными:
Значения параметра cpuset.sched_relax_domain_level
ЗначениеВоздействие
-1Использовать для балансировки нагрузки системное значение по умолчанию
0Не выполнять немедленную балансировку нагрузки; делать это только периодически
1Немедленно балансировать нагрузку между потоками одного процессорного ядра
2Немедленно балансировать нагрузку между соседними ядрами процессора
3Немедленно балансировать нагрузку между процессорами на одном узле или blade-модуле
4Немедленно балансировать нагрузку между несколькими процессорами в системах с неоднородным доступом к памяти (NUMA)
5Немедленно балансировать нагрузку между всеми процессорами в NUMA-системах

3.5. Подсистема devices

Подсистема devices отвечает за предоставление доступа к устройствам со стороны задач контрольной группы.
devices.allow
Задает устройства, к которым разрешен доступ задачам контрольной группы. Каждая запись состоит из четырех полей: тип, старший_номер, младший_номер и доступ. Значение полей тип, старший_номер и младший_номер определены в списке устройств Linux (см. http://www.kernel.org/doc/Documentation/devices.txt).
тип
Допустимые значения поля тип:
  • a — применяется ко всем устройствам, как к символьным, так и к блочным;
  • b — задает блочное устройство;
  • c — задает символьное устройство.
старший_номер, младший_номер
Поля старший_номер и младший_номер однозначно идентифицируют устройства Linux. Их значения описаны в списке устройств Linux. Поля разделяются двоеточием. Например, старший номер 8 соответствует SCSI-дискам, а младший номер 1 соответствует первому разделу на первом SCSI-диске; следовательно, 8:1 однозначно определяет раздел, представленный в файловой системе как /dev/sda1.
Звездочка (знак «*») может использоваться для обозначения любого старшего или младшего номера устройства. Например, 9:* обозначает все RAID-устройства, а *:* — все устройства.
доступ
Значение поля доступ задается последовательностью из одной или нескольких перечисленных ниже букв:
  • r — разрешает задачам осуществлять чтение из заданного устройства;
  • w — разрешает задачам осуществлять запись на заданное устройство;
  • m — разрешает задачам создавать файлы устройств, если они еще не существуют.
Например, если значение поля доступ задано как r, то задачи могут выполнять только чтение с заданного устройства, а если значение задано как rw, то задачи могут осуществлять чтение и запись.
devices.deny
Задает устройства, к которым запрещен доступ задачам контрольной группы. Формат записей аналогичен devices.allow.
devices.list
Возвращает список устройств, для которых были определены правила доступа со стороны задач контрольной группы.

3.6. Подсистема freezer

Подсистема freezer отвечает за приостанавку и возобновление задач контрольной группы.
freezer.state
Параметр имеет три возможных значения:
  • FROZEN — задачи контрольной группы приостановлены.
  • FREEZING — система находится в процессе приостановки задач контрольной группы.
  • THAWED — исполнение задач контрольной группы возобновлено.
Чтобы приостановить работу конкретного процесса, надо сделать следующее:
  1. Переместите процесс в контрольную группу той иерархии, к которой подключена подсистема freezer.
  2. Остановите работу этой группы, тем самым приостановив работу процесса, который в ней находится.
Нельзя перемещать процесс в уже остановленную ("замороженную") контрольную группу.
Стоит отметить, что значения FROZEN и THAWED могут быть записаны в параметр freezer.state, а значение FREEZING записывать нельзя, его можно только прочитать.

3.7. Подсистема memory

Подсистема memory позволяет накладывать ограничения и автоматически создает отчеты об использовании ресурсов памяти задачами контрольной группы.
memory.stat
Возвращает большое число параметров использования памяти, описанных в следующей таблице:
Таблица 3.1. Значения, представленные в файле memory.stat
Значение Описание
cache размер кэша страниц (в байтах), включая tmpfs (shmem)
rss размер кэша анонимной памяти и своппинга (в байтах), не включая tmpfs (shmem)
mapped_file размер файлов, отображенных в память с помощью системного вызова mmap (в байтах), включая tmpfs (shmem
pgpgin число страниц, скаченных в память
pgpgout число страниц, откаченных из памяти
swap размер использованной области своппинга (в байтах)
active_anon размер кэша анонимной памяти и своппинга в активном LRU-списке[a] (в байтах), включая tmpfs (shmem)
inactive_anon размер кэша анонимной памяти и своппинга в неактивном LRU-списке (в байтах), включая tmpfs (shmem)
active_file размер памяти (в байтах), находящейся в активном LRU-списке, для которой имеется копия данных в файлах
inactive_file размер памяти (в байтах), находящейся в неактивном LRU-списке, для которой имеется копия данных в файлах
unevictable размер памяти (в байтах), которая не может быть высвобождена
hierarchical_memory_limit предельный размер памяти (в байтах), который может использоваться в иерархии, куда входит контрольная группа с подсистемой memory
hierarchical_memsw_limit предельный размер памяти и области своппинга (в байтах), который может использоваться в иерархии, куда входит контрольная группа с подсистемой memory
[a] LRU, Least-Recently-Used list — список наименее используемой памяти.

Кроме этого, все параметры за исключением hierarchical_memory_limit и hierarchical_memsw_limit имеют аналоги с префиксом total_, которые возвращают данные не только о самой контрольной группе, но и о всех ее дочерних группах. Например, параметр swap возвращает данные о использовании области своппинга контрольной группой, а параметр total_swap — о суммарном использовании области своппинга контрольной группой и всеми ее дочерними группами.
При интерпретации значений, представленных в файле memory.stat, следует учитывать, что они соотносятся следующим образом:
  • active_anon + inactive_anon = (анонимная память) + (кэш файлов для tmpfs) + (кэш своппинга)
    Следовательно, active_anon + inactive_anonrss, поскольку rss не включает в себя tmpfs.
  • active_file + inactive_file = cache - размер tmpfs
memory.usage_in_bytes
Возвращает суммарный размер памяти (в байтах), занятый процессами контрольной группы.
memory.memsw.usage_in_bytes
Возвращает суммарный размер памяти и области своппинга (в байтах), занятый процессами контрольной группы.
memory.max_usage_in_bytes
Возвращает максимальный размер памяти (в байтах), использованный процессами контрольной группы.
memory.memsw.max_usage_in_bytes
Возвращает максимальный размер памяти и области своппинга (в байтах), использованный процессами контрольной группы.
memory.limit_in_bytes
Устанавливает ограничение на максимальный размер памяти, который может использоваться в режиме пользователя (включая кэш файлов). По умолчанию размер задается в байтах. Для указания более крупных единиц измерения можно использовать суффиксы — k или K для килобайтов, m или M для мегабайтов и g или G для гигабайтов.
Параметр memory.limit_in_bytes нельзя использовать для ограничения корневой контрольной группы. Только группы, стоящие на более низких ступенях иерархии, могут быть ограничены в потреблении ресурсов памяти.
Для отмены ограничений в файл memory.limit_in_bytes следует записать значение -1.
memory.memsw.limit_in_bytes
Устанавливает ограничение на максимальный суммарный размер используемой памяти и области своппинга. По умолчанию размер задается в байтах. Для указания более крупных единиц измерения можно использовать суффиксы — k или K для килобайтов, m или M для мегабайтов и g или G для гигабайтов.
Параметр memory.memsw.limit_in_bytes нельзя использовать для ограничения корневой контрольной группы. Только группы, стоящие на более низких ступенях иерархии, могут быть ограничены в потреблении ресурсов памяти.
Для отмены ограничений в файл memory.memsw.limit_in_bytes следует записать значение -1.

Установка параметров memory.memsw.limit_in_bytes и memory.limit_in_bytes

Важно отметить, что параметр memory.limit_in_bytes должен быть установлен до того, как установлен параметрmemory.memsw.limit_in_bytes. Попытка установить параметры в обратном порядке приведет к ошибке. Это объясняется тем, что параметр memory.memsw.limit_in_bytes становится доступным только после того, как исчерпаны ресурсы памяти, ограниченные параметром memory.limit_in_bytes.
Рассмотрим следующий пример. Установки параметров memory.limit_in_bytes = 2G и memory.memsw.limit_in_bytes = 4G для некоторой контрольной группы позволят процессам этой группы занять 2 ГБ оперативной памяти и, после исчерпания этого предела, занять еще 2 ГБ в области своппинга. Параметр memory.memsw.limit_in_bytes ограничивает суммарный размер оперативной памяти и области своппинга. Потенциально процессы контрольной группы, в которой не установлено значение параметра memory.memsw.limit_in_bytes, могут занять всю имеющуюся область своппинга (после исчерпания лимита на оперативную память) и вызвать аварийную ситуацию нехватки памяти из-за отсутствия свободного пространства в области своппинга.
Порядок, в котором устанавливаются значения параметров memory.limit_in_bytes и memory.memsw.limit_in_bytes в файле /etc/cgconfig.conf, тоже важен. Ниже приведен пример правильной конфигурации:
memory {
    memory.limit_in_bytes = 1G;
    memory.memsw.limit_in_bytes = 1G;
}
memory.failcnt
Счетчик случаев достижения предела потребления ресурсов памяти, установленного параметром memory.limit_in_bytes.
memory.memsw.failcnt
Счетчик случаев достижения предела суммарного потребления ресурсов памяти и своппинга, установленного параметром memory.memsw.limit_in_bytes.
memory.force_empty
При установке параметра в 0 освобождает память от всех страниц, использованных задачами контрольной группы. Этот интерфейс может использоваться только тогда, когда в контрольной группе нет задач. Если память не может быть освобождена, то по возможности она перемещается в родительскую контрольную группу. Перед удалением контрольной группы рекомендуется использовать параметр memory.force_empty, чтобы избежать перемещения в родительскую контрольную группу неиспользуемых страниц кэша памяти.
memory.swappiness
Устанавливает коэффициент, используемый ядром системы для определения предпочтения своппинга памяти процессов, входящих в контрольную группу, перед высвобождением памяти из кэша страничной памяти. Этот параметр для контрольной группы работает точно так же, как параметр, установленный в файле /proc/sys/vm/swappiness для всей системыю. По умолчанию значение равно 60. Значения меньше 60 уменьшают тенденцию ядра откачивать память процессов в своппинг, значения больше 60 увеличивают тенденцию своппинга, а значения больше 100 разрешают ядру откачивать в своппинг страницы памяти, входящие в адресное пространство процессов, принадлежащих данной контрольной группе.
Отметим, что значение 0 не предоствращает откачку страниц памяти процессов в своппинг. Откачка может произойти при недостатке системной памяти, так как глобальная логика управления виртуальной памятью не учитывает контрольные группы. Чтобы полностью запретить откачку страниц, вместо механизма контрольных групп рекомендуется использовать сисменый вызов mlock().
Нельзя менять параметр memory.swappiness для следующих групп:
  • для корневой контрольной группы, которая использует значение из файла /proc/sys/vm/swappiness;
  • для контрольной группы, у которой есть дочернии группы.
memory.use_hierarchy
Содержит флаг (значение 0 или 1), определяющий должен ли производиться сквозной учет потребления ресурсов памяти в иерархии контрольных групп. Если учет разрешен (значение 1), то подсистема memory высвобождает память дочерних процессов при превышении родительским процессом установленных пределов потребления памяти. По умолчанию (значение 0) высвобождение памяти в дочерних задачах не производится.

3.8. Подсистема net_cls

Подсистема net_cls присваивает сетевым пакетам идентификатор класса (classid), который позволяет контроллеру трафика tc отличать пакеты, поступающие из заданной контрольной группы. Контроллер трафика может быть настроен так, чтобы назначать разные приоритеты пакетам из разных контрольных групп.
net_cls.classid
Псевдофайл net_cls.classid содержит число, идентифицирующее обработчик трафика. При чтении из файла net_cls.classid значение classid представляется в десятичном формате, в то время как при записи нужно использовать шестнадцатиричный формат. Например, число 0x100001 представляет собой идентификатор обработчика, который в формате пакета iproute2 обычно записывается как 10:1. При чтении из файла net_cls.classid это значение будет представлено как число 1048577.
Формат идентификатора обработчика трафика следующий: 0xAAAABBBB, где AAAA — старший номер в шестнадцатиричной системе, а BBBB — младший номер. Нули в начале можно опускать. Число 0x10001 — это тоже, что 0x00010001, и представляет собой идентификатор обработчика 1:1. Ниже приведен пример установки обработчика 10:1 в файл net_cls.classid:
~]# echo 0x100001 > /cgroup/net_cls/red/net_cls.classid
~]# cat /cgroup/net_cls/red/net_cls.classid
1048577
Справочная страница tc содержит информацию о том, как настроить контроллер трафика для использования идентификаторов обработчиков, присваиваемых сетевым пакетам подсистемой net_cls.

3.9. Подсистема net_prio

Подсистема net_prio позволяет для каждого сетевого интерфейса динамически назначать приоритет трафика, исходящего из приложений контрольной группы. Сетевой приоритет — это число, которое используется внутри системы и сетевыми устройствами. Сетевой приоритет позволяет поразному обрабатывать пакеты при их отсылке, постановке в очередь и отбрасывании. Сетевой приоритет может быть установлен командой tc, но это выходит за пределы данного руководства (см. справочные страницы по команде tc).
Обычно приложения устанавливают приоритет своего трафика с помощью опции сокета SO_PRIORITY. Однако очень часто в приложениях не предусмотрена возможность установки приоритета, или же приоритет трафика зависит от окружающей среды, где используется приложение, и не может быть определен заранее.
Используя подсистему net_prio, администратор может поместить процесс в контрольную группу, которая определяет приоритет исходящего трафика для заданного сетевого интерфейса.

Замечание

Чтобы использовать подсистему net_prio, ядро операционной системы должно быть собрано со следующей опцией:
~]$ grep CONFIG_NETPRIO_CGROUP /boot/config-`uname -r`
CONFIG_NETPRIO_CGROUP=m
Модуль netprio_cgroup должен быть загружен. Это можно сделать так:
~]# modprobe netprio_cgroup
Чтобы убедиться, что модуль netprio_cgroup загружен, выполните следующую команду:
~]$ lsmod | grep netprio_cgroup
Как только разрешена работа подсистемы net_prio, это становится видно в списке из файла /proc/cgroups.
net_prio.prioidx
Файл доступный только на чтение, в котором содержится число, используемое ядром для внутреннего представления данной контрольной группы.
net_prio.ifpriomap
Содержит карту приоритетов, назначенных исходящему трафику, порождаемому процессами данной контрольной группы, и покидающему систему через перечисленные сетевые интерфейсы. Эта карта представляет собой список пар: <сетевой_интерфейс> <приоритет>:
~]# cat /cgroups/net_prio/iscsi/net_prio.ifpriomap
eth0 5
eth1 4
eth2 6
Содержимое файла net_prio.ifpriomap можно менять с помощью команды echo. Например:
~]# echo "eth0 5" > /cgroups/net_prio/iscsi/net_prio.ifpriomap
Приведенная выше команда назначает приоритет 5 сетевому трафику, исходящему от процессов контрольной группы iscsi в иерархии net_prio и передаваемому через сетевой интерфейс eth0. Родительская контрольная группа также имеет доступный для записи файл net_prio.ifpriomap, который можно использовать для установки приоритета по умолчанию.

3.10. Подсистема ns

Подсистема ns предоставляет возможность группировать процессы в отдельные пространства имен. Процессы могут взаимодействовать друг с другом внутри пространства имен, но они изолированы от процессов, работающих в других пространствах имен. В тех случаях, когда пространства имен используются для реализации виртуализации на уровне операционной системы, они называются контейнерами.

3.11. Дополнительные ресурсы

Документация по подсистемам ядра
Перечисленные ниже файлы располагаются в каталоге /usr/share/doc/kernel-doc-<версия_ядра>/Documentation/cgroups/ (доступном после установки пакета kernel-doc).
  • Подсистема blkioblkio-controller.txt
  • Подсистема cpuacctcpuacct.txt
  • Подсистема cpusetcpusets.txt
  • Подсистема devicesdevices.txt
  • Подсистема freezerfreezer-subsystem.txt
  • Подсистема memorymemory.txt
  • Подсистема net_prionet_prio.txt


[5] CFQ, Completely Fair Queuing — полностью справедливая процедура постановки в очередь.

Глава 4. Примеры использования

В этой главе приведены примеры использования возможностей контрольных групп.

4.1. Приоритизация ввода-вывода базы данных

Распределение ресурсов между базами данных с учетом их приоритета можно осуществить путем запуска каждого сервера баз данных в своей собственной виртуальной машине. Рассмотрим следующий пример. На системе работают две базы данных, каждая в своей вируальной машине KVM. Одна база данных имеет высокий приоритет, а другая низкий. Когда оба сервера баз данных работают одновременно, то у каждого из них падает скорость ввода-вывода, так как они поровну делят общую пропускную способность машины. Рисунок 4.1, «Скорость ввода-вывода без явного распределения ресурсов» иллюстрирует этот случай — как только начинает работать сервер низкоприоритетной базы данных (в момент времени около 45), скорость ввода-вывода у обеих баз данных становится примерно одинаковой.
Скорость ввода-вывода без явного распределения ресурсов
Скорость ввода-вывода падает, когда запускается вторая база данных.
Рисунок 4.1. Скорость ввода-вывода без явного распределения ресурсов

Чтобы обеспечить приоритет более важной базы данных, она может быть включена в контрольную группу с большим числом зарезервированных операций ввода-вывода, а низкоприоритетная база данных — в контрольную группу с небольшим числом зарезервированных операций. Приведенная ниже последовательность шагов показывает, как это можно сделать. Она должна быть выполнена на хост-системе.
Процедура 4.1. Приоритизация ввода-вывода
  1. Подключите подсистему blkio к контрольной группе /cgroup/blkio/:
    ~]# mkdir /cgroup/blkio
    ~]# mount -t cgroup -o blkio blkio /cgroup/blkio 
    
  2. Создайте контрольные группы для задач с высоким и низким приоритетом:
    ~]# mkdir /cgroup/blkio/high_prio
    ~]# mkdir /cgroup/blkio/low_prio
    
  3. Получите идентификаторы процессов виртуальных машин, в которых работают базы данных, и поместите их в соответствующие контрольные группы. В данном примере VM_high представляет собой имя виртуальной машины с высокоприоритетной базой данных, а VM_low — имя виртуальной машины с низкоприоритетной базой данных. Например:
    ~]# ps -eLf | grep qemu | grep VM_high | awk '{print $4}' | while read pid; do echo $pid >> /cgroups/blkio/high_prio/tasks; done
    ~]# ps -eLf | grep qemu | grep VM_low | awk '{print $4}' | while read pid; do echo $pid >> /cgroups/blkio/low_prio/tasks; done
    
  4. Установите соотношение 10:1 между контрольными группами high_prio и low_prio. Процессы в этих группах (то есть процессы, соответствующие виртуальным машинам, которые были добавлены в контрольные группы на предыдущем шаге) сразу начнут использовать только отведенные им ресурсы.
    ~]# echo 1000 > /cgroup/blkio/high_prio/blkio.weight
    ~]# echo 100 > /cgroup/blkio/low_prio/blkio.weight
    
    В нашем примере контрольная группа low_prio разрешает низкоприоритетной базе данных использовать только около 10% операций ввода-вывода, в то время как контрольная группа high_prio разрешает высокоприоритетной базе данных использовать до 90% операций ввода-вывода.
Рисунок 4.2, «Скорость ввода-вывода при явном распределении ресурсов» иллюстрирует результат ограничения низкоприоритетной базы данных и приоритизации более важной базы данных. Как только серверы баз данных помещены в соответствующие контрольные группы (в момент времени около 75), пропускная способность ввода-вывода делится между серверами в соотношении 10:1.
Скорость ввода-вывода при явном распределении ресурсов
Высокоприоритетная база данных вновь имеет высокую скорость ввода-вывода.
Рисунок 4.2. Скорость ввода-вывода при явном распределении ресурсов

Потребление ресурсов низкоприоритетной базой данных может быть ограничено другим способом — путем торможения ввода-вывода на блочное устройство. Этот способ позволяет установить предельное число операций чтения и записи в единицу времени доступное базе данных. Подробная информация по подсистеме blkio представлена в Раздел 3.1, «Подсистема blkio».

4.2. Распределение вычислительных ресурсов и памяти между группами

Когда одна система совместно используется многими пользователями, бывает полезно иметь возможность веделять некоторым пользователям больше ресурсов, чем другим. Рассмотрим следующий пример: в гипотетической компании есть три подразделения — финансовый отдел, отдел продаж и инженерный отдел. Если во всех подразделениях выполняются задачи, требующие больших вычислительных ресурсов и много памяти, то поскольку инженеры используют систему и ее ресурсы для большего числа задач, чем специалисты других подразделений, было бы логично выделить им больше ресурсов.
Механизм контрольных групп предоставляет возможность ограничивать потребление ресурсов каждой группой пользователей. Предположим, что в системе заведены следующие пользователи:
~]$ grep home /etc/passwd
martin:x:1000:1000::/home/martin:/bin/bash
john:x:1001:1001::/home/john:/bin/bash
mark:x:1002:1002::/home/mark:/bin/bash
peter:x:1003:1003::/home/peter:/bin/bash
jenn:x:1004:1004::/home/jenn:/bin/bash
mike:x:1005:1005::/home/mike:/bin/bash
Эти пользователи были включены в следующие группы:
~]$ grep -e "100[678]" /etc/group
finance:x:1006:jenn,john
sales:x:1007:mark,martin
engineering:x:1008:peter,mike
Для того, чтобы этот пример правильно работал, в системе должен быть установлен пакет libcgroup-tools. Используя файлы /etc/cgconfig.conf и /etc/cgrules.conf, можно определить иерархию и набор правил, ограничивающих выделение ресурсов каждому пользователю (см. Процедура 4.2, «Распределение вычислительных ресурсов и памяти между группами пользователей»).
Процедура 4.2. Распределение вычислительных ресурсов и памяти между группами пользователей
  1. Определим конфигурацию подсистем и контрольных групп в файле /etc/cgconfig.conf следующим образом:
    mount {
        cpu     = /cgroup/cpu_and_mem;
        cpuacct = /cgroup/cpu_and_mem;
        memory  = /cgroup/cpu_and_mem;
    }
    
    group finance {
            cpu {
                    cpu.shares="250";
            }
            cpuacct {
                    cpuacct.usage="0";
            }
            memory {
                    memory.limit_in_bytes="2G";
                    memory.memsw.limit_in_bytes="3G";
            }
    }
    
    group sales {
            cpu {
                    cpu.shares="250";
            }
            cpuacct {
                    cpuacct.usage="0";
            }
            memory {
                    memory.limit_in_bytes="4G";
                    memory.memsw.limit_in_bytes="6G";
            }
    }
    
    group engineering {
            cpu {
                    cpu.shares="500";
            }
            cpuacct {
                    cpuacct.usage="0";
            }
            memory {
                    memory.limit_in_bytes="8G";
                    memory.memsw.limit_in_bytes="16G";
            }
    }
    
    Загрузка с данным конфигурационным файлом приводит к подключению подсистем cpu, cpuacct и memory к одной контрольной группе — cpu_and_mem (см. Глава 3, Подсистемы и параметры настройки). Затем в cpu_and_mem создается иерархия, состоящая из трех контрольных групп: sales, finance и engineering. В каждой из этих групп устанавливаются свои параметры подсистем:
    • cpu — параметр cpu.shares определяет долю вычислительных ресурсов доступных процессам в каждой из контрольных групп. Установка значений параметра как 250, 250 и 500 для контрольных групп finance, sales и engineering означает, что процессы, запущенные в этих группах, могут потреблять вычислительные ресурсы в соотношении 1:1:2. Отметим, что когда в системе готов к работе только один процесс, то он потребляет столько вычислительных ресурсов, сколько ему требуется, вне зависимости от того, к какой контрольной группе он относится. Ограничения на потребление вычислительных ресурсов вступают в силу только тогда, когда несколько процессов конкурируют за ресурсы процессоров.
    • cpuacct — параметр cpuacct.usage="0" сбрасывает значения в файлах cpuacct.usage и cpuacct.usage_percpu. В них представлено процессорное время (в наносекундах), использованное процессами контрольной группы.
    • memory — параметр memory.limit_in_bytes задает ограничение на общий размер оперативной памяти доступной процессам, входящим в одну контрольную группу. В данном случае процессам, запущенным в группе finance, доступно 2 ГБ, процессам в sales — 4 ГБ, а процессам в engineering — 8 ГБ. Параметр memory.memsw.limit_in_bytes определяет общий размер оперативной памяти и области своппинга, который процессам разрешено использовать. Если какой-то процесс в контрольной группе finance достигнет 2 ГБ предел оперативной памяти, ему будет разрешено использовать еще 1 ГБ в области своппинга, то есть до общего установленного предела в 3 ГБ.
  2. Для определения правил, используемых демоном cgrulesengd при перераспределении процессов по контрольным группам, в файле /etc/cgrules.conf нужно указать следующее:
    #<user/group>         <controller(s)>         <cgroup>
    @finance              cpu,cpuacct,memory      finance
    @sales                cpu,cpuacct,memory      sales
    @engineering          cpu,cpuacct,memory      engineering
    
    Такая конфигурация создает правила, назначающие системной группе (например, @finance) контроллеры ресурсов, которые она может использовать (cpu, cpuacct, memory), и контрольную группу (finance), куда будут помещаться все процессы, запущенные пользователями, входящими в данную системную группу.
    В нашем примере, когда демон cgrulesengd, запускаемый командой service cgred start, находит процесс пользователя, входящего в системную группу finance (например, процесс пользователя jenn), идентификатор этого процесса автоматически записывается в файл /cgroup/cpu_and_mem/finance/tasks, и процесс подвергается ограничениям, установленным для контрольной группы finance.
  3. Для создания иерархии котрольных групп и установки их параметров запустите службу cgconfig:
    ~]# service cgconfig start
    Starting cgconfig service:                                 [  OK  ]
    
    Запустите службу cgred, чтобы демон cgrulesengd начал определять процессы, принадлежащие пользователями системных групп, сконфигурированных в файле /etc/cgrules.conf:
    ~]# service cgred start
    Starting CGroup Rules Engine Daemon:                       [  OK  ]
    
    Отметим, что служба, которая запускает демон cgrulesengd, называется cgred.
  4. Для того, чтобы приведенная выше конфигурация действовала после перезагрузки, нужно разрешить запуск служб cgconfig и cgred по умолчанию:
    ~]# chkconfig cgconfig on
    ~]# chkconfig cgred on
    
Чтобы проверить данную конфигурацию, нужно запустить процессы, интенсивно потребляющие вычислительные ресурсы или ресурсы оперативной памяти, и пронаблюдать результат, например, с помощью программы top. Для проверки управления вычислительными ресурсами из под каждого пользователя запустите команду dd следующим образом:
~]$ dd if=/dev/zero of=/dev/null bs=1024k
Эта команда читает из файла /dev/zero и пишет в файл /dev/null блоками по 1024 КБ. Программа top покажет примерно следующее:
 PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
8201 peter     20   0  103m 1676  556 R 24.9  0.2   0:04.18 dd
8202 mike      20   0  103m 1672  556 R 24.9  0.2   0:03.47 dd
8199 jenn      20   0  103m 1676  556 R 12.6  0.2   0:02.87 dd
8200 john      20   0  103m 1676  556 R 12.6  0.2   0:02.20 dd
8197 martin    20   0  103m 1672  556 R 12.6  0.2   0:05.56 dd
8198 mark      20   0  103m 1672  556 R 12.3  0.2   0:04.28 dd
⋮
Все процессы правильно размещены по контрольным группам и потребляют вычислительные ресурсы только в отведенных им пределах. Если остановить все процессы за исключением двух, принадлежащих группам finance и engineering, то освободившиеся ресурсы пропорционально распределяются между ними:
 PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
8202 mike      20   0  103m 1676  556 R 66.4  0.2   0:06.35 dd
8200 john      20   0  103m 1672  556 R 33.2  0.2   0:05.08 dd
⋮

Альтернативный способ

Поскольку демон cgrulesengd перемещает процесс в контрольную группу только после того, как выполнились условия, определенные правилами в файле /etc/cgrules.conf, в течение нескольких миллисекунд процесс может выполняться вне назначенной ему контрольной группы. Альтернативный способ перемещения процессов в контрольные группы связан с использованием PAM-модуля pam_cgroup.so. Этот модуль перемещает процессы в имеющиеся контрольные группы в соответствии с правилами, определенными в файле /etc/cgrules.conf. Последовательность шагов для конфигурации PAM-модуля pam_cgroup.so описана в Процедура 4.3, «Использование PAM-модуля для перемещения процессов в контрольные группы».
Процедура 4.3. Использование PAM-модуля для перемещения процессов в контрольные группы
  1. Установите пакет libcgroup-pam:
    ~]# yum install libcgroup-pam
    
  2. Убедитесь, что PAM-модуль установлен и доступен:
    ~]# ls /lib64/security/pam_cgroup.so
    /lib64/security/pam_cgroup.so
    
    Отметим, что на 32-битных системах этот модуль расположен в каталоге /lib/security/.
  3. Добавьте следующую строку в файл /etc/pam.d/su, чтобы модуль pam_cgroup.so использовался каждый раз, когда выполняется команда su:
    session         optional        pam_cgroup.so
    
  4. Создайте файлы /etc/cgconfig.conf и /etc/cgrules.conf так же, как и раньше (см. Процедура 4.2, «Распределение вычислительных ресурсов и памяти между группами пользователей»).
  5. Чтобы задействовать данную конфигурацию, все пользователи, которых касаются установки контрольных групп в файле /etc/cgrules.conf, должны выйти из системы.
При использовании PAM-модуля pam_cgroup.so служба cgred может быть отключена.

История изменений

История переиздания
Издание 1.0-8Fri May 25 2012Martin Prpič
Выпуск Руководства по управлению ресурсами в рамках Fedora 17.
Издание 1.0-7Fri Dec 23 2011Jaromír Hradílek
Выпуск Руководства по управлению ресурсами в рамках Fedora 16.
Издание 1.0-6Tue Dec 6 2011Martin Prpič
Выпуск Руководства по управлению ресурсами в рамках Red Hat Enterprise Linux 6.2 GA.
Издание 1.0-5Thu May 19 2011Martin Prpič
Выпуск Руководства по управлению ресурсами в рамках Red Hat Enterprise Linux 6.1 GA.
Издание 1.0-4Tue Mar 1 2011Martin Prpič
Исправления в соответствии с BZ#667623, BZ#667676, BZ#667699.
Уточнено описание команды cgclear: BZ#577101.
Уточнено описание команды lssubsystem: BZ#678517.
Блокирование процесса: BZ#677548.
Издание 1.0-3Wed Nov 17 2010Rüdiger Landmann
Откорректирован пример mount: BZ#612805.
Издание 1.0-2Thu Nov 11 2010Rüdiger Landmann
Удалены инструкции по отправлению отзывов для предыдущей версии.
Издание 1.0-1Wed Nov 10 2010Rüdiger Landmann
Контроль качества: BZ#581702 и BZ#612805.
Издание 1.0-0Tue Nov 9 2010Rüdiger Landmann
Полная версия для главного выпуска.