- PVSM.RU - https://www.pvsm.ru -
Kubernetes требует, чтобы каждый контейнер в кластере имел уникальный, маршрутизируемый IP. Kubernetes не назначает IP-адреса сам, оставляя эту задачу сторонним решениям.
Цель этого исследования — найти решение с наименьшими задержками, наибольшей пропускной способностью и самой небольшой стоимостью настройки. Поскольку наша нагрузка зависит от задержек, мы измеряем задержки высоких перцентилей [1] при достаточно активной сетевой нагрузке. В частности, мы сфокусировались на производительности в районе 30-50 процентов от максимальной нагрузки, поскольку это лучше всего отражает типовые ситуации для неперегруженных систем.
--net=host
Наша образцовая инсталляция. Все другие варианты сравнивались с ней.
Опция --net=host
[2] означает, что контейнеры наследуют IP-адреса своих хост-машин, т.е. сетевой контейнеризации нет.
Отсутствие сетевой контейнеризации априори обеспечивает лучшую производительность, чем наличие любой реализации — по этой причине мы использовали данную инсталляцию как эталон.
Flannel [3] — решение виртуальной сети, поддержкой которого занимается проект CoreOS [4]. Хорошо проверенное и готовое к production, поэтому стоимость внедрения минимальна.
Когда вы добавляете машину с flannel в кластер, flannel делает три вещи:
docker0 bridge
).aws-vpc
— регистрирует подсеть машины в таблице экземпляров Amazon AWS. Количество записей в этой таблице ограничено 50, т.е. вы не можете иметь более 50 машин в кластере, если используете flannel с aws-vpc
. Вдобавок, этот бэкенд работает только с Amazon AWS;host-gw
— создаёт IP-маршруты до подсетей через IP-адреса удалённой машины. Требует прямой L2-связности между хостами, на которых запущен flannel;vxlan
— создаёт виртуальный интерфейс VXLAN [8].Поскольку flannel использует интерфейс моста для пересылки пакетов, каждый пакет проходит через два сетевых стека, когда отправляется из одного контейнера в другой.
IPvlan [9] — драйвер в ядре Linux, позволяющий создавать виртуальные интерфейсы с уникальными IP-адресами без необходимости в использовании интерфейса моста.
Для назначения IP-адреса контейнеру с помощью IPvlan требуется:
IPvlan — относительно новое решение, поэтому пока нет готовых инструментов для автоматизации этого процесса. Таким образом, деплой IPvlan на множестве машин и контейнеров усложняется, то есть стоимость внедрения высока. Однако IPvlan не требует интерфейса моста и пересылает пакеты напрямую из NIC в виртуальный интерфейс, поэтому мы ожидали лучшей производительности, чем у flannel.
Для каждого варианта мы проделали следующие шаги:
Мы запускали этот тест с разными количеством запросов: от 50 000 до 450 000 запросов в секунду (RPS).
Для каждого запроса nginx отвечал статическим файлом фиксированного размера: 350 байт (содержимое в 100 байт и заголовки в 250 байт) или 4 килобайта.
host-gw
и aws-vpc
следует за ним с близкими показателями, при этом host-gw
проявил себя лучше под максимальной нагрузкой.vxlan
показал худшие результаты во всех тестах. Однако мы подозреваем, что его исключительно плохой перцентиль 99,999 вызван багом.--net=host
при приближении к лимиту пропускной способности.
Наш текущий выбор — flannel с host-gw
. У него мало зависимостей (в частности, не требуется AWS или новая версия ядра Linux), он прост в установке по сравнению с IPvlan и предлагает достаточную производительностью. IPvlan — наш запасной вариант. Если в какой-то момент flannel получит поддержку IPvlan, мы перейдём на такой вариант.
Несмотря на то, что производительность aws-vpc
оказалось немного лучше host-gw
, ограничение в 50 машин и факт жёсткой привязки к Amazon AWS стали для нас решающими факторами.
На 50 000 запросах в секунду все кандидаты продемонстрировали приемлемую производительность. Уже можно заметить основной тренд: IPvlan показывает лучшие результаты, host-gw
и aws-vpc
следуют за ним, а vxlan
— худший.
Перцентили задержки на 150 000 RPS (≈30 % от максимального RPS), мс
IPvlan немного лучше, чем host-gw
и aws-vpc
, однако у него худший перцентиль 99,99. У host-gw
немного лучшая производительность, чем у aws-vpc
.
Предполагается, что такая нагрузка является обычной для production, поэтому результаты в особенности важны.
Перцентили задержки на 250 000 RPS (≈50 % от максимального RPS), мс
IPvlan снова показывает лучшую производительность, но у aws-vpc
лучший результат в перцентилях 99,99 и 99,999. host-gw
превосходит aws-vpc
в перцентилях 95 и 99.
В большинстве случаев задержка близка к результатам для 250 000 RPS (350 байт), однако она стремительно растёт после перцентиля 99,5, что означает приближение к максимальному RPS.
Интересно, что host-gw
показывает гораздо лучшую производительность, чем aws-vpc
:
При нагрузке в 500 000 RPS только IPvlan всё ещё работает и даже превосходит --net=host
, однако задержка столь высока, что мы не можем назвать её допустимой для приложений, которые чувствительны к задержкам.
Большие результаты запросов (4 килобайта против тестируемых ранее 350 байт) приводят к большей сетевой нагрузке, однако список лидеров практически не меняется:
Перцентили задержки на 50 000 RPS (≈20 % от максимального RPS), мс
У host-gw
на удивление плохой перцентиль 99,999, однако он всё ещё показывает хорошие результаты для меньших перцентилей.
Перцентили задержки на 150 000 RPS (≈60 % от максимального RPS), мс
Это максимальный RPS с большим ответом (4 Кб). aws-vpc
значительно превосходит host-gw
в отличие от случая с небольшим ответом (350 байт).
Vxlan
был снова исключён из графика.
Для лучшего понимания этой статьи и воспроизведения нашего тестового окружения необходимо быть знакомым с основами высокой производительности.
В этих статьях содержится полезная информация по этой теме:
Современные NIC используют Receive Side Scaling (RSS) [19] через многочисленные линии запроса прерывания (IRQ [20]). EC2 предлагает только две такие линии в виртуализированном окружении, поэтому мы протестировали несколько конфигураций с RSS и Receive Packet Steering (RPS) [21] и пришли к следующим настройкам, отчасти рекомендованным документацией по ядру Linux:
lscpu
:
$ lscpu | grep NUMA
NUMA node(s): 2
NUMA node0 CPU(s): 0-8,18-26
NUMA node1 CPU(s): 9-17,27-35
Эта настройка выполняется записью 0
и 9
в /proc/irq/<num>/smp_affinity_list
, где номера IRQ получаются через grep eth0 /proc/interrupts
:
$ echo 0 > /proc/irq/265/smp_affinity_list
$ echo 9 > /proc/irq/266/smp_affinity_list
smp_affinity
в IRQ, у sysfs-файла rps_cpus
нет постфикса _list
, поэтому для перечисления CPU, которым RPS может направлять трафик, используются битовые маски (подробнее см. Linux kernel documentation: RPS Configuration [14]):
$ echo "00000000,0003fdfe" > /sys/class/net/eth0/queues/rx-0/rps_cpus
$ echo "00000000,0003fdfe" > /sys/class/net/eth0/queues/rx-1/rps_cpus
$ echo "00000000,07fc01ff" > /sys/class/net/eth0/queues/tx-0/xps_cpus
$ echo "0000000f,f803fe00" > /sys/class/net/eth0/queues/tx-1/xps_cpus
$ echo 65536 > /proc/sys/net/core/rps_sock_flow_entries
$ echo 32768 > /sys/class/net/eth0/queues/rx-0/rps_flow_cnt
$ echo 32768 > /sys/class/net/eth0/queues/rx-1/rps_flow_cnt
worker_cpu_affinity
[22]:
workers 18;
worker_cpu_affinity 1 10 100 1000 10000 ...;
taskset
и настроили планировщик для редкого переназначения потоков:
$ echo 10000000 > /proc/sys/kernel/sched_migration_cost_ns
$ taskset -ac 0-17 tcpkali --threads 18 ...
Такая конфигурация позволила равномерно распределить нагрузку на прерывания по ядрам процессора и добиться лучшей пропускной способности с сохранением той же задержки, что и в других опробованных конфигурациях.
Ядра 0 и 9 обслуживают только прерывания сетевых карт (NIC) и не работают с пакетами, но они остаются самыми занятыми:
Также был использовал tuned [23] от Red Hat с включённым профилем network-latency.
Для минимизации влияния nf_conntrack были добавлены правила NOTRACK [24].
Конфигурация sysctl была настроена на поддержку большого количества TCP-подключений:
fs.file-max = 1024000
net.ipv4.ip_local_port_range = "2000 65535"
net.ipv4.tcp_max_tw_buckets = 2000000
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1
net.ipv4.tcp_fin_timeout = 10
net.ipv4.tcp_slow_start_after_idle = 0
net.ipv4.tcp_low_latency = 1
От переводчика: Большое спасибо коллегам из Machine Zone, Inc за проведённое тестирование! Оно помогло нам, поэтому мы захотели поделиться им и с другими.
P.S. Возможно, вас также заинтересует наша статья «Container Networking Interface (CNI) — сетевой интерфейс и стандарт для Linux-контейнеров [25]».
Автор: zuzzas
Источник [26]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/proizvoditel-nost/259728
Ссылки в тексте:
[1] перцентилей: https://ru.wikipedia.org/wiki/%D0%9A%D0%B2%D0%B0%D0%BD%D1%82%D0%B8%D0%BB%D1%8C#.D0.9F.D0.B5.D1.80.D1.86.D0.B5.D0.BD.D1.82.D0.B8.D0.BB.D1.8C
[2] --net=host
: https://docs.docker.com/engine/reference/run/#network-settings
[3] Flannel: https://github.com/coreos/flannel
[4] CoreOS: https://coreos.com/
[5] etcd: https://github.com/coreos/etcd
[6] интерфейс моста: http://www.linuxfoundation.org/collaborate/workgroups/networking/bridge
[7] бэкенд: https://github.com/coreos/flannel#backends
[8] интерфейс VXLAN: https://en.wikipedia.org/wiki/Virtual_Extensible_LAN
[9] IPvlan: https://www.kernel.org/doc/Documentation/networking/ipvlan.txt
[10] Настроили сеть: http://machinezone.github.io/research/networking-solutions-for-kubernetes/#environment
[11] tcpkali: https://github.com/MachineZone/tcpkali
[12] How to receive a million packets per second: https://blog.cloudflare.com/how-to-receive-a-million-packets/
[13] How to achieve low latency with 10Gbps Ethernet: https://blog.cloudflare.com/how-to-achieve-low-latency/
[14] Scaling in the Linux Networking Stack: https://www.kernel.org/doc/Documentation/networking/scaling.txt
[15] c4.8xlarge: https://aws.amazon.com/ec2/instance-types/#c4
[16] enhanced networking: http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/enhanced-networking.html
[17] NUMA: https://en.wikipedia.org/wiki/Non-uniform_memory_access
[18] Linux 4.3.0: http://elrepo.org/linux/kernel/el7/x86_64/RPMS/
[19] Receive Side Scaling (RSS): https://msdn.microsoft.com/en-us/library/windows/hardware/ff556942(v=vs.85).aspx
[20] IRQ: https://en.wikipedia.org/wiki/Interrupt_request_(PC_architecture)
[21] Receive Packet Steering (RPS): https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/6/html/Performance_Tuning_Guide/network-rps.html
[22] worker_cpu_affinity
: http://nginx.org/en/docs/ngx_core_module.html#worker_cpu_affinity
[23] tuned: https://fedorahosted.org/tuned/
[24] правила NOTRACK: http://serverfault.com/a/536303/99164
[25] Container Networking Interface (CNI) — сетевой интерфейс и стандарт для Linux-контейнеров: https://habrahabr.ru/company/flant/blog/329830/
[26] Источник: https://habrahabr.ru/post/332432/
Нажмите здесь для печати.