本文是数人云研发工程师向阳在DockOne微信群分享的直播实录,与大家一起探究Docker的网络方案。
随着容器的火热发展,数人云越来越多的客户对容器网络特性要求也开始越来越高,比如:
一容器一IP;
多主机容器互联;
网络隔离;
ACL;
对接SDN等等。
这次主要跟大家聊聊Docker的网络方案,首先是现有容器网络方案介绍, 接下来重点讲解Calico的特性及技术点,作为引申和对比再介绍下Contiv的特性,最后给出对比测试结果。
现有的主要Docker网络方案
首先简单介绍下现有的容器网络方案,网上也看了好多对比,大家之前都是基于实现方式来分,以下两个方案引自作者彭哲夫在DockOne的分享:
隧道方案
通过隧道,或者说Overlay Networking的方式:
Weave,UDP广播,本机建立新的BR,通过PCAP互通。
Open vSwitch(OVS),基于VxLAN和GRE协议,但是性能方面损失比较严重。
Flannel,UDP广播,VxLan。
隧道方案在IaaS层的网络中应用也比较多,大家共识是随着节点规模的增长复杂度会提升,而且出了网络问题跟踪起来比较麻烦,大规模集群情况下这是需要考虑的一个点。
路由方案
还有另外一类方式是通过路由来实现,比较典型的代表有:
Calico,基于BGP协议的路由方案,支持很细致的ACL控制,对混合云亲和度比较高。
Macvlan,从逻辑和Kernel层来看隔离性和性能最优的方案,基于二层隔离,所以需要二层路由器支持,大多数云服务商不支持,所以混合云上比较难以实现。
路由方案一般是从3层或者2层实现隔离和跨主机容器互通的,出了问题也很容易排查。
我觉得Docker 1.9以后再讨论容器网络方案,不仅要看实现方式,而且还要看网络模型的“站队”,比如说你到底是要用Docker原生的 “CNM”,还是CoreOS,谷歌主推的“CNI”。
Docker Libnetwork Container Network Model(CNM)阵营
Docker Swarm overlay
Macvlan IP network drivers
Calico
Contiv(from Cisco)
Docker Libnetwork的优势就是原生,而且和Docker容器生命周期结合紧密;缺点也可以理解为是原生,被Docker“绑架”。
Container Network Interface(CNI)阵营
Kubernetes
Weave
Macvlan
Flannel
Calico
Contiv
Mesos CNI
CNI的优势是兼容其他容器技术(e.g. rkt)及上层编排系统(Kuberneres Mesos),而且社区活跃势头迅猛,Kubernetes加上CoreOS主推;缺点是非Docker原生。
而且从上的也可以看出,有一些第三方的网络方案是“脚踏两只船”的, 我个人认为目前这个状态下也是合情理的事儿,但是长期来看是存在风险的,或者被淘汰,或者被收购。
Calico
接下来重点介绍Calico,原因是它在CNM和CNI两大阵营都扮演着比较重要的角色。即有着不俗的性能表现,提供了很好的隔离性,而且还有不错的ACL控制能力。
Calico是一个纯3层的数据中心网络方案,而且无缝集成像OpenStack这种IaaS云架构,能够提供可控的VM、容器、裸机之间的IP通信。
通过将整个互联网的可扩展IP网络原则压缩到数据中心级别,Calico在每一个计算节点利用Linux Kernel实现了一个高效的vRouter来负责数据转发,而每个vRouter通过BGP协议负责把自己上运行的workload的路由信息像整个Calico网络内传播——小规模部署可以直接互联,大规模下可通过指定的BGP route reflector来完成。
这样保证最终所有的workload之间的数据流量都是通过IP路由的方式完成互联的。
Calico节点组网可以直接利用数据中心的网络结构(无论是L2或者L3),不需要额外的NAT,隧道或者Overlay Network。
如上图所示,这样保证这个方案的简单可控,而且没有封包解包,节约CPU计算资源的同时,提高了整个网络的性能。
此外,Calico基于iptables还提供了丰富而灵活的网络Policy,保证通过各个节点上的ACLs来提供Workload的多租户隔离、安全组以及其他可达性限制等功能。
Calico架构
结合上面这张图,我们来过一遍Calico的核心组件:
Felix,Calico Agent,跑在每台需要运行Workload的节点上,主要负责配置路由及ACLs等信息来确保Endpoint的连通状态;
etcd,分布式键值存储,主要负责网络元数据一致性,确保Calico网络状态的准确性;
BGP Client(BIRD), 主要负责把Felix写入Kernel的路由信息分发到当前Calico网络,确保Workload间的通信的有效性;
BGP Route Reflector(BIRD),大规模部署时使用,摒弃所有节点互联的 mesh 模式,通过一个或者多个BGP Route Reflector来完成集中式的路由分发。
Calico Docker Network 核心概念
从这里开始我们将“站队” CNM,通过Calico Docker libnetwork plugin的方式来体验和讨论Calico容器网络方案。
先来看一下CNM模型:
从上图可以知道,CNM基于3个主要概念:
Sandbox,包含容器网络栈的配置,包括Interface,路由表及DNS配置,对应的实现如:Linux Network Namespace;一个Sandbox可以包含多个Network;
Endpoint,做为Sandbox接入Network的介质,对应的实现如:veth pair、TAP;一个Endpoint只能属于一个Network,也只能属于一个Sandbox;
Network,一组可以相互通信的Endpoints;对应的实现如:Linux bridge、VLAN;Network有大量Endpoint资源组成。
除此之外,CNM还需要依赖另外两个关键的对象来完成Docker的网络管理功能,他们分别是:
NetworkController,对外提供分配及管理网络的APIs,Docker Libnetwork支持多个活动的网络driver,NetworkController允许绑定特定的driver到指定的网络;
Driver,网络驱动对用户而言是不直接交互的,它通过插件式的接入来提供最终网络功能的实现;Driver(包括IPAM)负责一个Network的管理,包括资源分配和回收。
有了这些关键的概念和对象,配合Docker的生命周期,通过APIs就能完成管理容器网络的功能,具体的步骤和实现细节这里不展开讨论了, 有兴趣的可以移步 Github:https://github.com/docker/libnetwork/blob/master/docs/design.md。
接下来再介绍两个Calico的概念:
Pool,定义可用于Docker Network的IP资源范围,比如:10.0.0.0/8或者192.168.0.0/16;
Profile,定义Docker Network Policy的集合,由tags和rules组成;每个 Profile默认拥有一个和Profile名字相同的Tag,每个Profile可以有多个Tag,以List形式保存。
Profile样例:
Inbound rules:1 allow from tag WEB 2 allow tcp to ports 80,443Outbound rules:1 allow
Demo
基于上面的架构及核心概念,我们通过一个简单的例子,直观的感受下Calico的网络管理。
Calico以测试为目的集群搭建,步骤很简单,这里不展示了, 大家可以直接参考Github:https://github.com/projectcalico/calico-containers/blob/master/docs/calico-with-docker/docker-network-plugin/README.md。
这里默认已经有了Calico网络的集群,IP分别是:192.168.99.102和192.168.99.103。
calicoctl status截图:
同时,已经有两个IP Pool创建好,分别是:10.0.0.0/26和192.168.0.0/16。
calicoctl pool show截图:
当前集群也已经通过使用calico driver和IPAM创建了不同的Docker Network,本次Demo只需要使用DataMan。
Docker Network ls 截图:
calicoctl profile show截图:
下面我们使用DataMan这个网络,在两台slave机器上各启动一个容器:
数人云下发容器的Marathon json file:
{ "id": "/nginx-calico","cmd": null,"cpus": 0.1,"mem": 64,"disk": 0,"instances": 2,"container": {"type": "DOCKER","volumes": [],"docker": { "image": "nginx", "network": "HOST", "privileged": false, "parameters": [ { "key": "net", "value": "dataman" } ], "forcePullImage": false}},"portDefinitions": [{ "port": 10000, "protocol": "tcp", "labels": {}}]}
两台slave容器IP截图:
从上图可以看出,两个slave上的容器IP分别是:slave 10.0.0.48、slave2 192.168.115.193。
Slave容器连通性测试截图:
IP路由实现
根据上面这个Calico数据平面概念图,结合我们的例子,我们来看看Calico是如何实现跨主机互通的:
两台slave route截图:
对照两台slave的路由表,我们就知道,如果slave 1上的容器(10.0.0.48)想要发送数据到slave 2 上的容器(192.168.115.193), 那它就会match到最后一条路由规则,将数据包转发给slave 2(192.168.99.103),那整个数据流就是:
container - kernel - (cali2f0e)slave 1 - one or more hops - (192.168.99.103)slave 2 - kernel - (cali7d73)container
这样,跨主机的容期间通信就建立起来了,而且整个数据流中没有NAT、隧道,不涉及封包。
安全策略ACL
Calico的ACLs Profile主要依靠iptables和ipset来完成,提供的是可针对每个容器级别的规则定义。
具体的实现我们可以通过iptables命令查看对应的chain和filter规则, 这里我们就不展开讨论了。
Contiv
https://contiv.github.io
Contiv是Cisco开源出来的针对容器的基础架构,主要功能是提供基于Policy的网络和存储管理,是面向微服务的一种新基架。
Contiv能够和主流的容器编排系统整合,包括:Docker Swarm、Kubernetes、Mesos and Nomad。
如上图所示,Contiv比较“诱人”的一点就是,它的网络管理能力,既有L2(VLAN)、L3(BGP),又有 Overlay(VxLAN),而且还能对接Cisco自家的 SDN 产品 ACI。可以说有了它就可以无视底层的网络基础架构,向上层容器提供一致的虚拟网络了。
Contiv Netplugin特性
多租户网络混部在同一台主机上;
集成现有SDN方案;
能够和非容器环境兼容协作,不依赖物理网络具体细节;
即时生效的容器网络Policy/ACL/QoS规则。
网络方案性能对比测试
最后附上我们使用qperf做的简单性能测试结果,我们选取了vm-to-vm、host、calico-bgp、calico-ipip以及Swarm Overlay进行了对比。
其实Contiv也测试了,但是因为Contiv的测试环境和其他方案使用的不同,不具有直接可比性,所以没有放入对比图里。 直观感受就是基于OVS的方案确实不理想,后面有时间会统一环境继续进行测试对比,包括Contiv的L3/L2方案以及引入MacVLAN、Flannel等。
测试环境:VirtualBox VMs,OS:Centos 7.2,kernel 3.10,2 vCPU,2G Mem。
带宽对比结果如下:
时延对比结果如下:
qperf 命令:
# server 端$ qperf# client 端# 持续 10s 发送 64k 数据包,tcp_bw 表示带宽,tcp_lat 表示延迟$ qperf -m 64K -t 10 192.168.2.10 tcp_bw tcp_lat# 从 1 开始指数递增数据包大小$ qperf -oo msg_size:1:64k:*2 192.168.2.10 tcp_bw tcp_lat
总结
随着容器的落地,网络方案必将成为“兵家”必争之地,我们 数人云 是轻量级 PaaS 容器集群管理云平台,在网络方案选择上的考虑是:
性能,Calico和MacVLAN都有着不错的表现;Contiv L3(BGP)理论上性能也不会差;
普适性,Calico对底层的基本要求就是IP层可达;MacVLAN不适应于公有云;Contiv对底层的兼容性可能更好;
可编程性,保证整个网络管理过程能够程序化、API化,这样方便集成到产品里,不需要手动运维;Calico和Contiv都有相应的模块;
未来发展,这个就是我说的“站队”,Docker的CNM和CoreOS、Kubernetes的CNI,现在还看不清,Calico和Contiv都是支持的。
综上,个人推荐关注和尝试下Calico或者Contiv做为容器的网络方案,有问题或者收获,欢迎随时交流分享。
QA
Q:从你发的Marathon json文件来看,你们是对Mesos底层的网络做了扩展吗?容器网络通过”parameters”传递下去的吗?
A:就是利用Marathon支持的Docker parameters下发,等同于docker run —net dataman xxx。
Q:Felix根据配置的pool地址段配置路由,BGP Client通告路由?请问bgp的邻居关系是怎么建立的?是依靠etcd里的信息?
A:是的,Felix配置本地Kernel路由,BGP Client负责分发路由信息;BGP小规模部署采取mesh方式建立,所有节点互联n^2的联系,大规模部署推荐 部署一个或多个BGP route reflector,专门负责路由信息分发。
Q:请问在DataMan这个网络中路由信息是如何更新的?我们知道BGP是可以自己发现收敛网络的,那么在网络控制层面是如何设计的?
A:随着使用DatMan这个网络的容器的添加或者删除,Felix负责更新本地路由,BGP client 负责向外分发;Calico的BGP和广域网的BGP还是有不同,它只是使用private AS num,相对自治,网络控制层面都是可以程序控制的。
Q:请问Calico如何解决多租户里地址冲突的问题?
A:多租户容器混部在同一主机上时,所使用的Network最好不要用同一个Pool里的就好,这样就不可能有冲突了。
Q:如果集群的容器很多,那么相应的路由表的规则也会增多,这样会不会对网络性能造成影响?
A:网络性能不会有太大影响,因为容器多流量多网络压力本来就大,倒是会增加系统负载,毕竟要配置路由规则,同步网络信息;这部分我们也很关心,但还没有具体的测试结果。
Q:还有就是路由信息是存放在etcd中吗?如何保证路由表的读取性能和维护路由表的信息更新?
A:生效的路由肯定是本地的,Endpoint等信息是在etcd的;这两个问题都是Calico自身要解决的问题,这部分我们也很关心,但还没有具体的测试结果。
Q:Calico下跨多个路由hop的情况,中间路由不需要学习这么多的容器路由表吗?
A:不需要,中间过程是依赖节点之间原有的网络建设的,只要两个节点互通,所有的hop都不需要知道Calico内部的容器路由信息。
Q:还有一个问题,就是网络管理问题。目前从设备厂商网站看有几个支持VXLAN控制器的。这些控制器能不能与容器OVS协同? 目前来看我们这里买国外产品还是比较困难的。
A:这个肯定是问题,我觉得作为平台方,我们能做的很少,如果要改变,肯定是要SDN设备厂商发力,就像是各家都会去为OpenStack适配设备提供driver一样,但是也需要Docker或者说容器编排系统能做到如同OpenStack那样的行业标准级。
Q:Calico能和Flannel整合么,CoreOS上Kubelet里同时出现了Calico和Flannel?
A:Calico在DockerCon 2016应该是高调拥抱了Flannel,两个整合出了一个叫canal的项目,有兴趣可以去找找看。
Q:我想问一下老师,你这VXLAN的标签是Calico打的对吧?
A:Calico没有VXLAN,Calico的tag会对应到 ipset,iptables 用来 match filter规则。