Время отклика Kubenet ухудшено, решено с помощью hostNetwork: правда, с приложением Unicorn

Я пытаюсь отладить проблему, которая решается с помощью hostNetwork: true, Установка k8s использует kubenet, а версия k8s 1.9.8.

Установка выполняется с помощью kops на AWS с использованием экземпляров m4.xlarge и c4.xlarge.

Проблема заключается в следующем:

Когда мы перенесли это приложение в kubernetes, время отклика (процентиль 95) для определенной конечной точки увеличилось примерно на 20-30%.

Эта проблема решается, однако, при использовании hostNetwork: true в ямле. Производительность такая же, как на виртуальных машинах для этой конечной точки, т. Е. Процентиль 95 для времени отклика одинакова для этой конечной точки.

Я спрашивал об этом в рабочие часы кабинета 18 января (да, некоторое время назад!) И hostNetwork: true Обходной путь подойдет туда.

Обратите внимание, что все содержимое Kube-прокси может быть отброшено, так как это увеличенное время отклика видно при измерении в самом приложении. Я имею в виду, что приложение ruby ​​измеряет время, которое требуется, и отправляет его сборщику журналов. На этот раз, то есть, поскольку запрос начинает обрабатываться приложением до его завершения, он уже показывает снижение производительности. Таким образом, Kube-прокси и тому подобное вне уравнения.

Стручок имеет 3 контейнера:

  • Nginx
  • Сборщик бревен
  • Приложение (приложение ruby, работающее с единорогом)

Эти приложения также находятся в режиме виртуальных машин

Что я пробовал:

  • Нашел способ воспроизвести с помощью ab(apache benchmark)
    • ab -c 1 -n 1000 'https://...
    • То же самое происходит с http, а не https
  • Я попытался удалить контейнер nginx, но это ничего не меняет. Сборщик журналов используется поверх localhost, и то же самое делается на виртуальных машинах, которые не демонстрируют проблему.
  • Я пытался использовать unix-сокеты между nginx и приложением вместо localhost, но это тоже ничего не изменило.
  • Пробовал использовать те же экземпляры (m4.xlarge) с EKS: происходит то же самое. Хотя стоимость производительности не использует hostNetwork: true меньше, около 10%. Обратите внимание, что EKS не использует kubenet и использует свое собственное сетевое наложение на основе какого-либо открытого источника.
  • Пробовал использовать другую конечную точку, которая просто возвращает строку (ставит "ОК"), и проблема не возникает
  • Пробовал использовать конечную точку, которая возвращает несколько МБ (например, "Die" * 10 * 1024 * 1024) и вопроса тоже не бывает
  • Пробовал ту же самую конечную точку, которая имеет проблему с различными параметрами строки запроса, таким образом, ответ является большим (9 МБ) или коротким (130 КБ), и оба надежно воспроизводят проблему
  • Попробовал приложение nodejs, которое возвращает похожие jsons из аналогичных источников, и проблема отсутствует (ни с короткими / длинными ответами). Что может делать дальше:

Итак, я пытаюсь отладить эту проблему, чтобы понять, что это такое, и, надеюсь, перестать использовать hostNetwork: true, Там, кажется, путь, чтобы копать дальше:

  • Попробуйте другие CNI (EKS показал меньшее снижение производительности), чтобы увидеть, если производительность меняется

  • Посмотрите, что делает эта конечная точка или как она взаимодействует с единорогом и всем стеком. Одно большое отличие состоит в том, что единорог - это один процесс на запрос (синхронный), а nodejs - нет.

  • Попробуйте использовать более новые машины (m5/c5), чтобы увидеть, не снижают ли они производительность. Но, поскольку эта проблема не существует с текущими экземплярами, использующими их в качестве виртуальных машин, кажется, что, если это поможет, будет только скрыть проблему

Эта конечная точка, имеющая проблему с perf, является конечной точкой в ​​ruby, которая читает базу данных и возвращает json. С базой данных, хостом, сетью все выглядит нормально (мониторинг процессора, дискового ввода-вывода, подкачки и т. Д. С помощью vmstat, наших обычных инструментов, консоли AWS, проверка kern.log, sysloca и тому подобного)

Случайно, у вас был подобный опыт? Или у вас есть другие идеи о том, как продолжить отладку этой проблемы?

Любые идеи или любая помощь более чем приветствуются!

Родриго

2 ответа

Кажется, проблема в https://github.com/kubernetes/kubernetes/issues/56903

Обходные пути, упомянутые там (как dnsPolicy: DefaultРешите вопрос для меня.

Эти два поста объясняют проблему подробно: https://www.weave.works/blog/racy-conntrack-and-dns-lookup-timeouts и https://blog.quentin-machu.fr/2018/06/24/5-15s-dns-lookups-on-kubernetes/

А также предоставить некоторые обходные пути.

Короче говоря: в nf существует состояние гонки, которое влияет на протоколы без установления соединения (например, UDP) при выполнении DNAT/SNAT. Ребята плетения прислали патч, чтобы исправить большинство гонок. Чтобы обойти это, вы можете использовать внешний DNS (т.е. не Kube-DNS, так как он предоставляется через службу и, следовательно, использует DNAT), установить флаги для glibc (но не работают для Musl), использовать минимальную задержку с tc, так далее.

Примечание: использование dnsPolicy: Default делает трюк, потому что он использует внешний DNS-сервер (то есть не размещен в kubernetes и не доступен через службу, которая выполняет DNAT).

Я проверю флаги glibc для моего кластера, хотя dnsPolicy: Default Для меня эта проблема решается, так как мы используем разрешение службы DNS k8s в некоторых приложениях.

Звучит так, как будто вы испытываете накладные расходы из-за NAT Докера.
hostNetwork: true предоставляет доступ к сети хоста для pod/ контейнера (ов), в отличие от использования NAT, обеспечивая лучшую производительность... Но снижая безопасность.

Надеюсь это поможет!

Другие вопросы по тегам