本文主要梳理宿主机上容器之间通信的细节。

单台宿主机上,这些隔离的容器进程之间是如何通信的?

容器处于不同的网络命名空间,它们之间无法直接通信,而是利用了一种名为 Veth Pair 的虚拟设备,它就像一根网线,一头连在宿主机,一头连在容器中。宿主机上的那一头还被插在了 docker0 网桥上。docker0 相当于一个二层交换机的作用,所以容器之间的通信是依赖二层网络通信的。

通信的细节

container1: 172.17.0.2

container2: 172.17.0.3

1. 首先容器中有一条直接路由规则,如图。172.17.0.0 网段(这个网段是宿主机上容器 ip的网段)都走 eth0,也就是直接通过二层网络发送。

2. 我们知道 eth0 是一个 Veth 设备,它的另一头连着宿主机,就是它。 -w831

3. 而这个 vethe7a5a9f 实际上被插在了 docker0 这个网桥上(另外一个是另一个容器的)。 -w559

4. 由于是通过二层网络到达另一个容器,我们需要获得对方的 MAC 地址。怎么弄到呢?ARP 广播。docker0 作为二层交换机的角色,会将 ARP 广播转发到所有容器的虚拟网卡,然后我们就可以拿到 MAC 地址了。

5. 最后就可以愉快地通信啦。

总结一下数据流:

container1(eth0) --> container1 对应的 veth --> docker0 --> container2 对应的 veth --> container2(eth0)

问答部分

1. 如何找到容器和宿主机上 veth 设备的对应关系呢?

目前没有找到比较直接的办法,这个方法是需要进入容器的。

# 在宿主机上执行
ip link | grep veth

-w960

# 在 docker 中执行
cat /sys/class/net/eth0/iflink

-w340

都是 20,说明二者满足对应关系。