使用 OVS 打通多节点上的容器通信(Underlay)

概述

在上一篇文章中,提到了怎么使用 OVS 构建 Overlay 网络的问题。那么这一篇中,主要会研究 Underlay 网络。关于 Overlay 和 Underlay 网络的区别,已经有很多文章详细阐述了。

使用 underlay 网络,最大的特点就是容器和 vm 会在同一个网络下,这样容器和 vm 之间是可以直接通信的。因此我们可以大概猜测出,一个 underlay 网络下,容器和 vm 之间都应该通过交换机进行连接。因此我们可以得出下面的网络拓扑图:

图1 underlay 网络示意图

下面,我们就来实际操作一下,构建出一个这样的 underlay 网络。实验环境如下:

  • 物理机: 操作系统 ubuntu 19.10, open vSwitch 2.12.0

  • 虚拟机: centos/7,内核 4.3.3,open vSwitch 2.5.9

虚拟机的 vagrantfile 可以用下面的:

因为设备问题,我没有办法用两台 Host 去组件整个网络,因此这里的目标就是只实现这一部分,并且只会启动两台虚拟机,其余的原理也是一样:

准备 Host 环境

Host 环境上主要是要通过 Open vSwitch 创建一个虚拟交换机,并且有两个 internal 类型的 port 供虚拟机接入。命令如下:

现在,我们就准备好了 Host 的环境。下面我们使用 vagrant 启动虚拟机,提示选择桥接网络的时候,记得选择桥接 tap0 和 tap1,这样,虚拟机就连上了 vSwitch。

准备虚拟机环境

首先,启动在虚拟机上的 ovsdb-server 和 ovs-vswitchd:

然后创建虚拟交换机,并且将虚拟机的网卡也接入该交换机:

下面我们启动一个容器 c1,并且通过 veth pair 接入到虚拟交换机上。

为了让 192.168.3.0/24 的流量都通过 br0 交换机,我们还要修改一下路由表,比如我这里默认的路由表规则如下:

删除并重新创建:

这个时候,我们可以测试一下,虚拟机到容器 c1 是否能够直接通信:

再测试一下宿主机到容器的通信

再测试一下容器到宿主机之间的通信:

这里其实有个比较容器忽略的地方(对于我来说),就是虚拟机的网卡需要打开混杂(promiscuous) 模式。不然当流向 192.168.3.21 的包进到虚拟机的时候,虚拟机网卡发现 mac 地址不是自己的,就会直接抛弃。这个模式我是在上面提供的 Vagrantfile 中打开了。如果实验的时候发现有问题,可以往这个方向多多考虑。接着,我们用同样的方式启动第二台虚拟机即可。

最后测试两台vm上容器和容器之间的通信:

这样,我们整个网络已经构建完毕,但是这里还有个问题,会出现数据包重复的现象,比如我从 vm0 到 vm1,vm0 会重复发送两次,vm1 会重复响应两次:

也就是虚拟机到宿主机到包会重复。但是如果使用 ovs-tcpdump 来抓包,则不会出现这个问题。我能给出的解释是:因为 vm 和 host 在同一个底层的网络协议上,所以一个包会出现两次。

Last updated

Was this helpful?