Короткий ответ
Ограничения задаются напрямую в unit-файле сервиса через директивы MemoryMax, CPUQuota (и аналогичные), которые systemd транслирует в соответствующую cgroup; cgroups v1 использует отдельные независимые иерархии для разных контроллеров (cpu, memory и т.д.), а cgroups v2 — единую унифицированную иерархию для всех контроллеров, что упрощает совместное применение лимитов и обязательно для некоторых современных функций (например, PSI-метрик).
Как это работает подробнее
При запуске сервиса systemd создаёт для него отдельную cgroup и записывает в соответствующие файлы контроллера (memory.max, cpu.max в v2) заданные лимиты; ядро затем физически ограничивает процесс и всех его потомков внутри этой cgroup, не позволяя превысить memory limit (при превышении срабатывает cgroup-level OOM killer) или дольше использовать CPU сверх заданной квоты (происходит throttling).
Пример кода
[Service]
ExecStart=/usr/bin/myapp
MemoryMax=512M
CPUQuota=150%Что использовать на практике
- Практика. лимиты через systemd — простой и декларативный способ избежать ситуации 'шумного соседа', когда один сервис на мультисервисном хосте потребляет все ресурсы и мешает остальным; важно сопоставлять MemoryMax с реальными пиковыми потребностями приложения, иначе сервис будет либо убит cgroup OOM killer, либо постоянно троттлиться по CPU, деградируя по задержкам.
Подводные камни
- Риск. Частая ошибка — задать CPUQuota слишком низким без нагрузочного тестирования и получить постоянный troттлинг с резким ростом задержек под нагрузкой, что в мониторинге часто выглядит как «необъяснимые» скачки времени ответа.