Я пытаюсь понять, как отслеживать пропускную способность, поступающую из контейнера 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