Ограничение ресурсов в systemd: какой способ выбрать
CPUQuota, MemoryMax и TasksMax помогают ограничить аппетиты сервиса, но действуют по-разному. Сравниваем лимиты для отдельной службы, относительный приоритет CPU, временные задания и общие ограничения через slice — с конфигурациями для systemd 252 и новее.

Если один сервис забирает всю память, а разовое задание мешает основному приложению, универсальный лимит не решит обе проблемы. В systemd можно задать жёсткий потолок, распределить CPU между соседями или ограничить целую группу служб. Ниже — четыре подхода и критерии выбора. Примеры рассчитаны на systemd 252 и новее; доступность отдельных контроллеров зависит также от ядра и настроек cgroup.
Сначала решите, что именно ограничивать
Попытка исправить перегрузку одним параметром часто приводит к неприятному сюрпризу: процесс действительно перестаёт расходовать ресурс, но вместе с этим начинает тормозить, перезапускаться или не запускать новые потоки. Поэтому сначала разделите три задачи:
- Потолок потребления. Сервис не должен перейти заданную границу по памяти или CPU.
- Приоритет при конкуренции. Когда CPU не хватает всем, одной службе нужно отдавать его чаще другой.
- Общий бюджет. Несколько служб должны вместе оставаться в пределах заданной памяти или CPU.
cgroup* — группа процессов, для которой ядро Linux учитывает и регулирует потребление ресурсов. systemd помещает службы и задания в такие группы и настраивает доступные ограничения.
Четыре способа задать ограничения
1. Жёсткие лимиты для одной постоянной службы
Используйте drop-in, если нужно постоянно ограничивать конкретный сервис, например myapp.service. Команда откроет редактор конфигурации:
sudo systemctl edit myapp.serviceДобавьте настройки:
[Service]
MemoryHigh=700M
MemoryMax=1G
CPUQuota=150%
TasksMax=256MemoryHigh — граница, после которой ядро сильнее давит на потребление памяти и может замедлить процессы. MemoryMax — жёсткий предел: при его достижении служба может столкнуться с нехваткой памяти и завершением процессов механизмом OOM. CPUQuota=150% ограничивает службу примерно полутора ядрами вычислительного времени; это не обещание, что она всегда получит столько CPU. TasksMax считает задачи, включая потоки, а не только процессы.
После сохранения проверьте конфигурацию и перезапустите службу:
sudo systemctl daemon-reload
sudo systemctl restart myapp.serviceУбедитесь, что параметры загружены: systemctl show myapp.service -p MemoryHigh -p MemoryMax -p CPUQuotaPerSecUSec -p TasksMax -p ControlGroup. Перезапуск может оборвать текущие запросы — применяйте его по правилам обслуживания именно вашего приложения.
2. Относительный приоритет CPU
Если задача не в том, чтобы обрезать CPU, а в том, чтобы важная служба получала больше времени при конкуренции, используйте CPUWeight. Например, значение можно задать в том же drop-in:
[Service]
CPUWeight=200Вес влияет на распределение CPU между конкурирующими группами. Когда простаивающих ресурсов много, служба может использовать доступный процессор полностью; вес не задаёт потолок. Значение 200 не означает 200% CPU и не даёт гарантированной доли при любых обстоятельствах: результат зависит от конкурентов и их настроек. Цена подхода — относительность: добавление или изменение соседней службы может изменить фактическое распределение.
3. Временный лимит для отдельного задания
Для разовой обработки удобнее запустить отдельную transient-службу, не редактируя постоянный unit:
sudo systemd-run --unit=report-job \
--property=MemoryMax=512M \
--property=CPUQuota=50% \
--property=TasksMax=64 \
/usr/local/bin/report-job --oncesystemd создаст службу с именем report-job.service и запустит указанную команду под заданными ограничениями. После старта посмотрите состояние через systemctl status report-job.service. Этот вариант удобен для пакетных задач и ручных запусков. Его цена — настройки относятся к этому запуску: для расписания, повторов и наблюдения за результатом нужно отдельно продумать способ запуска и учёта задания.
4. Общий бюджет для нескольких служб через slice
Если несколько служб должны вместе расходовать не больше заданного объёма, ограничьте родительский slice. Например, создайте /etc/systemd/system/limited.slice:
[Unit]
Description=Resource budget for limited services
[Slice]
MemoryMax=2G
CPUQuota=250%В этом фрагменте опечатка в строке с CPUQuota недопустима, поэтому используйте корректную конфигурацию целиком:
[Unit]
Description=Resource budget for limited services
[Slice]
MemoryMax=2G
CPUQuota=250%
TasksMax=512Затем укажите для каждой нужной службы её slice через drop-in, например:
[Service]
Slice=limited.sliceПеречитайте конфигурацию и перезапустите затронутые службы. Лимит родительской группы относится к их совокупному потреблению: одна служба может оставить меньше ресурсов другой. Это полезно для набора воркеров, но не заменяет индивидуальные лимиты, если один участник группы способен вытеснить остальных.
Сравнение: что выигрываете и чем платите
| Подход | Когда подходит | Цена и риск |
|---|---|---|
| MemoryMax, CPUQuota, TasksMax в drop-in службы | Постоянно ограничить один сервис | Превышение памяти может привести к OOM; жёсткая квота CPU замедлит работу под нагрузкой |
| CPUWeight | Распределять CPU между конкурирующими службами | Не ограничивает максимальное потребление и не гарантирует фиксированную долю |
| systemd-run с параметрами | Разовое или отдельно запускаемое задание | Настройка не становится автоматически постоянной политикой сервиса |
| Лимит родительского slice | Общий бюджет группы служб | Службы конкурируют за общий лимит; один шумный сосед влияет на остальных |
Когда что выбирать
Для сервиса с известным верхним пределом памяти задайтеMemoryMax, а более мягкую границуMemoryHighиспользуйте как сигнал и средство давления до жёсткого потолка.Для CPU выберитеCPUQuota, если нужен именно предел. ВыберитеCPUWeight, если важнее преимущество при конкуренции, но нельзя полностью отнимать свободный процессор.Для разового импорта или отчёта используйтеsystemd-run, чтобы не менять настройки постоянной службы.Для группы воркеров задайте общий бюджет через slice; если важна изоляция каждого участника, добавьте ограничения отдельным службам.
Жёсткий лимит не делает приложение эффективнее. Он переводит неконтролируемое потребление в предсказуемый отказ или замедление — поэтому настраивайте не только потолок, но и реакцию приложения на него.
Что ломается и как проверить настройки
Перед включением жёстких лимитов измерьте обычное и пиковое потребление. Для памяти смотрите не только среднее значение, но и пики во время запуска, прогрева кэша и обработки крупных запросов. Для CPU фиксируйте загрузку и задержки при реальной конкуренции. Без таких замеров число вроде MemoryMax=1G — не оптимизация, а догадка.
После изменений проверьте параметры командой systemctl show, а текущую загрузку групп — через systemd-cgtop. В системе с cgroup v2 файлы группы доступны под /sys/fs/cgroup; путь конкретной группы можно узнать в свойстве ControlGroup. Сверяйте результат с документацией установленной версии systemd: набор доступных настроек зависит от версии менеджера и возможностей ядра.
Служба не стартует. Проверьте журнал черезjournalctl -u myapp.service, синтаксис drop-in и имя unit. Ошибка конфигурации — не повод наугад менять лимиты.Сервис стал медленным после CPUQuota. Квота ограничивает доступное процессорное время. Сравните задержки до и после и проверьте, не подходит ли вместо потолка относительныйCPUWeight.Процессы завершаются при росте памяти. Проверьте сообщения журнала и события нехватки памяти.MemoryMax— аварийная граница, а не гарантия корректного завершения запросов.В slice одна служба мешает другой. Общий лимит ограничивает группу целиком. Настройте индивидуальные ограничения или разделите службы по разным slice.
Не путайте cgroup-лимиты с LimitNOFILE и похожими ограничениями на отдельные ресурсы процесса: это другой механизм. Здесь рассматриваются только управление памятью, CPU и количеством задач через resource control systemd.
Что делать дальше
Начните с одной службы и одного измеримого риска: например, ограничьте пиковую память или защитите основной сервис от пакетной задачи. Снимите показатели до изменения, примените лимит в окно обслуживания и проверьте задержки, перезапуски и сообщения об OOM. Затем решите, нужен ли отдельный потолок, приоритет CPU или общий бюджет slice. Не переносите значения на другие серверы без повторных замеров.
* cgroup — механизм ядра Linux для группировки процессов и контроля их ресурсов.
Универсальный ассистент: Обычный чат: тексты, идеи, разбор, перевод, расчёты.
Спросить за 8 ₽Источники: systemd.resource-control — параметры управления ресурсами, systemd-run — запуск transient-служб и заданий
Частые вопросы
Чем CPUQuota отличается от CPUWeight?
MemoryMax завершит службу, если лимит достигнут?
Как ограничить несколько служб общим лимитом?
Работают ли эти настройки на cgroup v1 и в другой версии systemd?
Можно ли задать лимит разовой задаче, не меняя unit-файл?
Почему после установки лимита приложение стало тормозить?
Материал носит информационный характер и подготовлен редакцией «Агентуры». Он не является офертой, рекламой или индивидуальной консультацией. Упомянутые продукты, компании и торговые знаки принадлежат их правообладателям. Перед принятием решений, влекущих юридические или финансовые последствия, обратитесь к профильному специалисту.