注:本篇仅仅是对各个网络方案的简介和思考。须要深刻学习如何部署和使用的同窗请自行度娘~docker
docker的使用者十分普遍,不止有网易蜂巢,daocloud,时速云这类的已经成熟化的公有云服务,许多中小型企业内部也在试图将docker容器应用到内部的运维工做中。网络
在成熟的容器服务架构中,每每会依赖IaaS层去实现更好的隔离效果,一个很明显的例子就是网络的连通性和隔离性。许多企业使用neutron做为这方面的支持而且能得到不错的效果。架构
而中小型企业内部,甚至一些我的用户的docker环境就不多考虑租户隔离了,连通性和性能是这类用户的至高需求。
好比下面这段对话:
“咱们部门这套业务是基于dubbo的架构来开发的,如今其中的服务A要放大家容器环境里面跑。”
“能够啊,来来来,我帮你打镜像,我帮你跑,要几个实例?OK没问题。”
“大家容器集群里的服务,咱们的dubbo注册中心都访问不到啊!搞什么鬼?”
“很差意思很差意思,咱们的容器IP是虚拟的IP,你无法主动访问咱们的。不过咱们用了k8s,能够把整个服务以一个IP:port的形式提供给注册中心,你看咱们还帮大家作了负载均衡。”
“咱们不须要大家帮咱们作负载均衡,咱们就想把容器当虚拟机同样用嘛~”
“这...”负载均衡
实际上,对于每个初步接触docker的人来讲,网络是绝对的痛点,要搭建一套能让容器跨机器的集群,是玩转容器,建设CaaS的第一步。这里简单介绍一下几种使用较为广泛的容器网络方案,并详细讲述笔者在“远古时期”的网络方案解决思路。运维
容器直接使用宿主机的网络配置,包括网卡,路由等,这种方案下,从网络层面来看,容器就不是容器了,只是一个宿主机上的进程(端口)而已。
使用这种模式的性能损耗最少(直接用宿主机的网卡,能有什么损耗)。可是除非在容器中咱们作好端口的自动化配置,不然端口被占用了,容器就启动不了。分布式
flannel已经日趋成熟,从本来的udp,vxlan支持,到后来的aws,host-gw,gce网络。这里主要说udp,vxlan,host-gw。
udp和vxlan在flannel中其实只是封装协议的不一样而已。笔者了解很少,不敢多作解释,不过这两种方式的性能实际上是差很少的(不少人会以为vxlan性能更好)。flannel实现的是一个三层网络。可是udp,vxlan协议是经过隧道方式进行跨机互联,简单地说就是:
容器a的数据包pkg->宿主机A的docker0->路由到宿主机A的flannel0网卡->被封装->宿主机A的物理网卡->宿主机B的物理网卡->路由到宿主机B的flannel0网卡->被解封->经过暴露出来的目的容器IP找到docker0->docker0转给容器的虚拟网卡微服务
封装解封的过程致使flannel会有20-30%的损耗。工具
host-gw是一个比较新鲜的方式,在slaver节点属于同一个二层网络,且能够自由配置slaver节点网络的前提下,咱们使用host-gw,会使得slaver节点上建立出一系列路由规则,经过这套路由规则,将容器发出的数据包转发给相应的机器。这种模式性能会更好。
flannel的主要缺点在于,既没有租户隔离(即:一套环境里,每个容器均可以访问到其余任何容器),也没有对外开放(集群外没有搭建flannel的机器ping不通容器)。性能
calico是一种容器级路由和防火墙工具,它可以在容器级别上为每一个容器实例或k8s的Pod实例指定访问规则,达到服务间可控的访问。
Calico的原理是经过修改每一个主机节点上的iptables和路由表规则,实现容器间数据路由和访问控制,并经过Etcd协调节点配置信息的。所以Calico服务自己和许多分布式服务同样,须要运行在集群的每个节点上。
calico已经并入了k8s的CNI插件。在每个slaver节点上启动一个calico容器,去劫持docker的建立命令,接管容器网络的配置。
calico吸引人的地方在于:他有一套本身的管理体系,给不一样的子网络增长了标签,能够经过这种方式实现容器网络的隔离;同时业内认为他的性能也是很好的,基本接近裸机的网络性能,然而笔者在本身的环境中测试了几回,效果并不尽如人意,。学习
接下来讲下桥接+IPAM模式。这个方案针对的是一种比较特殊的使用场景:
docker有许多用法,微服务是其中一种,经过docker技术圈内爱好者的交流,咱们了解到确实有一些企业试图,或者已经将容器当作虚拟机在用。上文中的对话就是这个使用场景之一,这种场景下的网络问题总结为:同一个网络环境中的机器里,非docker机器主动链接docker机器上的容器是连不通的。
解决方法:
1.给这个网络环境中非docker的机器也部署虚拟网络,将flannel,calico这类组件在全网络范围内作分布式的部署。(考虑到机器数量,可能存在的VM,VM会有起停操做,这个方案基本不可行)
2.给容器一个和宿主机器同一层网络的IP,即二层网络IP,路由到宿主机的物理网卡,进行转发。
咱们知道docker1.9之后增长了network特性,docker daemon能够本身建立一个network,经过选择network给容器配置网络。
在二层网络的基础上,咱们在宿主机创建一个网桥,桥接了物理网卡和docker network(固然了type必须是bridge)。设置好路由规则和gateway,docker容器建立时桥接到相应的network上,就能够正常地访问二层网络内的任何机器/容器。
一样的,由于这种方式下容器建立后IP是一个二层网络内的IP,因此外部机器能够很方便地访问容器。这是一种全暴露的网络模式。作到了彻底的连通,但没办法作到网络的隔离。
那IPAM又是什么鬼?
假设这种状况:桥接模式下,容器和宿主机是同一个网段,好比172.16.1.0/24,假设该网段中的.1~.10都是宿主机,咱们在.1的宿主机上建立的容器,其IP一定是172.16.1.2,172.16.1.3,...会发现容器的IP和宿主机重复了。这就麻烦了,要么咱们就连不上容器,要么咱们就连不上IP为172.16.1.2的宿主机。(简单地说下缘由:每一个宿主机彼此并不知悉对方的IP和MAC信息,咱们建立的那个网桥也没有这方面的记录,容器启动时,网桥上已经记录了本机的IP:172.16.1.1,但没有记录172.16.1.2,因此就会给容器分配172.16.1.2这个IP)
那就开发一个服务用于管理IP吧,docker原生支持network plugin,其中一个插件就是IPAM,即ip分配管理服务。docker network建立/销毁容器时会使用IPAM去申请/释放一个合法的IP。若是没有指定IPAM插件,docker daemon会自动配置的网段中选一个IP,其逻辑是按数字从小到大进行分配。
咱们开发一个IPAM,经过IPAM来进行IP的申请和释放,并在整个集群中创建一个IP的管理中心,维护整个容器集群的IP资源。保证一个IP只能同时被最多一个容器使用。
这种方案的性能看起来应该是和flannel host-gw,calico差很少的,由于其本质仍是路由转发,不一样之处是给容器分配了二层网络IP,全部容器都暴露了,所以这种模式下网络就难以作租户隔离(容器更像一个瘦VM了~),而这种状况下,dubbo的服务能够直接在容器上部署,k8s的service特性,kube-proxy组件基本能够酌情弃用。
综上所述:
展望:calico可能会是最适合容器云的网络方案,由于租户的网络隔离是生产化过程当中绝对不可缺乏的。若是仅在内部小规模使用,追求简单配置,可使用flannel,若是将容器vm化,能够考虑使用桥接+ipam。