Контроль ресурсов [332.3]

Рейтинг: 64.6% · 12 голосов
Специализация LPIC-3 303 (v3.0): криптография и PKI/X.509, шифрование ФС (LUKS/TPM2/Clevis), DNSSEC, hardening хоста, IDS, контроль доступа (SELinux/AppArmor), сетевая безопасность, nftables, VPN, пентест.
Ответить
Аватара пользователя
Sergey_Sysadmin
Сообщения: 134
Зарегистрирован: 11 май 2026, 05:31

Контроль ресурсов [332.3]

Сообщение Sergey_Sysadmin »

Оглавление курса (16)
  1. Введение в LPIC-3 303: безопасность Linux
  2. X.509 и инфраструктура открытых ключей [331.1]
  3. X.509 для шифрования, подписи и аутентификации [331.2]
  4. Шифрование файловых систем [331.3]
  5. DNS и криптография [331.4]
  6. Усиление защиты хоста [332.1]
  7. Урок 6. Обнаружение вторжений на хосте: AIDE, auditd, сканеры руткитов и OpenSCAP
  8. Контроль ресурсов [332.3] (вы здесь)
  9. Дискреционный контроль доступа: ACL и атрибуты [333.1]
  10. Мандатный контроль доступа: SELinux и AppArmor [333.2]
  11. Усиление сетевой защиты [334.1]
  12. Сетевое обнаружение вторжений
  13. Фильтрация пакетов [334.3]
  14. Виртуальные частные сети (VPN) [334.4]
  15. Уязвимости и угрозы [335.1]
  16. Основы тестирования на проникновение [335.2]
Урок 7. Контроль ресурсов [332.3]

Любой процесс на машине - потенциальный источник отказа в обслуживании. Утёкшая память, форк-бомба, скрипт в бесконечном цикле, прожорливый сборщик мусора - и хост перестаёт отвечать, OOM-killer начинает убивать не тех, кого вы хотели, а SSH-сессия зависает в самый неподходящий момент. В этом уроке мы разберём, как заранее очертить каждому сервису его клетку по CPU, памяти, числу процессов и операциям ввода-вывода. Инструменты: cgroups v2 как фундамент, директивы ресурсов systemd как удобный фасад над cgroups, и старая добрая пара ulimit плюс limits.conf для лимитов на уровне сессии PAM.

Изображение

Как это работает

В современном ядре все ограничения ресурсов сводятся к cgroups version 2 - единой иерархии в /sys/fs/cgroup. В отличие от первой версии с её россыпью раздельных иерархий, в v2 есть одно дерево, и каждый контроллер (cpu, memory, io, pids) включается для поддерева через файл cgroup.subtree_control. Процесс всегда принадлежит ровно одной cgroup, а лимиты наследуются вниз по дереву. На июнь 2026 во всех живых дистрибутивах (Debian 13, Ubuntu 24.04 LTS, RHEL 10, Fedora 41+) по умолчанию работает именно unified-иерархия cgroup v2, а cgroup v1 считается легаси.

systemd - это менеджер cgroups номер один в системе. Каждый юнит он помещает в свою cgroup-ветку (system.slice, user.slice и так далее), поэтому управлять ресурсами проще через директивы юнита, чем руками писать в файлы cgroupfs. Директива MemoryMax ставит жёсткий потолок памяти (превышение ведёт к OOM внутри cgroup), MemoryHigh - мягкий порог, при котором ядро начинает агрессивно отжимать страницы и притормаживать процесс, не убивая его. CPUQuota ограничивает процессорное время (200% значит два полных ядра), TasksMax режет число задач - именно это спасает от форк-бомб. IOWeight и IOReadBandwidthMax управляют дисковым вводом-выводом.

ulimit и /etc/security/limits.conf - это другой, более старый слой. Он опирается на rlimits ядра (системный вызов setrlimit) и применяется через PAM-модуль pam_limits при входе пользователя. Лимиты тут на процесс или на пользователя, а не на cgroup: nproc - максимум процессов пользователя, nofile - дескрипторов на процесс, fsize - размер файла. Это работает только для интерактивных и PAM-сессий, поэтому для системных сервисов всегда предпочитайте директивы systemd - они точнее и применяются гарантированно.

Команды и примеры

Посмотреть, какая версия cgroup активна, и текущее потребление юнита:

Код: Выделить всё

stat -fc %T /sys/fs/cgroup     # cgroup2fs = unified v2
systemctl status nginx.service # внизу строка CGroup и Memory/Tasks
systemd-cgtop                  # top по cgroup: CPU, память, IO
systemd-cgls                   # дерево cgroup как ls
Задать лимиты сервису без правки файла на лету (сохранится в drop-in):

Код: Выделить всё

systemctl set-property nginx.service MemoryMax=512M CPUQuota=150% TasksMax=200
systemctl show nginx.service -p MemoryMax -p CPUQuota -p TasksMax
Постоянная настройка через drop-in - одинаково в Debian/Ubuntu и RHEL/Fedora:

Код: Выделить всё

systemctl edit nginx.service
# в открывшийся override.conf пишем:
[Service]
MemoryMax=512M
MemoryHigh=400M
CPUQuota=150%
CPUWeight=50
TasksMax=200
IOWeight=80

systemctl daemon-reload
systemctl restart nginx.service
Временно запустить любую команду в ограниченной transient-cgroup:

Код: Выделить всё

systemd-run --scope -p MemoryMax=200M -p TasksMax=50 ./suspicious_script.sh
Лимиты сессии. Проверка и временная установка через ulimit (флаг -S мягкий, -H жёсткий):

Код: Выделить всё

ulimit -a            # все лимиты текущей сессии
ulimit -u            # nproc: число процессов
ulimit -n 8192       # поднять nofile в этой сессии
Постоянно - через /etc/security/limits.conf или drop-in в /etc/security/limits.d/:

Код: Выделить всё

# /etc/security/limits.d/90-app.conf
# домен  тип    элемент  значение
appuser  hard   nproc    1024
appuser  soft   nproc    512
appuser  hard   nofile   65536
@devs    hard   fsize    1048576
Убедитесь, что pam_limits подключён. В Debian/Ubuntu смотрите /etc/pam.d/common-session, в RHEL/Fedora - /etc/pam.d/system-auth и password-auth. Строка должна присутствовать:

Код: Выделить всё

session  required  pam_limits.so
Для systemd-сервисов rlimits задаются прямо в юните и не зависят от PAM:

Код: Выделить всё

[Service]
LimitNOFILE=65536
LimitNPROC=1024
Частые грабли
  • limits.conf не действует на systemd-сервисы. PAM тут вообще не участвует - пишите LimitNOFILE/LimitNPROC в юните.
  • Лимит nproc в limits.conf считается на всего пользователя по всем сессиям, а не на процесс. Поставите 50 - и пятидесятая ssh-сессия того же юзера не залогинится.
  • Путаница soft и hard. soft - текущее значение, его можно поднять до hard без рута. hard - потолок, выше которого не прыгнуть без привилегий.
  • root по умолчанию игнорирует многие лимиты nproc, поэтому форк-бомба из-под root уложит систему даже при выставленном limits.conf. Спасает только TasksMax на уровне slice/cgroup.
  • MemoryLimit устарел - это директива cgroup v1. В v2 используйте MemoryMax и MemoryHigh.
  • CPUQuota без понимания процентов: 100% это одно ядро. На 8-ядерной машине 100% сильно недозагрузит сервис.
  • Чтобы контроллер cpu или io работал на listed-юните, он должен быть делегирован выше по дереву. Если ограничение тихо игнорируется - проверьте cgroup.controllers и subtree_control родителя.
Мини-лаба
  • Проверьте версию cgroup: stat -fc %T /sys/fs/cgroup. Убедитесь, что это cgroup2fs.
  • Создайте простой сервис-нагрузку (например, юнит, запускающий stress-ng или цикл на bash) и запустите его.
  • Через systemctl set-property ограничьте его MemoryMax=100M и TasksMax=20. Перезапустите и посмотрите systemd-cgtop.
  • Запустите внутри ограниченной cgroup форк-бомбу через systemd-run --scope -p TasksMax=20 и убедитесь, что хост остался жив, а размножение упёрлось в лимит.
  • Создайте /etc/security/limits.d/99-lab.conf с hard nproc для тестового пользователя, перелогиньтесь под ним и проверьте ulimit -u.
  • Сравните: попробуйте форк-бомбу из-под этого юзера (с лимитом) и убедитесь, что cgroup-лимит надёжнее, чем PAM-лимит.
  • Уберите лимиты (systemctl revert), верните стенд в исходное состояние.
Контрольные вопросы
  • Чем отличается MemoryHigh от MemoryMax и какое поведение ядра стоит за каждым?
  • Почему форк-бомба из-под root может пройти limits.conf, и какой механизм её всё же остановит?
  • Что означает CPUQuota=250% на машине с четырьмя ядрами?
  • В каких случаях лимиты из /etc/security/limits.conf не применяются и почему?
  • Чем cgroup v2 принципиально отличается от v1 в части иерархии и делегирования контроллеров?
  • Как одной командой запустить произвольный процесс в ограниченной по памяти и числу задач временной cgroup?
👍3 ❤️ 🔥1 😄 🤔1
Аватара пользователя
quantumpenguin
Сообщения: 1
Зарегистрирован: 14 май 2026, 20:57

Re: Контроль ресурсов [332.3]

Сообщение quantumpenguin »

А если MemoryHigh выставлен ниже MemoryMax, процесс сначала тормозит на High, а до Max вообще не дойдет? Или это два независимых триггера?
👍1 ❤️ 🔥 😄 🤔
Аватара пользователя
gama
Сообщения: 1
Зарегистрирован: 24 май 2026, 23:43

Re: Контроль ресурсов [332.3]

Сообщение gama »

Проверил на стенде: TasksMax=20 в systemd-run реально гасит форк-бомбу, а вот limits.conf под обычным юзером уперся в nproc только после того как сессия уже подвисла. cgroup явно надежнее.
👍2 ❤️1 🔥1 😄 🤔
Ответить
← Предыдущая глава
Урок 6. Обнаружение вторжений на хосте: AIDE, auditd, сканеры руткитов и OpenSCAP
Следующая глава →
Дискреционный контроль доступа: ACL и атрибуты [333.1]

Все главы курса «LPIC-3 303: безопасность Linux»

Поделиться темой: ✈ Telegram VK

Вернуться в «LPIC-3 303: безопасность Linux»

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и 1 гость