ТЕХНОЛОГИИ

Cannot create thread в контейнере: проверка pids.max и pids.events

В этом материале
ГЛАВНОЕ ЗА МИНУТУ

Ошибка создания потока в контейнере может означать достижение pids.max, даже если RAM и GPU свободны. В pids controller учитываются задачи ядра, включая потоки, поэтому число процессов в привычном представлении ps может недооценивать расход лимита.

Ошибка создания потока в контейнере может означать достижение pids.max, даже если RAM и GPU свободны. В pids controller учитываются задачи ядра, включая потоки, поэтому число процессов в привычном представлении ps может недооценивать расход лимита.

Привяжите ошибку к действующей группе

Сохраните точное сообщение, время и PID приложения. Найдите его cgroup через /proc/PID/cgroup со стороны хоста и прочитайте pids.current, pids.max, pids.events. Счётчик max в events показывает отказы из-за лимита, а не число погибших процессов. Проверяйте прирост за интервал воспроизведения. У контейнера может быть разрешён большой бюджет, но более тесная родительская группа ограничит создание новых задач для всех своих потомков.

Официальный источник 1.

Посчитайте потоки отдельно

Один Python-процесс может запускать потоки библиотек, сетевых клиентов и подготовки данных. Список PID без TID не описывает такую нагрузку. Сопоставьте число задач приложения с pids.current и проверьте, не стартуют ли одновременно диагностические команды, фоновые worker или повторные экземпляры службы. Когда лимит уже достигнут, даже docker exec может не суметь создать shell. Это осложнение диагностики, а не доказательство отсутствия работающего основного процесса.

Официальный источник 2.

Разберите рост после обновления

В условном контейнере pids.max равен 128. После добавления нескольких подготовительных worker pids.current приближается к 128, а очередной thread start получает EAGAIN. Откат числа worker возвращает возможность запуска. Такой опыт поддерживает гипотезу pids limit, если одновременно увеличился pids.events. При стабильных событиях изучайте другие ограничения создания потоков и фактический расход памяти, вместо автоматического повышения этого предела.

Поле диагностической записиСмысл проверки
PID и путь cgroupОшибка относится к нужному экземпляру
pids.current до и послеВидно изменение числа задач
Прирост events maxЕсть связь с отказом контроллера
Лимиты родителейПроверена общая граница потомков

Выберите ограниченное исправление

Сначала уберите повторные процессы и ненужную параллельность. Если количество потоков оправдано, пересчитайте pids budget с запасом для запуска и обслуживания, затем измените декларативную конфигурацию. Бесконечный предел скрывает ошибки неконтролируемого размножения задач. Не завершайте процессы наугад по имени: один контейнер может включать важный родительский процесс и его нормально работающие дочерние задачи. Для воспроизведения достаточно отдельного стенда с той же структурой запуска.

Проверьте повторный старт

Сделайте холодный запуск, рабочую нагрузку и штатное завершение. На каждой стадии сохраните число задач и прирост events. Проверьте, остаётся ли возможность выполнить заранее согласованную диагностическую команду при максимальной нагрузке. Итоговый артефакт должен включать разрешённое число worker, предельный наблюдавшийся расход и значение pids.max. Такой документ описывает реальный бюджет процессов; он не обещает, что любое последующее обновление библиотек сохранит прежнее количество потоков.

Также сохраните дерево потомков после завершения нагрузки. Оставшиеся фоновые задачи могут объяснить расход следующего запуска, даже если текущая операция уже закончилась и основное приложение выглядит простаивающим.

Связанные разборы: gpu containers vs vms; server preparation.

← Все материалы