Linux docker shaper: Управление траффиком внутри контейнера: различия между версиями

Материал из noname.com.ua
Перейти к навигацииПерейти к поиску
Строка 102: Строка 102:
   
   
  +
===Поднять псквдоинтерфейсы==
 
 
<PRE>
 
<PRE>
 
ip link set up dev ifb0
 
ip link set up dev ifb0
Строка 109: Строка 109:
   
   
  +
Для простоты помещаем имя интерфейса на котором будем управлять трафикомв переменную окружения
 
 
<PRE>
 
<PRE>
 
export CONTAINER_INTERFACE="eth0"
 
export CONTAINER_INTERFACE="eth0"
 
</PRE>
 
</PRE>
   
  +
===Очистить существующие правила===
 
<PRE>
 
<PRE>
 
tc qdisc delete dev ${CONTAINER_INTERFACE} ingress
 
tc qdisc delete dev ${CONTAINER_INTERFACE} ingress
tc qdisc delete dev ${${CONTAINER_INTERFACE} root
+
tc qdisc delete dev ${CONTAINER_INTERFACE} root
 
</PRE>
 
</PRE>
  +
Ощибки тут можо проигнорировать (если на самом деле не было настроено политик)
  +
<PRE>
  +
tc qdisc delete dev ${CONTAINER_INTERFACE} root
  +
RTNETLINK answers: No such file or directory
  +
</PRE>
  +
  +
Добавить корневые правила
 
<PRE>
 
<PRE>
 
tc qdisc add dev ${CONTAINER_INTERFACE} ingress
 
tc qdisc add dev ${CONTAINER_INTERFACE} ingress
Строка 125: Строка 133:
 
tc filter add dev ${CONTAINER_INTERFACE} parent 1:0 protocol ip u32
 
tc filter add dev ${CONTAINER_INTERFACE} parent 1:0 protocol ip u32
 
</PRE>
 
</PRE>
  +
===Перенаправляем входящий / исходящий траффик на разные интерфейсы===
 
<PRE>
 
<PRE>
 
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 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
 
tc filter add dev ${CONTAINER_INTERFACE} parent ffff: protocol ip u32 match ip src 192.168.250.3 action mirred egress redirect dev ifb1
 
</PRE>
 
</PRE>
  +
  +
===Проверка работы перенаправления===
  +
<PRE>
  +
# 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
  +
</PRE>
  +
  +
<PRE>
  +
# 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
  +
</PRE>
  +
   
 
<PRE>
 
<PRE>

Версия 14:10, 12 марта 2020


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

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

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

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

В примере 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 500ms