Найти в Дзене
ИнфоКомм

Сеть в Linux (Linux Traffic Control)

Оглавление

Привет, дорогой читатель!

Страница регистрации в академии
Страница регистрации в академии

Зарегистрируйтесь и получите доступ к бесплатному контенту. А также будьте в курсе нового учебного контента. Ссылка на учебную платформу:

Академия ИНФОКОММ

infocomm.space

Благодарность автору
Благодарность автору

Если материал полезен, то есть способ отблагодарить меня. Любая сумма будет отличной наградой и стимулом писать полезный контент для Вас.

Купить кофе автору

TC+NETEM+TBF+IPERF

Думаю, ни для кого не секрет, что общемировой тренд на применение Unix-based дистрибутивов как в бизнесе, так и в личном использовании продолжается и обороты не шуточные (в России так уж точно ставка на Linux уже сделана…). Скажу сразу, что если в личной жизни люди пока что чаще используют Windows (исторически сложилось…), то сервисы, которыми вы пользуетесь ежедневно "живут" преимущественно на Linux серверах в ЦОДах. Если быть точнее, то в Docker контейнерах, но сейчас не об этом…) Поэтому данная статься преимущественно для начинающего сетевого инженера (админа)/DevOps инженера, приоткрывающая ширму безграничных возможностей Linux по управлению траффиком. Если интересно и актуально – погнали под кат!

Итак, речь пойдет про такие утилиты как tc (traffic control) – очень полезную и мощную утилиту, которая дает возможность настраивать пакетный фильтр ядра. Для чего это может понадобится? Ну прежде всего для симуляции (воссоздания) реальных сред передачи данных. Если вы сетевой инженер, то вам может понадобится отработать сценарии с потерями пакетов (packet loss) и задержками (packet delay) на каналах, как для TCP так и для UDP приложений или же попросту ограничить пропускную способность канала. Если мы говорим про DevOps инженера и разработчиков, то умение работать с такими утилитами как tc и netem (network emulator) могут помочь, к примеру, при тестировании эффективности уровня (слоя) кеша между приложением и базой данных, чтобы увидеть ощутимую разницу между временем получения ответов от самой базы (первые обращения) и получением уже закешированных SQL ответов. Надеюсь объяснил актуальность, а теперь приступаем к демонстрационным примерам.

Исходная схема простейшего стенда:

-3

Исходные задержки (packet dalay), потери (packet loss) в направлении ПК2-->ПК1:

-4

Задержки (packet delay)

Цель эксперимента - установить на интерфейсе ens 256 (ПК1) задержку в 400ms и удостовериться с ПК2, что мы действительно наблюдаем задержку (используя для этого не менее классную утилиту MTR).

Для этого нам потребуется следующая команда:

tc qdisc add dev ens256 root netem delay 400ms

где tc - сама утилита, qdisq - сокращение от 'queueing discipline' (если по простому - это набор очередей для интерфейсов), dev ens256 - тут мы указываем для какого интерфейса конкретно мы будем использовать qdisc, netem - надстройка над tc, позволяющая в понятном человеку формате формировать правила задержек, потерь, изменений (corruption) пакетов для исходящего с указанного интерфейса трафика (egress).

Посмотреть, какие в данный момент правила применены на интерфейсе можно так:

-5

Итак результат в студию (картина на ПК2):

-6

Заметили, что к средней задержке в 0.3 мс добавилась нехилая задержка в 400ms?

Теперь не маловажно разобраться а как же все вернуть в зад. Ну так это тоже не сложно, поможет команда:

tc qdisc del dev ens256 root

После применения команды смотрим, что в данный момент на интерфейсе все в штатном состоянии:

-7

Поехали дальше!

Потеря пакетов и изменение трафика (Packet Loss and Packet Corruption)

Цель эксперимента (Packet Loss) - установить на интерфейсе ens 256 (ПК1) требуемый уровень потерь (пусть будет 10%) и удостовериться с ПК2, что мы действительно наблюдаем потери.

Для этого нам потребуется следующая команда:

tc qdisc add dev ens256 root netem loss 10%

Картина на ПК2:

-8

Результат ожидаем, не так ли? Имеем на сети потери в 10%.

Удаляем правило, как делали в первом эксперименте командой

tc qdisc del dev ens256 root и двигаемся дальше...

Давайте на минуту задумаемся, а что мы можем считать утратой пакета?

Не знаю как вам, а мне пришла на ум парочка вариантов:

1. Пакет "дропнули" на транзите или на пункте назначения (пакет не дошел до ядра конечной системы). Данный случай мы как раз сымитировали чуть ранее ;

2. Пакет таки дошел, но контрольная сумма не сошлась и он был отброшен (пакет пришел в ядро, система проверила его на целостность и он не прошел ее и был дропнут). Данную ситуацию можно сымитировать утилитой tc, но используя ключевое слово - currupt. Команда будет выглядеть так:

tc qdisc add dev ens256 root netem corrupt 5%

А результат так:

-9

При данных режимах работы tc - стремится к указанному процентному значению, но достигает их изредка и значение будет колебаться в пределах от 2 до 5%.

3. По какой-то причине пакет задвоился и за оригинальным пакетом, следом пришел брат близнец - итог тот же - дроп). Данную ситуацию можно сымитировать утилитой tc, но используя ключевое слово - duplicate. Команда может выглядеть так:

tc qdisc add dev ens256 root netem duplicate 1%

Результат не буду показывать, он не особо информативен. Общая суть думаю уже понятна.

Вывод: Теперь вы знаете как выглядят потери, задержки. Однако причин потерь может быть несколько и тут уже вам придется глубже капнуть в том месте, на том хопе на который вам указывает MTR.

Пропускная способность (Bandwidth limit)

Для того чтобы ограничить ширину канала на выходе с интерфейса нам потребуется команда вида:

tc qdisc add dev ens256 root tbf rate 1mbit burst 32kbit latency 400ms

данной командой мы хотим ограничить пропускную способность исходящего (egress) канала одним мегабитом в секунду с возможностью превысить данное пороговое значение в период всплесков до 32 кбит/с.

Тут нужно пояснить, что для ограничения ширины канала используется tbf - Token Bucket Filter. Если упрощать, то это своего рода буфер. В своей работе tbf использует взаимоисключающие друг друга опции: latancy и limit. Latancy в работе tbf - максимальное время которое пакет должен просиживать в буфере. Limit - количество байт, которое может быть помещено в буфер (очередь) ожидания своего токена на передачу. В нашем примере мы будем использовать опцию latency.

Итак выполнили команду на ПК2, и теперь нам как-то надо проверить, что действительно канал ПК1-->ПК2 такой каким мы его планировали. Для этого нам пригодится еще одна полезная утилита iperf. Запустим iperf в режиме сервера на ПК2 командой:

iperf -s 0.0.0.0

Теперь на ПК2 у нас прослушивается порт 5001:

-10

На ПК1 же, в свою очередь, запускаем iperf в режиме клиента командой:

iperf -c 10.159.115.117 и получаем следующий результат на ПК1:

-11

На ПК2 результат такой:

-12

Обратите внимание, что пропускная способность ограничена в данный момент в направлении ПК1-->ПК2. Чтобы канал имел единую пропускную способность, надо сделать зеркальные настройки.

На этом все! Надеюсь было полезно и я вас побудил покопать глубже при необходимости. Буду благодарен если оцените лайком, а в идеале жду комментарии, дополнения и вопросы!

До новых встреч!