Linux docker shaper: Управление траффиком внутри контейнера

Материал из noname.com.ua
Перейти к навигацииПерейти к поиску


Ограничение траффика в контейнере

Постановка задачи

Настроить гибкое управление траффиком в том числе задержками и потерями внутри контейнера==

Предварительно определнные значения переменных

В примере 6142712b1eef это индентификатор контейнера

Получения PID

Получить PID процесса докера (внутри контейнера этот процесс будет иметь PID=1)

docker inspect -f '{{.State.Pid}}' "6142712b1eef"

Далее можно этот пид подставлять везде в комманды или исподбзовать переполучение его каждый раз (что более гибко)
для удобства помещаем идентификатор контейнера в переменную окружения

export DOCKER_CONTAINER_UUID="6142712b1eef"

Подготовительный шаги

Для утилиты ip требуются файлы в /var/run/netns

mkdir -p /var/run/netns
ln -sf /proc/$(docker inspect -f '{{.State.Pid}}' "${DOCKER_CONTAINER_UUID}")/ns/net "/var/run/netns/${DOCKER_CONTAINER_UUID}"

По сути тут делается симлинк с файла который указывает на неймспейс созданный докером в место где ожидает его найти ip
подробнее можно прочитать тут : мануал
Кототкая цитата:

       By convention a named network namespace is an object at
       /var/run/netns/NAME that can be opened. The file descriptor resulting
       from opening /var/run/netns/NAME refers to the specified network
       namespace. Holding that file descriptor open keeps the network
       namespace alive. The file descriptor can be used with the setns(2)
       system call to change the network namespace associated with a task.
После проделанных шагов набюлюдаю доступный  для работы netns
# ip netns
6142712b1eef (id: 6)


Управление траффиком внутри контейнера

Создание псевдоинтерфейсов ifb

modprobe  ifb numifbs=10

Перенос интерфейсов из глобального неймспейса в докер

ip link set  dev ifb0 netns ${DOCKER_CONTAINER_UUID}
ip link set  dev ifb1 netns ${DOCKER_CONTAINER_UUID}


Переход в контейнер

Тут можно воспользоваться альтернативным путем - утилитой nsenter но в данном случае это мне кажется излишним

ip netns exec ${DOCKER_CONTAINER_UUID} bash


Проверка состояния интерфейсов

ifconfig  -a
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.255.5  netmask 255.255.255.0  broadcast 192.168.255.255
        ether 02:42:c0:a8:ff:05  txqueuelen 0  (Ethernet)
        RX packets 1680190  bytes 287513973 (287.5 MB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 1094755  bytes 119082164 (119.0 MB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

ifb0: flags=130<BROADCAST,NOARP>  mtu 1500
        ether b2:fa:b3:1f:cc:21  txqueuelen 32  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

ifb1: flags=130<BROADCAST,NOARP>  mtu 1500
        ether ca:44:06:d0:6d:c9  txqueuelen 32  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
<skipped>


Поднять псевдоинтерфейсы

ip link set up dev ifb0
ip link set up dev ifb1


Для простоты помещаем имя интерфейса на котором будем управлять трафикомв переменную окружения

export   CONTAINER_INTERFACE="eth0"

Очистить существующие правила

tc qdisc delete dev ${CONTAINER_INTERFACE} ingress
tc qdisc delete dev ${CONTAINER_INTERFACE} root

Ощибки тут можо проигнорировать (если на самом деле не было настроено политик)

tc qdisc delete dev ${CONTAINER_INTERFACE} root
RTNETLINK answers: No such file or directory

Добавить корневые правила

tc qdisc add  dev ${CONTAINER_INTERFACE} ingress
tc qdisc add  dev ${CONTAINER_INTERFACE} root handle 1:0 htb default 3
tc filter add dev ${CONTAINER_INTERFACE} parent 1:0  protocol ip u32

Перенаправляем входящий / исходящий траффик на разные интерфейсы

tc filter add dev ${CONTAINER_INTERFACE} parent 1:     prio 1  protocol ip u32 match ip dst  192.168.250.3    action mirred egress redirect dev ifb0
tc filter add dev ${CONTAINER_INTERFACE} parent ffff:          protocol ip u32 match ip src  192.168.250.3    action mirred egress redirect dev ifb1

Проверка работы перенаправления

# tcpdump  -n -i ifb0
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on ifb0, link-type EN10MB (Ethernet), capture size 262144 bytes
^C12:08:26.032289 IP 192.168.255.5 > 192.168.250.3: ICMP echo request, id 12785, seq 21, length 64
12:08:27.033178 IP 192.168.255.5 > 192.168.250.3: ICMP echo request, id 12785, seq 22, length 64
# cpdump  -n -i ifb1
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on ifb1, link-type EN10MB (Ethernet), capture size 262144 bytes
^C12:08:33.140209 IP 192.168.250.3 > 192.168.255.5: ICMP echo reply, id 12785, seq 28, length 64
12:08:34.141523 IP 192.168.250.3 > 192.168.255.5: ICMP echo reply, id 12785, seq 29, length 64

Установка задержки

tc qdisc del dev ifb0 root
tc qdisc add dev ifb0 root netem delay 10ms
tc qdisc del dev ifb1 root
tc qdisc add dev ifb1 root netem delay 20ms