利用pipework与OVS构建跨主机容器网络

一、前言

本文提供了一种可行的、灵活的方案用于构建跨主机的Docker容器网络。鉴于目前的各类网络方案均依赖其他大型项目(比如CoreOS,Kubernetes)。本文的主旨就是抛开其他不必要的依赖,构建一个在大多数平台上都能运行的网络方案。

pipework,是由Docker的工程师Jérôme Petazzoni开发的一个Docker网络配置工具,由200多行shell代码写成,适合在多种不同的网络环境下配置容器网络,支持多种功能。github获取地址:https://github.com/jpetazzo/pipework

二、构建网络前的准备

1. 环境及软件版本信息:

Ubuntu 14.04 LTS x64
OpenvSwitch 2.3.0
Docker 1.4.1
Pipework
Bridge-utils
Nsenter

2. 安装必须的工具:

OpenvSwitch与Docker:(本文不再多论述它们的安装,请参考文末的参考资料。)

Pipework:

bridge-utils:

Nsenter:

配合Nsenter进入容器操作的脚本injec.py:

三、网络方案一

1. 目标拓扑:

网络方案 目标拓扑

如上图所示,共有4个节点,每个节点有internal address(用于服务器管理)、external address(用于外部访问),每个节点安装、启动一个OVS示例并创建两个网桥br0与br1(ip地址不是必须的)。节点上的OVS通过overlay连接,注意在构建环路之前先启用STP生成树协议。这样一来,同一广播域的容器节点都能在整个网络中通讯。

2. 实验:

在每个节点上创建所需的网桥:

注意:在相应的节点上创建隧道

创建host1至host2的GRE隧道(可以选择VXLAN)(在host1上执行)

创建host2至host1的GRE隧道:(在host2上执行)

创建host2至host3的GRE隧道:

创建host3至host2的GRE隧道:

创建host3至host4的GRE隧道:

创建host4至host3的GRE隧道:

创建host4至host1的GRE隧道:

创建host1至host4的GRE隧道:

3. 测试:

在host1上创建一个容器(使用ubuntu镜像):

在host2上创建一个不同广播域的容器:

在host3上创建与test1同广播域的容器:

在host3上创建另一个与test1同广播域的容器:

使用injec.py进入容器测试:

用ping操作验证相应的容器检测网络连通性:

使用inject.py进入test1后:

可以看到我们指定的设备eth1已经存在,而且拥有相应的IP地址。

测试连通性:

可以看到,ping不同广播域的test2是无法连通的。

ping其他的容器:

虽然有的容器并不在本地,但通过这个网络还是可以访问到他们。

4. 测试总结:

在这个网络中,通过设置GRE隧道,建立同一广播域的容器,不管在哪台主机上,都可以互相访问。无论是local to remote还是local to local都可以访问。

四、网络方案二

1. 目标拓扑:

网络方案二 目标拓扑

在这个网络图中,省略了linux bridge,直接把容器挂在ovs0上,这样可以支持vlan。至于ovs0之间的连接,我还是坚持使用了overlay的技术。如果要扩展为一个类似方案一的环状拓扑,请开启ovs的STP并手动建立GRE或VXLAN连接。

2. 实验:

在每台主机上创建ovs0网桥并配置好GRE隧道(host1和host2的IP地址参考方案一):

创建host1至host2的GRE隧道(可以选择VXLAN):(在host1上执行)

创建host2至host1的GRE隧道:(在host2上执行)

修改Pipework源码:

找到这一行:

换行添加一行代码(echo $LOCAL_IFNAME),结果如下:

3. 测试:

在host1上启动数个容器,设置vlan id:

在host2上启动数个容器,设置vlan id:

同样使用injec.py进入容器进行测试:

进入test1:

可以看到,只能ping通同一个vlan内同广播域的容器。

4. 测试总结:

这个方案提供了VLAN支持,修改pipework的原因是为了反馈容器加入ovs网桥的veth peer一头的信息。因为在该方案中,删除容器后,veth peer还有一头是记录在ovs中的,可以通过ovs-vsctl查看。但是它并没有提示该残留的veth属于哪个容器,因此通过pipework的反馈,用户可以用程序记录该值,方便以后的删除操作。

五、析疑

1. 关于Nsenter:Nsenter是util-linux包含的一个工具,安装完之后,可以这样访问:

原理就是获取指定容器的pid,然后再使用nsenter访问容器。CONT_NAME/ID可以填容器的名字或ID。这实现了docker attach的功能,当然,你也可以单纯使用docker attach进入容器。

2. 关于Pipework:
Q:如何在挂载容器到某个网桥时指定IP地址?
A:

不可以漏了掩码。

Q:如果要把容器挂载到多个网桥中,提示RTNETLINK answers: File exists,怎么解决?
A:你可以显式地指定挂载到网桥的设备名称。通过参数-i指定:

这里指定了一个设备eth1。

Q:在方案2中,怎样指定vlan id?
A:在掩码后加上@VLAN_ID

Q:有详细的使用文档吗?
A:有,见github:http://https://github.com/jpetazzo/pipework
或者参考这篇资料:http://http://www.infoq.com/cn/articles/docker-network-and-pipework-open-source-explanation-practice/

3. 关于方案1:
在方案1中,我使用了多个linux bridge。但实际上,多个bridge其实不是必须的,一个可能的优化是只建立一个linux bridge(无IP设置),挂载到ovs0上,可以把不同广播域的容器都挂载到网桥上,基本上不会发生冲突,只有同一个广播域的容器可以通讯。这样就可以不创建那么多网桥了。
另外,如果你要构建环状拓扑,一定要开启ovs的STP,否则会出现广播风暴问题。

4. 关于方案2:
在方案2中,容器直接挂载在ovs0上,因为docker会创建一个veth peer,它的一头放在容器中,另一头放在bridge中。pipework把veth peer的一头通过ovs-vsctl add-port添加至ovs0。如果你删除容器,veth peer的一头其实还会留在ovs0上,但你不清楚哪个才是属于你刚删除的容器的veth peer,因此你应该修改pipework,令它返回添加到ovs0上的那个veth peer,方便后续的管理工作。

5. 关于两种方案的共同问题:
这两个方案有一个共同的缺点:我还没找出能用的L3 router方案,在未来我会使用openflow重新做一个方案,克服这一缺陷。

如果你构建环状拓扑,环路无法通信,因为STP的原因,跨主机的网络会短暂中断。

方案中,我没有配置交换机的chunk口,而是直接用overlay技术。因为GRE和VXLAN的IP头增加,用户可能需要修改docker的设置,设置一个合适的MTU值,否则网络性能会很差。

两个方案中,我都没有修改本来的docker0网桥。这是因为考虑到外部访问的问题。常规的docker应用,在docker run时已经指定好要执行的命令,设置端口映射之类的操作。如果启动时设置--net=none,外部将无法通过端口访问容器提供的服务。pipework支持修改路由,在掩码后加@GATEWAY,可以使外部流量从新的设备经过,不再经过默认的eth0(即挂载在docker0上的设备),但明显这不是我们想要的结果。所以,在这个方案中,用户只需要以传统的方式启动容器,在需要时使用pipework挂载到不同的网桥上即可。对于服务发现这类需求,用户可以自行通过etcd这类工具实现。

pipework设置的内容将会在容器重启后丢失,但用户可以在容器启动后重新使用pipework设置。

六、总结

希望大家能从这些方案中找到灵感,寻找一个合适自己的网络方案。本人也正在自己的个人项目中应用这些方案。

参考资料

http://www.infoq.com/cn/articles/docker-network-and-pipework-open-source-explanation-practice/

https://github.com/jpetazzo/pipework

http://my.oschina.net/hochikong/blog/379354

http://blog.163.com/digoal%40126/blog/static/163877040201411602548445/

https://www.sdnlab.com/5889.html

ovs安装:https://www.sdnlab.com/3166.html

作者简介:
何智刚,2015至今,现为广东的一名在校高三学生,在学习之余,主要研究docker,OpenStack,SDN,对其领域都有所涉猎,目标是迈向full stack。


  • 本站原创文章仅代表作者观点,不代表SDNLAB立场。所有原创内容版权均属SDNLAB,欢迎大家转发分享。但未经授权,严禁任何媒体(平面媒体、网络媒体、自媒体等)以及微信公众号复制、转载、摘编或以其他方式进行使用,转载须注明来自 SDNLAB并附上本文链接。 本站中所有编译类文章仅用于学习和交流目的,编译工作遵照 CC 协议,如果有侵犯到您权益的地方,请及时联系我们。
  • 本文链接https://www.sdnlab.com/13111.html
分享到:
相关文章
条评论

登录后才可以评论

Hochikong 发表于15-08-17
0