B3. cgroups і OOM killer
Модуль 12 стверджує, що malloc майже ніколи
не повертає NULL, а нестача пам’яті проявляється несподіваним завершенням
процесу. Тут ви відтворите це керовано, у власній контрольній групі
й не ризикуючи системою.
Заразом побачите, що cgroups не є якоюсь «технологією контейнерів», а лишається звичайним механізмом ядра, доступним просто з командного рядка.
-
Розвідка.
Terminal window mount | grep cgroup2cat /sys/fs/cgroup/cgroup.controllerssystemd-cgls | head -20Переконайтеся, що це саме v2 (одна ієрархія), і подивіться, як
systemdуже розклав усі служби по групах. -
Власна група.
Створіть каталог у
/sys/fs/cgroup, увімкніть потрібні контролери в батьківськомуcgroup.subtree_control, помістіть у групу процес, записавши його PID уcgroup.procs.Зверніть увагу на правило внутрішніх вузлів: у v2 процеси можуть лежати лише в листках дерева. Спроба покласти процес у групу, яка має дочірні, дасть помилку — і це не баг.
-
Обмеження процесора.
cpu.maxу форматі «квота період». Запустіть зациклений процес і подивіться вtop, що він отримує рівно задану частку.Порівняйте з
nice:nice— це вага відносно конкурентів,cpu.max— абсолютна квота (модуль 7). Процес ізnice 19на порожній машині займе 100%, процес ізcpu.max 50000 100000— рівно 50%, навіть якщо більше нікого немає. -
Обмеження пам’яті й OOM.
memory.maxна 64 МіБ, потім програма, що виділяє й записує пам’ять по 10 МіБ у циклі. Запис обов’язковий: без нього сторінки фізично не існують (модуль 12).Спостерігайте
memory.current,memory.eventsі журнал ядра. -
Тиск замість убивства.
Тепер те саме, але з
memory.highзамістьmemory.max. Процес не вбивається — його гальмують, змушуючи звільняти пам’ять. Подивіться наmemory.pressureі поясніть різницю у звіті. -
Ввід-вивід.
io.maxна конкретний пристрій, потімddі замір швидкості до й після.
Що треба вміти підтвердити
Section titled “Що треба вміти підтвердити”| Твердження | Чим доводиться |
|---|---|
| Система на cgroups v2 | mount | grep cgroup2 |
| Ваша група існує й містить процес | cat <група>/cgroup.procs |
| Процесор обмежено квотою, а не пріоритетом | cat <група>/cpu.max + top |
| Пам’ять обмежено | cat <група>/memory.max |
| OOM спрацював саме у вашій групі | cat <група>/memory.events (поле oom_kill) |
| Ядро це зафіксувало | journalctl -k --grep 'Out of memory' |
Ви розумієте різницю high і max |
письмове пояснення у звіті |
Часті помилки
Section titled “Часті помилки”Контролери не ввімкнені. Файлів cpu.max і memory.max просто немає,
поки контролер не дозволено в cgroup.subtree_control батьківської групи.
Процес не потрапляє в групу. У cgroup.procs пишеться один PID за раз,
а потоки переносяться через cgroup.threads.
systemd забирає групу назад. Створювати групи руками поруч із деревом
systemd можна, але надійніше робити це через systemd-run --scope.
OOM убив не того. Якщо обмеження стоїть на батьківській групі, жертву обиратимуть серед усіх нащадків. Перевірте, що ви обмежили саме той рівень, який мали на увазі.
Далі, якщо цікаво
Section titled “Далі, якщо цікаво”Обмежити кількість процесів через pids.max і подивитися, що станеться
з форк-бомбою :(){ :|:& };: — вона перестає бути небезпечною.