Назад | Перейти на главную страницу

Использование CPUQuota в systemd

Я пытаюсь установить жесткое ограничение на использование ЦП для команды dd. Я создал следующий файл модуля

[Unit]
Description=Virtual Distributed Ethernet

[Service]
ExecStart=/usr/bin/ddcommand
CPUQuota=10%

[Install]
WantedBy=multi-user.target

которые вызывают следующий простой скрипт

#!/bin/sh
dd if=/dev/zero of=/dev/null bs=1024k

Как я видел в этом руководстве, использование ЦП для моего dd обслуживание не должно превышать 10%. Но когда я запускаю system-cgtop команда использование составляет около 70-75%.

Есть идеи, что я делаю не так и как это исправить?

Когда я выполняю systemctl show dd Я получаю следующие результаты относительно процессора

CPUShares=18446744073709551615
StartupCPUShares=18446744073709551615
CPUQuotaPerSecUSec=100ms
LimitCPU=18446744073709551615

Хорошо

Ваше решение правильное и действительно должно быть перспективным; используя systemd для управления настройками cgroup служб, например. CPUQota.

[Unit]
Description=Virtual Distributed Ethernet

[Service]
ExecStart=/usr/bin/ddcommand
CPUQuota=10%

[Install]
WantedBy=multi-user.target

Увидеть man systemd.resource-control для получения более полезных настроек cgroup в systemd.

Плохо

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

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

В CPUQuota настройка доступна только с systemd 213, см. https://github.com/systemd/systemd/blob/master/NEWS

    * The CFS CPU quota cgroup attribute is now exposed for
      services. The new CPUQuota= switch has been added for this
      which takes a percentage value. Setting this will have the
      result that a service may never get more CPU time than the
      specified percentage, even if the machine is otherwise idle.

Это, например, проблема с Дебиан Джесси который поставляется только с systemd 208. В качестве альтернативы можно настроить cpu.cfs_period_us и cpu.cfs_quota_us вручную с помощью cgcreate и cgset из cgroup-bin пакет, например.

sudo cgcreate -g cpu:/cpulimited
sudo cgset -r cpu.cfs_period_us=50000 cpulimited
sudo cgset -r cpu.cfs_quota_us=10000 cpulimited
sudo cgexec -g cpu:cpulimited /usr/bin/ddcommand

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

Для настроек cpu.cfs_period_us и cpu.cfs_quota_us чтобы быть доступным, ядро ​​должно быть скомпилировано с флагом конфигурации CONFIG_CFS_BANDWIDTH. К сожалению, ядро ​​3.16.x для Дебиан Джесси не компилируется с этим флагом по умолчанию, см. это запрос функции.

Это будет доступно в Debian Stretch хотя. Также можно было использовать ядро ​​из Джесси-Backports, у которого должен быть установлен флаг.


Надеюсь, этот ответ поможет нескольким людям с той же проблемой, что и я ...

PS: Простой способ проверить, работает ли квота ЦП в вашей среде:

$ apt-get install stress
$ systemd-run -p CPUQuota=25% --slice=stress -- stress -c <your cpu count>

и смотреть с top или htopнагрузка должна быть распределена (равномерно) по всем процессорам / ядрам, в сумме до 25%.

Альтернатива

В качестве альтернативного инструмента можно использовать cpu-limit, который должен быть доступен в большинстве дистрибутивов, например.

$ apt-get install cpulimit
$ cpulimit -l 10 -P /usr/bin/ddcommand

Работает отправкой SIGSTOP и SIGCONT к прикрепленной команде, чтобы приостановить и возобновить ее работу.

AFAIK было сложно одновременно управлять несколькими отдельными / автономными процессами, например сгруппируйте их вместе, но для этого также может быть решение ...

У меня была аналогичная задача по ограничению использования ЦП, но вариант использования был совершенно другим. Он должен был нагружать набор регрессионных тестов на локальной машине, чтобы имитировать то, что он проходит на загруженном CI-сервере (что вызывает недетерминированное или нестабильное поведение тестов). Это сработало как шарм, в отличие от cpulimit и stress.

systemd-run -p CPUQuota="25%" --scope --uid=$USER --gid=$USER -- pytest ...

--scope заставил его наследовать текущую среду оболочки и вывод команды на стандартный вывод, как обычно. Единственная разница в производительности была Запуск области как единицы run-uN.scope как первая строка.

Для запуска требуются права root, и у меня есть приглашение графического интерфейса от pkttyagent. Вводить пароль каждый раз может быть неудобно, если вам нужно запускать команду несколько раз подряд, например, чтобы настроить CPUQuota, поэтому добавив к указанной выше команде префикса sudo -E env PATH=$PATH упростил бы задачу.

На всякий случай, потому что есть сообщения, что он не работал / не поддерживался в старых версиях.

$ uname -r
4.15.0-51-generic
$ systemd --version | head -n 1
systemd 229