Как настроить ограничение памяти через systemd при срабатывании oom-killer
Что проверяют
Понимаете ли вы, что глобальный OOM-killer выбирает жертву по oom_score и может убить базу вместо виновника утечки, а лимит на cgroup запирает проблему внутри одного сервиса. Следом спрашивают, чем MemoryMax= отличается от MemoryHigh= и как убедиться, что лимит применился.
Как отвечать
На cgroups v2, а это все актуальные дистрибутивы, лимиты задаются в секции [Service] через drop-in: systemctl edit my.service, чтобы не править файл из пакета.
MemoryMax=: жёсткий потолок. При его достижении OOM-killer срабатывает внутри cgroup сервиса, остальная система не страдает. Старое имяMemoryLimit=относится к cgroups v1 и устарело;MemoryHigh=: мягкий порог. Выше него ядро активно отбирает страницы и притормаживает процесс, давая шанс не дойти до жёсткого лимита. Ставят чуть нижеMemoryMax=;MemorySwapMax=0: не даёт сервису уйти в своп вместо честного OOM, иначе он неделями живёт в деградации;OOMPolicy=: что делать с юнитом, когда убит его процесс. По умолчаниюstop,killдобивает все процессы юнита,continueоставляет остальные;OOMScoreAdjust=: от-1000до1000, сдвигает приоритет при глобальном OOM. Критичным сервисам ставят отрицательное значение.
Лимит меняется и на лету: systemctl set-property my.service MemoryMax=1G. Проверка: systemctl show my.service -p MemoryMax, systemd-cgtop, счётчик oom_kill в файле memory.events cgroup сервиса, а сам факт убийства виден в journalctl -k. Если нужно реагировать раньше ядра, есть systemd-oomd, который убивает по давлению памяти.
Где спотыкаются
Пишут LimitRSS= или LimitAS=. Первый современное ядро Linux игнорирует, второй режет виртуальное адресное пространство и валит JVM и Go-сервисы, которые резервируют много виртуальной памяти, задолго до реальной нехватки.
Ставят MemoryMax= впритык к -Xmx. Heap помещается, но метаспейс, стеки потоков и off-heap буферы выводят процесс за потолок.
Правят юнит прямо в /usr/lib/systemd/system и забывают daemon-reload. Изменения не применяются, а следующее обновление пакета их затирает.