行至水穷处

坐看云起时

DOCKER容器跨宿主机通信方法-(3):Openvswitch

Openvswitch overlay网络:

配置前网络状况

主机1:

主机2:

主机1设置:

添加ovs—br0网桥:

ovs-vsctl add-br ovs-br0

连接ovs-br0到docker0交换机中:

brctl addif docker0 ovs-br0

ovs-br0中增加gre接口并向对端设置gre隧道:

ovs-vsctl add-port ovs-br0 gre1 — set interface gre1 type=gre option:remote_ip=172.16.199.27

相关输出

增加到目的docker0网络的路由,使其通过本机docker0:

增加前后路由对比

主机2设置:

添加ovs—br0网桥:

ovs-vsctl add-br ovs-br0

连接ovs-br0到docker0交换机中:

brctl addif docker0 ovs-br0

ovs-br0中增加gre接口并向对端设置gre隧道:

ovs-vsctl add-port ovs-br0 gre2 — set interface gre2 type=gre option:remote_ip=172.16.199.17

增加到目的docker0网络的路由,使其通过本机docker0:

ip route add 172.17.0.0/16 dev docker0

测试输出:

主机1上的busybox-1容器ping主机2容器IP:

主机2上busybox1容器ping主机1容器IP:

主机1相关输出:

主机2相关输出:

抓包分析:

可以看到,红色部分的外部IP包头,源mac和目的mac分别是两台主机的物理网卡mac

内层的以太网包头中,源mac是主机1的docker0 mac,目的mac是主机2上目标容器里mac

数据path拓扑:

可以想象为两台主机上的docker0被gre隧道虚拟直连起来。

此时在主机1中的docker容器内arp表:

可以看到在容器内目的地址172.27.0.1的mac实际上是主机2内docker0桥的mac,这里比较特殊,注意到实际抓包中,GRE内层以太网的目的mac却是主机2内的容器真实mac, 此时如果直接查看主机1本身的arp表,可以看到172.27.0.2(目的容器IP)的mac是真实目的容器的mac(经过docker0接口):

  1. 所以最终的实际数据路径:
    主机1内的容器1向主机2的容器2发送数据包,在源容器内,目的mac是主机2中的docker0的mac
  2. 数据包根据目的IP查找主机1的系统路由表,将数据发往主机1的docker0桥,
  3. 数据包流经主机的docker0后,源mac被修改为docker0的mac,目的mac被修改为目标容器的真实mac
  4. 由于docker0向外直接对联了ovs-br0网桥,数据包被发送到ovs-br0并执行GRE封装
  5. 数据包通过GRE隧道(实际流经主机的物理网卡,经由外部网络)到达对端host2
  6. 对端host2首先解封装GRE,获得内层以太网数据包,并根据目的mac将数据包送往主机的docker0,并最终发送给目标容器

注意:

上述两个主机内的容器不在同一个网段,如果在同一个网段(但ip不重叠)也是可以的,配置中只是无需指定目标路由那个配置了。

对于这种手工的openvswitch配置方式,如果有很多host,需要在每台上配置gre,并彼此形成full mesh结构,手工配置起来还是很复杂。因此实际上,可以通过一些第三方的解决方案来自动化这些事情,比如flannel网络模式

点赞

发表评论

电子邮件地址不会被公开。 必填项已用*标注