docker:如何轻松获得veth bridge接口对?

use*_*984 11 networking bridge docker

我有两个docker的集装箱,这样的桥梁:

root@venus-166:~# docker ps
CONTAINER ID        IMAGE                                         COMMAND                CREATED             STATUS              PORTS                      NAMES
ef99087167cb        images.docker.sae.sina.com.cn/ubuntu:latest   /bin/bash -c /home/c   2 days ago          Up 21 minutes       0.0.0.0:49240->22223/tcp   night_leve3         
c8a7b18ec20d        images.docker.sae.sina.com.cn/ubuntu:latest   /bin/bash -c /home/c   2 days ago          Up 54 minutes       0.0.0.0:49239->22223/tcp   night_leve2 

bridge name bridge id       STP enabled interfaces
docker0     8000.72b675c52895   no      vethRQOy1I
                            vethjKYWka
Run Code Online (Sandbox Code Playgroud)

我怎样才能获得哪个容器匹配veth*

ef99 => vethRQOy1I or ef99 => vethjKYWka
Run Code Online (Sandbox Code Playgroud)

// ------------------------------------------------ ----------

我知道它有效ethtool,但还有更好的方法吗?

Joe*_*ice 15

这是上面提到的ethtool技巧的变体,没有实际使用ethtool:

function veth_interface_for_container() {
  # Get the process ID for the container named ${1}:
  local pid=$(docker inspect -f '{{.State.Pid}}' "${1}")

  # Make the container's network namespace available to the ip-netns command:
  mkdir -p /var/run/netns
  ln -sf /proc/$pid/ns/net "/var/run/netns/${1}"

  # Get the interface index of the container's eth0:
  local index=$(ip netns exec "${1}" ip link show eth0 | head -n1 | sed s/:.*//)
  # Increment the index to determine the veth index, which we assume is
  # always one greater than the container's index:
  let index=index+1

  # Write the name of the veth interface to stdout:
  ip link show | grep "^${index}:" | sed "s/${index}: \(.*\):.*/\1/"

  # Clean up the netns symlink, since we don't need it anymore
  rm -f "/var/run/netns/${1}"
}
Run Code Online (Sandbox Code Playgroud)

  • 我似乎没有足够的声誉来评论"lxc.network.veth.pair"的答案,但我会注意到最近版本的Docker默认使用libcontainer而不是LXC,在这种情况下,任何选项都通过 - -lxc-conf被默默忽略. (3认同)

jpe*_*zzo 5

有多种"hackish"方法可以做到:

  • 扫描内核日志,如Jiri所述(但你必须在启动容器后立即执行,否则会变得混乱);
  • 检查容器中的接口计数器(发送/接收的数据包/字节),然后与主机中的接口进行比较,找到完全匹配的对(但是发送和接收方向被翻转);
  • 使用iptables LOG规则.

最后一个选择是,恕我直言,更可靠的(并且最容易使用),但它仍然非常hackish.这个想法很简单:

  1. 添加iptables规则以记录例如到达Docker网桥的ICMP流量:

    sudo iptables -I INPUT -i docker0 -p icmp -j LOG

  2. 将ping发送到要标识的容器:

    IPADDR=$(docker inspect -format='{{.NetworkSettings.IPAddress}}' 0c33)

    ping -c 1 $IPADDR

  3. 检查内核日志:

    dmesg | grep $IPADDR

    您将看到如下所示的行:

    […] IN=docker0 OUT= PHYSIN=vethv94jPK MAC=fe:2c:7f:2c:ab:3f:42:83:95:74:0b:8f:08:00 SRC=172.17.0.79 …

    如果你想要花哨,只需PHYSIN=…用awk或sed 提取.

  4. 删除iptables日志记录规则(除非您希望将其保留在那里,因为您将定期ping容器以识别它们).

如果您需要防弹版,则可以安装ulogd和使用ULOG目标.它不是将数据包标头写入内核日志,而是通过netlink套接字发送它们,然后用户程序可以正确处理它们.


Jir*_*iri 0

我不知道如何正确获取它,但是您使用了一个技巧:您可以在运行容器后扫描系统日志以获取添加的接口:

#!/bin/sh

JOB=$(sudo docker run -d ...)
sleep 1s
INTERFACE=$(grep "docker0: port" /var/log/syslog | tail -n 1 |  sed -r s/^.*\(veth[^\)]+\).*$/\\1/)
echo "job: $JOB interface: $INTERFACE"
Run Code Online (Sandbox Code Playgroud)