Назад | Перейти на главную страницу

Подсчет пропускной способности из контейнера Docker

Я пытаюсь понять, как отслеживать пропускную способность, поступающую из контейнера Docker.

Обычно я использую --uid-owner как отметка, чтобы отслеживать использование полосы пропускания для данного пользователя. Однако даже когда я запускаю все процессы в качестве пользователя внутри контейнера докеров --uid-owner не работает. Вместо того, чтобы использовать --uid-owner, Я попытался просто отслеживать все пакеты, исходящие от виртуального устройства Ethernet, созданного докером.

Однако это тоже ничего не дало: что бы я ни пытался, пакеты не перехватываются.

Из чистого отчаяния я попытался просто связать правила во всех цепочках, но безрезультатно.

Chain PREROUTING (policy ACCEPT 3041 packets, 7849454 bytes)
num      pkts      bytes target     prot opt in     out     source               destination
1           0        0 MARK       tcp  --  veth5a36 any     anywhere             anywhere             MARK set 0x1

Chain INPUT (policy ACCEPT 273 packets, 23305 bytes)
num      pkts      bytes target     prot opt in     out     source               destination
1           0        0 MARK       tcp  --  veth5a36 any     anywhere             anywhere             MARK set 0x1

Chain FORWARD (policy ACCEPT 2750 packets, 7821109 bytes)
num      pkts      bytes target     prot opt in     out     source               destination
1           0        0 MARK       tcp  --  any    veth5a36  anywhere             anywhere             MARK set 0x1
2           0        0 MARK       tcp  --  veth5a36 any     anywhere             anywhere             MARK set 0x1
3           0        0            all  --  veth5a36 eth0    anywhere             anywhere             mark match 0x1

Chain OUTPUT (policy ACCEPT 293 packets, 80020 bytes)
num      pkts      bytes target     prot opt in     out     source               destination
1           0        0 MARK       tcp  --  any    veth5a36  anywhere             anywhere             MARK set 0x1

Chain POSTROUTING (policy ACCEPT 3043 packets, 7901129 bytes)
num      pkts      bytes target     prot opt in     out     source               destination
1           0        0 MARK       tcp  --  any    veth5a36  anywhere             anywhere             MARK set 0x1

Кто-нибудь может сказать мне, как успешно помечать пакеты из контейнера докеров? Предпочтительно использовать --uid-owner но сейчас возьму все :)

Проблема связана с пространствами имен. Docker использует их для изоляции ресурсов, что также означает, что они не учитываются в общем количестве ресурсов хоста.

Когда ты бежишь iptables на хосте вы в основном смотрите только в пространство имен хоста, а интересующие вас пакеты сопоставляются с пространством имен контейнера. Чтобы обойти эту проблему, вы можете использовать ip netns чтобы по-прежнему запускать iptables на хосте, но в сетевом пространстве имен контейнера.

Первый, ip netns имеет несколько противоречивый интуитивный интерфейс. Чтобы присоединиться к пространству имен существующего процесса (в данном случае к вашему контейнеру), вы должны создать ссылку в /var/run/netns/ в пространство имен процесса:

# ln -sf /proc/`docker inspect -f '{{ .State.Pid }}' YOUR_CONTAINER`/ns/net /var/run/netns/SOME_NAME

(возможно, вам придется mkdir /var/run/netns)

Теперь вы можете запускать iptables в пространстве имен вашего контейнера:

# ip netns exec SOME_NAME iptables -L -nv

Обратите внимание, что это выводит набор правил iptables внутри контейнера, который, вероятно, будет пустым.

Если вы в настоящее время используете --uid-owner только для того, чтобы иметь счетчики для каждого пользователя, он вам больше не нужен, потому что в этом случае счетчики цепочки применяются только к контейнеру, и этого должно быть достаточно.

Наконец, вы можете очистить /var/run/netns.

Несколько контейнеров на пользователя

Если у вас есть несколько контейнеров на пользователя и вы хотите их подсчитать, вы можете запустить свои контейнеры с --net=container:OTHER_CONTAINER_FROM_USER, чтобы их пространства имен были объединены.

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

Если это недопустимое ограничение, вы можете подсчитать контейнеры по отдельности и позже сгруппировать их на основе uid.

Вы можете найти дополнительную информацию об этой проблеме Вот.

Не совсем то, что вы просили, но я полагаю, это выполнит свою работу.

Цитата из Блог Docker:

Счетчики уровня интерфейса

Поскольку каждый контейнер имеет виртуальный интерфейс Ethernet, вы можете напрямую проверить счетчики TX и RX этого интерфейса.

[...]

Но пока лучший способ - проверить метрики из контейнеров. Я не говорю о запуске специального агента в контейнере или о чем-то подобном. Мы собираемся запустить исполняемый файл из среды хоста, но в сетевом пространстве имен контейнера.

Точный формат команды:

ip netns exec <nsname> <command...>

Например:

ip netns exec mycontainer netstat -i