简单来说,实现docker跨主机容器间通信,常用的第三方网络方案是Flannel,Weave,Calico:
Flannel会为每个host分配一个subnet,容器从这个subnet中分配ip,这些ip可以在host间路由,容器间无需NAT和port mapping转发就可以实现跨主机通信。Flannel网络没有提供Docker DNS服务, 容器间不能通过hostname访问。
Weave对于容器来说,它就像是一个巨大的以太网交换机, 所有容器都被接入到这个交换机,同样容器间无需NAT和port mapping转发就可以实现跨主机通信。Weave网络提供了Docker DNS服务, 容器之间可以通过hostname访问。
Calico是一个纯三层的虚拟网络,它会为每个容器分配一个ip,每个host都是router,把不同host的容器连接起来,从而实现跨主机间容器通信。与vxlan不同的是,calico网络不对数据包进行额外封装,不需要NAT和端口映射,扩展性和 性能都很好。Calico网络提供了Docker DNS服务, 容器之间可以通过hostname访问。
以上三种网络方案区别:
1)从网络模型上来说
-> Flannel网络有两种模式:vxlan模式是一种overlay覆盖网络,而host-gw模式将主机作为网关,依赖于纯三层的ip转发;
-> Weave网络是一种overlay覆盖网络;
-> Calico网络也是一种纯三层的网络;
(overlay是基于vxlan的虚拟网络,可以将二层网络数据封装到UDP进行传输,在主机间建立vxlan虚拟隧道,实现跨主机容器之间通信)。
2)分布式存储(Distributed Store)
-> Flannel和Calico都需要分布式健值存储数据库(key-values),比如etcd或consul;
-> Weave自己负责在主机间交换网络配置信息,不需要etcd或consul这些数据库;
3)IP地址管理(IPAM)
-> Flannel为每个主机自动分配独立的subnet,用户只需要指定一个大的IP池。不同subnet之间的路由信息也由Flannel自动生成和配置。
-> Weave默认配置下所有容器使用10.32.0.0/12的subnet,如果此地址空间与现有IP冲突,则可以通过--ipalloc-range分配特定的subnet。
-> Calico通过IP Pool可以为每个主机定制自己的subnet。
4)网络连通和隔离
-> 不同Flannel网络中的容器可以直接通信,Flannel没有提供网络隔离。与外网通信可以通过bridge网络。
-> Weave网络默认配置下所有容器在一个大的subnet中,可以自由通信,如果要实现网络隔离,需要为容器指定不同的subnet或IP。若要与外网通信,则需要将主机加入到weave网络,并把主机当作网关。
-> Calico默认配置下只允许同一网络中的容器之间通信,但通过其强大的Policy能够实现几乎任意场景的访问控制。
一、Calico 基本介绍
Calico是一个纯三层的协议,为OpenStack虚机和Docker容器提供多主机间通信。Calico不使用重叠网络比如flannel和libnetwork重叠网络驱动,它是一个纯三层的方法,使用虚拟路由代替虚拟交换,每一台虚拟路由通过BGP协议传播可达信息(路由)到剩余数据中心。
二、Calico 结构组成
Calico不使用重叠网络比如flannel和libnetwork重叠网络驱动,它是一个纯三层的方法,使用虚拟路由代替虚拟交换,每一台虚拟路由通过BGP协议传播可达信息(路由)到剩余数据中心;Calico在每一个计算节点利用Linux Kernel实现了一个高效的vRouter来负责数据转发,而每个vRouter通过BGP协议负责把自己上运行的workload的路由信息像整个Calico网络内传播——小规模部署可以直接互联,大规模下可通过指定的BGP route reflector来完成。
结合上面这张图,我们来过一遍 Calico 的核心组件:
Felix: Calico agent,跑在每台需要运行 workload 的节点上,主要负责配置路由及 ACLs 等信息来确保 endpoint 的连通状态;
etcd:分布式键值存储,主要负责网络元数据一致性,确保 Calico 网络状态的准确性;
BGPClient(BIRD):主要负责把 Felix 写入 kernel 的路由信息分发到当前 Calico 网络,确保 workload 间的通信的有效性;
BGP Route Reflector(BIRD): 大规模部署时使用,摒弃所有节点互联的 mesh 模式,通过一个或者多个BGP Route Reflector来完成集中式的路由分发;
通过将整个互联网的可扩展 IP 网络原则压缩到数据中心级别,Calico 在每一个计算节点利用Linux kernel实现了一个高效的vRouter来负责数据转发而每个vRouter通过BGP
协议负责把自己上运行的 workload 的路由信息像整个 Calico 网络内传播 - 小规模部署可以直接互联,大规模下可通过指定的BGP route reflector 来完成。这样保证最终所有的 workload 之间的数据流量都是通过 IP 包的方式完成互联的。
三、Calico 工作原理
Calico把每个操作系统的协议栈认为是一个路由器,然后把所有的容器认为是连在这个路由器上的网络终端,在路由器之间跑标准的路由协议——BGP的协议,然后让它们自己去学习这个网络拓扑该如何转发。所以Calico方案其实是一个纯三层的方案,也就是说让每台机器的协议栈的三层去确保两个容器,跨主机容器之间的三层连通性。
对于控制平面,它每个节点上会运行两个主要的程序,一个是Felix,它会监听ECTD中心的存储,从它获取事件,比如说用户在这台机器上加了一个IP,或者是分配了一个容器等。接着会在这台机器上创建出一个容器,并将其网卡、IP、MAC都设置好,然后在内核的路由表里面写一条,注明这个IP应该到这张网卡。绿色部分是一个标准的路由程序,它会从内核里面获取哪一些IP的路由发生了变化,然后通过标准BGP的路由协议扩散到整个其他的宿主机上,让外界都知道这个IP在这里,你们路由的时候得到这里来。
由于Calico是一种纯三层的实现,因此可以避免与二层方案相关的数据包封装的操作,中间没有任何的NAT,没有任何的overlay,所以它的转发效率可能是所有方案中最高的,因为它的包直接走原生TCP/IP的协议栈,它的隔离也因为这个栈而变得好做。因为TCP/IP的协议栈提供了一整套的防火墙的规则,所以它可以通过IPTABLES的规则达到比较复杂的隔离逻辑。
Calico节点组网可以直接利用数据中心的网络结构(支持 L2 或者 L3),不需要额外的 NAT,隧道或者 VXLAN overlay network。
如上图所示,这样保证这个方案的简单可控,而且没有封包解包,节约 CPU 计算资源的同时,提高了整个网络的性能。此外,Calico 基于 iptables 还提供了丰富而灵活的网络 policy, 保证通过各个节点上的 ACLs 来提供 workload 的多租户隔离、安全组以及其他可达性限制等功能。
四、Calico网络方式(两种)
1)IPIP
从字面来理解,就是把一个IP数据包又套在一个IP包里,即把 IP 层封装到 IP 层的一个 tunnel,看起来似乎是浪费,实则不然。它的作用其实基本上就相当于一个基于IP层的网桥!一般来说,普通的网桥是基于mac层的,根本不需 IP,而这个 ipip 则是通过两端的路由做一个 tunnel,把两个本来不通的网络通过点对点连接起来。ipip 的源代码在内核 net/ipv4/ipip.c 中可以找到。
2)BGP
边界网关协议(Border Gateway Protocol, BGP)是互联网上一个核心的去中心化自治路由协议。它通过维护IP路由表或‘前缀’表来实现自治系统(AS)之间的可达性,属于矢量路由协议。BGP不使用传统的内部网关协议(IGP)的指标,而使用基于路径、网络策略或规则集来决定路由。因此,它更适合被称为矢量性协议,而不是路由协议。BGP,通俗的讲就是讲接入到机房的多条线路(如电信、联通、移动等)融合为一体,实现多线单IP,BGP 机房的优点:服务器只需要设置一个IP地址,最佳访问路由是由网络上的骨干路由器根据路由跳数与其它技术指标来确定的,不会占用服务器的任何系统。
BGP工作模式:
bgp工作模式和flannel的host-gw模式几乎一样;
bird是bgd的客户端,与集群中其它节点的bird进行通信,以便于交换各自的路由信息;
随着节点数量N的增加,这些路由规则将会以指数级的规模快速增长,给集群本身网络带来巨大压力,官方建议小于100个节点;
限制:和flannel的host-gw限制一样,要求物理机在二层是连能的,不能跨网段;
Route Reflector模式:
在更大规模的集群中,需要通过Route Reflector模式专门创建一个或者几个专门的节点,负责跟所有的BGP客户端建立连接,从而学全全局的路由规则;
而其它节点,只需要跟这几个专门的节点交换路由信息,就可以获得整整个集群的路由信息
IPIP模式:
场景:用在跨网段通信的情况下,bgp模式在跨网段的场景将不能工作;
tunl0:创建的虚拟网卡设备,此时的作用就和flannel的VxLAN工作模式类似(此处的tunl0不是flannel的UDP模式中的tun0)
calico cross-subnet
ipip虽然实现了 calico 跨网段通信,但对于相同网段间的主机通信来说,IP-in-IP 就有点多余了,因为二者宿主机处于同一广播域,2层互通,直接走主机路由即可。此时需要借助calico cross-subnet
$ calicoctl apply -f - << EOF apiVersion: v1 kind: ipPool metadata: cidr: 192.168.0.0/16 spec: ipip: enabled: true mode: cross-subnet nat-outgoing: true EOF 上述描述出自https://www.cnblogs.com/zqliu8/p/11605839.html
五、Calico网络通信模型
calico是纯三层的SDN 实现,它基于BPG 协议和Linux自身的路由转发机制,不依赖特殊硬件,容器通信也不依赖iptables NAT或Tunnel 等技术。
能够方便的部署在物理服务器、虚拟机(如 OpenStack)或者容器环境下。同时calico自带的基于iptables的ACL管理组件非常灵活,能够满足比较复杂的安全隔离需求。
在主机网络拓扑的组织上,calico的理念与weave类似,都是在主机上启动虚拟机路由器,将每个主机作为路由器使用,组成互联互通的网络拓扑。当安装了calico的主机组成集群后,其拓扑如下图所示:
每个主机上都部署了calico/node作为虚拟路由器,并且可以通过calico将宿主机组织成任意的拓扑集群。当集群中的容器需要与外界通信时,就可以通过BGP协议将网关物理路由器加入到集群中,使外界可以直接访问容器IP,而不需要做任何NAT之类的复杂操作。
当容器通过calico进行跨主机通信时,其网络通信模型如下图所示:
从上图可以看出,当容器创建时,calico为容器生成veth pair,一端作为容器网卡加入到容器的网络命名空间,并设置IP和掩码,一端直接暴露在宿主机上,
并通过设置路由规则,将容器IP暴露到宿主机的通信路由上。于此同时,calico为每个主机分配了一段子网作为容器可分配的IP范围,这样就可以根据子网的
CIDR为每个主机生成比较固定的路由规则。
当容器需要跨主机通信时,主要经过下面的简单步骤:
- 容器流量通过veth pair到达宿主机的网络命名空间上。
- 根据容器要访问的IP所在的子网CIDR和主机上的路由规则,找到下一跳要到达的宿主机IP。
- 流量到达下一跳的宿主机后,根据当前宿主机上的路由规则,直接到达对端容器的veth pair插在宿主机的一端,最终进入容器。
从上面的通信过程来看,跨主机通信时,整个通信路径完全没有使用NAT或者UDP封装,性能上的损耗确实比较低。但正式由于calico的通信机制是完全基于三层的,这种机制也带来了一些缺陷,例如:
- calico目前只支持TCP、UDP、ICMP、ICMPv6协议,如果使用其他四层协议(例如NetBIOS协议),建议使用weave、原生overlay等其他overlay网络实现。
- 基于三层实现通信,在二层上没有任何加密包装,因此只能在私有的可靠网络上使用。
- 流量隔离基于iptables实现,并且从etcd中获取需要生成的隔离规则,有一些性能上的隐患。
上述出自链接:https://blog.csdn.net/tony_vip/java/article/details/102957330
Calico on Kubernetes 从入门到精通
参考链接https://blog.csdn.net/watermelonbig/article/details/84981945