OOM-killer срабатывает раньше, чем ожидается, для docker без root.

Вопрос или проблема

Я использую Docker без root-доступа на общем сервере. Контейнеры Docker могут использовать много памяти, но обычно меньше, чем физический предел. Тем не менее, иногда они уничтожаются OOM-киллером. Я хочу избежать этой проблемы, насколько это возможно.

Также кажется, что целью для уничтожения всегда является не контейнер, а user.service. Я слышал, что vm.oom_kill_allocating_task регулирует это поведение, но, похоже, не работает (устарело?).

У вас есть какое-либо решение по этому вопросу?

  • Конфигурация, чтобы включить OOM-киллер только в критических ситуациях.
  • Уничтожать проблемный контейнер вместо всей пользовательской службы, когда это срабатывает.

Дополнительная информация:

  • ОС: Ubuntu 24.04
  • Память: 256GB физической, >1TB своп (увеличение свопа может не помочь в этой проблеме)
  • Я не уверен относительно systemd-oomd, поэтому связанная конфигурация не изменялась.
  • Вычислительные ресурсы управляются с помощью Slurm, поэтому я хочу, чтобы OOM убивал только очень опасные процессы, которые могут вызвать сбой системы. На данный момент я не думаю, что использование Slurm влияет на эту проблему, но фактическая команда запуска Docker выглядит так: docker run --cpuset-cpus 0-15 -m 64G --gpus "device=0" image:tag ...
$ journalctl --no-pager --no-hostname
Feb 15 00:19:45 systemd[633229]: docker.service: systemd-oomd уничтожил некоторые процессы в этом юните.
Feb 15 00:19:45 systemd[633229]: docker.service: Основной процесс завершился, код=killed, статус=9/KILL
Feb 15 00:19:45 systemd[633229]: docker.service: Уничтожение процесса 633329 (slirp4netns) с сигналом SIGKILL.
Feb 15 00:19:45 systemd[633229]: docker.service: Уничтожение процесса 633363 (containerd) с сигналом SIGKILL.
Feb 15 00:19:45 systemd[633229]: docker.service: Не удалось уничтожить контрольную группу /user.slice/user-1001.slice/[email protected]/app.slice/docker.service, игнорирование: Неверный аргумент
Feb 15 00:19:45 systemd[633229]: docker.service: Уничтожение процесса 633329 (slirp4netns) с сигналом SIGKILL.
Feb 15 00:19:45 systemd[633229]: docker.service: Уничтожение процесса 633363 (containerd) с сигналом SIGKILL.
Feb 15 00:19:45 systemd[633229]: docker.service: Не удалось уничтожить контрольную группу /user.slice/user-1001.slice/[email protected]/app.slice/docker.service, игнорирование: Неверный аргумент
Feb 15 00:19:45 systemd[633229]: docker.service: Завершился с результатом 'сигнал'.
Feb 15 00:19:45 systemd[633229]: docker.service: Процесс юнита 633329 (slirp4netns) остается запущенным после остановки юнита.
Feb 15 00:19:45 systemd[633229]: docker.service: Процесс юнита 633363 (containerd) остается запущенным после остановки юнита.
Feb 15 00:19:45 systemd[633229]: docker.service: Использовано 15мин 2,657с процессорного времени, 23,1G пикового объема памяти, 0B пикового объема свапа памяти.
Feb 15 00:19:45 gvfsd[727979]: Не удается установить соединение с шиной
Feb 15 00:19:45 gvfsd[730917]: Не удается установить соединение с шиной
Feb 15 00:19:45 systemd[633229]: dbus.service: systemd-oomd уничтожил некоторые процессы в этом юните.
Feb 15 00:19:45 kernel: rfkill: включен обработчик ввода
Feb 15 00:19:45 systemd-oomd[1713]: Рассмотрено 57 cgroups для уничтожения, основными кандидатами были:
Feb 15 00:19:45 systemd-oomd[1713]:         Путь: /user.slice/user-1001.slice/[email protected]/app.slice/docker.service
Feb 15 00:19:45 systemd-oomd[1713]:                 Лимит давления памяти: 0.00%
Feb 15 00:19:45 systemd-oomd[1713]:                 Давление: Avg10: 0.00 Avg60: 0.00 Avg300: 0.00 Всего: 24ms
Feb 15 00:19:45 systemd-oomd[1713]:                 Текущая загрузка памяти: 4.7G
Feb 15 00:19:45 systemd-oomd[1713]:                 Минимум памяти: 0B
Feb 15 00:19:45 systemd-oomd[1713]:                 Низкая память: 0B
Feb 15 00:19:45 systemd-oomd[1713]:                 Pgscan: 4224247
Feb 15 00:19:45 systemd-oomd[1713]:                 Последний Pgscan: 4224183
Feb 15 00:19:45 systemd-oomd[1713]:         Путь: /user.slice/user-1001.slice/[email protected]/user.slice/docker-f0a7b0edb9645a366c3d136d0566d84e029f5c4211f3ce4ee2e4e081f3e049cb.scope
Feb 15 00:19:45 systemd-oomd[1713]:                 Лимит давления памяти: 0.00%
Feb 15 00:19:45 systemd-oomd[1713]:                 Давление: Avg10: 77.63 Avg60: 33.71 Avg300: 10.08 Всего: 36s
Feb 15 00:19:45 systemd-oomd[1713]:                 Текущая загрузка памяти: 21.8G
Feb 15 00:19:45 systemd-oomd[1713]:                 Минимум памяти: 0B
Feb 15 00:19:45 systemd-oomd[1713]:                 Низкая память: 0B
Feb 15 00:19:45 systemd-oomd[1713]:                 Pgscan: 0
Feb 15 00:19:45 systemd-oomd[1713]:                 Последний Pgscan: 0
...
Feb 15 00:19:45 systemd-oomd[1713]: Уничтожен /user.slice/user-1001.slice/[email protected]/init.scope из-за давления памяти для /user.slice/user-1001.slice/[email protected] = 75.34% > 50.00% за > 20с с активностью восстановления
$ sudo sysctl vm
vm.admin_reserve_kbytes = 8192
vm.compact_unevictable_allowed = 1
vm.compaction_proactiveness = 20
vm.dirty_background_bytes = 0
vm.dirty_background_ratio = 10
vm.dirty_bytes = 0
vm.dirty_expire_centisecs = 3000
vm.dirty_ratio = 20
vm.dirty_writeback_centisecs = 500
vm.dirtytime_expire_seconds = 43200
vm.extfrag_threshold = 500
vm.hugetlb_optimize_vmemmap = 0
vm.hugetlb_shm_group = 0
vm.laptop_mode = 0
vm.legacy_va_layout = 0
vm.lowmem_reserve_ratio = 256   256 32  0   0
vm.max_map_count = 1048576
vm.memfd_noexec = 0
vm.memory_failure_early_kill = 0
vm.memory_failure_recovery = 1
vm.min_free_kbytes = 90112
vm.min_slab_ratio = 5
vm.min_unmapped_ratio = 1
vm.mmap_min_addr = 65536
vm.mmap_rnd_bits = 32
vm.mmap_rnd_compat_bits = 16
vm.nr_hugepages = 0
vm.nr_hugepages_mempolicy = 0
vm.nr_overcommit_hugepages = 0
vm.numa_stat = 1
vm.numa_zonelist_order = Node
vm.oom_dump_tasks = 1
vm.oom_kill_allocating_task = 1
vm.overcommit_kbytes = 0
vm.overcommit_memory = 0
vm.overcommit_ratio = 50
vm.page-cluster = 3
vm.page_lock_unfairness = 5
vm.panic_on_oom = 0
vm.percpu_pagelist_high_fraction = 0
vm.stat_interval = 1
vm.swappiness = 60
vm.unprivileged_userfaultfd = 0
vm.user_reserve_kbytes = 131072
vm.vfs_cache_pressure = 100
vm.watermark_boost_factor = 15000
vm.watermark_scale_factor = 10
vm.zone_reclaim_mode = 0

Профиль памяти и свапа по Prometheus: вертикальная линия возле центра соответствует приведенному выше логу.

Конфигурация, чтобы включить OOM-киллер только в критических ситуациях.

OOM-киллер вызывается только в критических ситуациях.

Правильный способ исправить это – настроить конфигурацию приложения для работы в пределах доступных ресурсов. Вторичный подход – уменьшить коэффициент over_commit (vm.overcommit_memory = 2 ; vm.overcommit_ratio = 20 и при необходимости отрегулировать коэффициент).

Память: 256GB физической, >1TB своп

Боже мой, это ОЧЕНЬ много памяти. Особенно если у вас нет мониторинга. Исправление вашего мониторинга также должно быть приоритетом.

Ответ или решение

Вопрос, связанный с преждевременным срабатыванием OOM-killer в среде rootless Docker, может возникнуть из-за множества факторов, которыми управляет операционная система и конфигурации Docker. В данном случае вы используете rootless Docker на общем сервере с Ubuntu 24.04, имея значительные аппаратные ресурсы: 256 ГБ физической памяти и более 1 ТБ swap пространства. Однако система сталкивается с непредвиденными проблемами при распределении памяти, что приводит к срабатыванию OOM-killer.

Теоретическая часть

OOM-killer (Out-Of-Memory killer) — это механизм в Linux, который автоматически завершает процессы при нехватке оперативной памяти, чтобы предотвратить полное исчерпание имеющихся ресурсов, что может привести к зависанию системы. Основная задача OOM-killer — освободить ресурсы, чтобы система могла продолжать работать. В современных системах, использующих systemd, за управление OOM-событиями в основном отвечает модуль systemd-oomd, который может быть настроен на основе давления на память и использования swap.

Пример

Ситуация, с которой вы столкнулись, состоит в преждевременном срабатывании OOM-killer, который целится не в контейнеры непосредственно, а в службы пользователя (user.service), такие как slirp4netns и containerd. Это нежелательное поведение, так как вы ожидаете, что только проблемные контейнеры будут остановлены, а не вся служба, под которой они работают.

Применение

Вот несколько подходов, которые вы можете рассмотреть для устранения данной проблемы:

  1. Настройка параметров ядра: Проверьте текущие настройки связанных с памятью параметров системы. Особое внимание стоит уделить параметрам overcommit_memory и overcommit_ratio. Ваши текущие настройки таковы: vm.overcommit_memory = 0 и vm.overcommit_ratio = 50. Вы можете попробовать установить vm.overcommit_memory = 2 и уменьшить vm.overcommit_ratio, чтобы ограничить агрессивные выделения памяти, которые могут провоцировать OOM-killer. Этот подход может быть полезным для более осторожного использования памяти.

  2. Мониторинг и управление ресурсами: Ваша система снабжена значительным объемом swap памяти, однако это не всегда может решить проблему. Лучшим решением будет развернуть эффективную систему мониторинга — например, Prometheus, чтобы отслеживать память в режиме реального времени. Таким образом, вы сможете управлять ограничениями на использование ресурсов для каждого из контейнеров индивидуально.

  3. Настройки Docker: Рассмотрите возможность более тонкой настройки ограничений для каждого Docker-контейнера. Например, изменение параметров --memory и --memory-swap в команде docker run. Это позволит контролировать, сколько физической памяти и swap может быть использовано каждым контейнером.

  4. Используйте systemd-oomd: Поскольку вы не изменяли конфигурацию systemd-oomd, вам стоит ее настроить так, чтобы использовать давление на память как метрику для завершения процессов. Ознакомьтесь с документацией по systemd-oomd, чтобы настроить agressive reclaiming и оптимальные thresholds для вашего окружения.

  5. Тест и оптимизация приложений: Проверьте архитектуру приложений на предмет утечек памяти и малоэффективных операций с памятью. Это можно сделать с помощью профилирования нагрузки на систему в условиях, приближенных к боевым.

  6. Изоляция и тестирование на стенде: Попробуйте перенести приложения в отдельные тестовые контейнеры или окружения, чтобы выявить специфические проблемы с памятью без риска для основной системы.

Таким образом, правильно выбранный и сконфигурированный набор инструментов мониторинга и управления памятью, а также более строгий контроль над выделением ресурсов контейнерами могут помочь в снижении риска преждевременного срабатывания OOM-killer в вашей системе.

Оцените материал
Добавить комментарий

Капча загружается...