Вопрос или проблема
Я работаю в среде Kubernetes.
На одном поде я запускаю клиент, который отправляет различное количество параллельных запросов на вывод LLM на кластер (поды) серверов, каждый из которых имеет свой собственный IP-адрес кластера.
Однако у меня возникают некоторые проблемы, когда я пытаюсь увеличить количество параллельных запросов на клиенте. Кажется, он может обрабатывать 2048 запросов, но не 4096. Когда я масштабирую до 4096, родительский процесс, который порождает мои потоки “клиента”, зависает на этом этапе:
больше стандартного вывода libcurl
.
.
.
* Закрытие соединения 60
* Кэш соединений полон, закрывается самое старое соединение
* Кэш соединений полон, закрывается самое старое соединение
* Соединение #184 с хостом 10.xxx.xx.154 осталось нетронутым
* Закрытие соединения 105
* Закрытие соединения 40
* Соединение #232 с хостом 10.xxx.xx.154 осталось нетронутым
* Соединение #63 с хостом 10.xxx.xx.154 осталось нетронутым
* Кэш соединений полон, закрывается самое старое соединение
* Закрытие соединения 205
* Соединение #238 с хостом 10.xxx.xx.154 осталось нетронутым
Сейчас я предполагаю, что это проблема с клиентом, потому что я не вижу плохих HTTP ответов в логах серверов, запросы просто перестают приходить.
Клиентскому поду назначено 64 2-ядерных vCPU и более 128 ГиБ ОЗУ, так что я сильно сомневаюсь, что это из-за исчерпания ресурсов.
Есть ли у кого-нибудь какие-либо идеи, что еще может вызывать это?
Ответ или решение
Исходя из представленной ситуации, проблема связана с ошибкой "слишком много открытых соединений", возникающей в среде Kubernetes при увеличении количества одновременных запросов на инференцию модели широкомасштабного языка (LLM) с одного клиента к кластеру серверов. Давайте рассмотрим детали более подробно и предложим возможные решения.
Теория
Проблема "too many open connections" часто связана с исчерпанием лимитов на количество допустимых одновременных сетевых соединений. Это может быть вызвано несколькими факторами:
-
Ограничения на уровне клиента: Например, библиотека libcurl может иметь ограничения на количество открытых соединений. Это может проявляться в сообщениях о переполнении кэша соединений, как указано в вашем выводе.
-
Ограничения операционной системы: В Unix-подобных ОС существуют лимиты на количество открытых файлов (file descriptors), которые также контролируют количество открытых сетевых соединений. Эти лимиты могут быть установлены участниками Kubernetes или операционной системой, на которой выполняется клиентский под.
-
Квоты и настройки Kubernetes: Kubernetes сам по себе может иметь ограничения на уровне кластера, которые могут ограничивать количество соединений, особенно если используется сетевой плагин (например, Calico, Weave), который может иметь собственные ограничения.
Пример
Рассмотрим типичный сценарий: у вас есть клиентское приложение, написанное с использованием библиотеки libcurl, которое посылает HTTP-запросы к серверу. Если клиентская программа пытается создать больше соединений, чем разрешено текущими настройками, она начнет закрывать старые соединения, чтобы открыть новые. Это приведет к частичной или полной остановке новых запросов.
Применение
Чтобы разрешить данную проблему, рассмотрите следующие шаги:
-
Настройки libcurl: Проверьте конфигурацию libcurl в вашей клиентской программе. Попробуйте изменить настройки
CURLOPT_MAXCONNECTS
, чтобы увеличить размер кэша соединений. Это поможет libcurl лучше управлять большим числом открытых соединений. -
Параметры операционной системы: Убедитесь, что лимиты на количество файлов (file descriptors) достаточно высоки. Это можно проверить и изменить с помощью команд
ulimit -n
на клиентском поде Kubernetes. Если текущий лимит низок, увеличьте его посредством корректировки параметров ядра или скриптов инициализации системы. -
Настройки кластера Kubernetes: Проверьте и настройте максимальные квоты на уровне кластера и отдельных подов. Убедитесь, что используются оптимальные настройки для сетевого плагина, который управляет сетевыми соединениями между подами.
-
Оптимизация клиентского приложения: Рассмотрите возможность использования пулов соединений или механизмов повторного использования соединений внутри вашей клиентской программы, чтобы уменьшить необходимость создавать новые соединения при каждом запросе.
-
Мониторинг и логирование: Имплементируйте расширенный мониторинг и логирование как на стороне клиента, так и на стороне сервера, чтобы детально отслеживать состояние и количество соединений в реальном времени. Это поможет в точной диагностике проблем по мере их появления.
-
Распределение нагрузки: Если это возможно, рассмотрите возможность горизонтального масштабирования клиентских подов для распределения нагрузки равномернее, что может помочь отчасти снять нагрузку на единичные экземпляры по количеству одновременно поддерживаемых соединений.
Следуя этим рекомендациям, вы сможете устранить или значительно минимизировать проблемы с нехваткой открытых соединений, улучшив производительность и надежность вашего приложения в Kubernetes.