简介

Calico 是一种容器之间互通的网络方案。在虚拟化平台中,比如OpenStack、Docker等都需要实现workloads之间互连,但同时也需要对容器做隔离控制,就像在Internet中的服务仅开放80端口、公有云的多租户一样,提供隔离和管控机制。而在多数的虚拟化平台实现中,通常都使用二层隔离技术来实现容器的网络,这些二层的技术有一些弊端,比如需要赖 VLAN、bridge 和隧道等技术,其中bridge 带来了复杂性,vlan 隔离和tunnel 隧道则消耗更多的资源并对物理环境有要求,随着网络规模的增大,整体会变得越加复杂。我们尝试把 Host 当作Internet 中的路由器,同样使用BGP同步路由,并使用iptables 来做安全访问策略,最终设计出了Calico 方案

适用场景:k8s环境中的pod之间需要隔离
设计思想:Calico不使用隧道或NAT来实现转发,而是巧妙的把所有二三层流量转换成三层流量,并通过host上路由配置完成跨Host转发

Calico架构

calico1

Calico网络模型主要工作组件:

  1. Felix:运行在每一台 Host 的 agent 进程,主要负责网络接口管理和监听、路由、ARP 管理、ACL 管理和同步、状态上报等

  2. etcd:分布式键值存储,主要负责网络元数据一致性,确保Calico网络状态的准确性,可以与kubernetes共用

  3. BGP Client(BIRD):Calico 为每一台 Host 部署一个 BGP Client,使用 BIRD 实现,BIRD 是一个单独的持续发展的项目,实现了众多动态路由协议比如 BGP、OSPF、RIP 等。在 Calico 的角色是监听 Host 上由 Felix 注入的路由信息,然后通过 BGP 协议广播告诉剩余 Host 节点,从而实现网络互通

  4. BGP Route Reflector:在大型网络规模中,如果仅仅使用 BGP client 形成 mesh 全网互联的方案就会导致规模限制,因为所有节点之间俩俩互联,需要 N^2 个连接,为了解决这个规模问题,可以采用 BGP 的 Router Reflector 的方法,使所有 BGP Client 仅与特定 RR 节点互联并做路由同步,从而大大减少连接数

Felix

Felix会监听ECTD中心的存储,从它获取事件,比如说用户在这台机器上加了一个IP,或者是创建了一个容器等。用户创建pod后,Felix负责将其网卡、IP、MAC都设置好,然后在内核的路由表里面写一条,注明这个IP应该到这张网卡。同样如果用户制定了隔离策略,Felix同样会将该策略创建到ACL中,以实现隔离

BIRD

BIRD是一个标准的路由程序,它会从内核里面获取哪一些IP的路由发生了变化,然后通过标准BGP的路由协议扩散到整个其他的宿主机上,让外界都知道这个IP在这里,你们路由的时候得到这里来

架构特点

由于Calico是一种纯三层的实现,因此可以避免与二层方案相关的数据包封装的操作,中间没有任何的NAT,没有任何的overlay,所以它的转发效率可能是所有方案中最高的,因为它的包直接走原生TCP/IP的协议栈,它的隔离也因为这个栈而变得好做。因为TCP/IP的协议栈提供了一整套的防火墙的规则,所以它可以通过IPTABLES的规则达到比较复杂的隔离逻辑

Calico网络两种模式

IPIP:从字面来理解,就是把一个IP数据包又套在一个IP包里,即把 IP 层封装到 IP 层的一个 tunnel。它的作用其实基本上就相当于一个基于IP层的网桥!一般来说,普通的网桥是基于mac层的,根本不需 IP,而这个 ipip 则是通过两端的路由做一个 tunnel,把两个本来不通的网络通过点对点连接起来。
BGP:边界网关协议(Border Gateway Protocol, BGP)是互联网上一个核心的去中心化自治路由协议。它通过维护IP路由表或‘前缀’表来实现自治系统(AS)之间的可达性,属于矢量路由协议。BGP不使用传统的内部网关协议(IGP)的指标,而使用基于路径、网络策略或规则集来决定路由。因此,它更适合被称为矢量性协议,而不是路由协议。BGP,通俗的讲就是讲接入到机房的多条线路(如电信、联通、移动等)融合为一体,实现多线单IP,BGP 机房的优点:服务器只需要设置一个IP地址,最佳访问路由是由网络上的骨干路由器根据路由跳数与其它技术指标来确定的,不会占用服务器的任何系统

IPIP模式

环境准备

一个msater节点,ip 172.171.5.95,一个node节点 ip 172.171.5.96
calicoipip1
创建一个daemonset的应用,pod1落在master节点上 ip地址为192.168.236.3,pod2落在node节点上 ip地址为192.168.190.203
calicoipip2
pod1 ping pod2
calicoipip3
pod1上的路由信息
calicoipip4
根据路由信息,ping 192.168.190.203,会匹配到第一条,第一条路由的意思是:去往任何网段的数据包都发往网管169.254.1.1,然后从eth0网卡发送出去,路由表中Flags标志的含义:
U up表示当前为启动状态
H host表示该路由为一个主机,多为达到数据包的路由
G Gateway 表示该路由是一个网关,如果没有说明目的地是直连的
D Dynamicaly 表示该路由是重定向报文修改
M 表示该路由已被重定向报文修改

master节点上的路由信息
calicoipip5
当ping包来到master节点上,会匹配到路由tunl0,该路由的意思是:去往192.169.190.192/26的网段的数据包都发往网关172.171.5.96,因为pod1在5.95,pod2在5.96,所以数据包就通过设备tunl0发往到node节点上
node节点上路由信息
calicoipip6
当node节点网卡收到数据包之后,发现发往的目的ip为192.168.190.203,于是匹配到红线的路由。该路由的意思是:192.168.190.203是本机直连设备,去往设备的数据包发往caliadce112d250,这个设备就是veth pair的一端。在创建pod2时calico会给pod2创建一个veth pair设备。一端是pod2的网卡,另一端就是我们看到的caliadce112d250。下面我们验证一下。在pod2中安装ethtool工具,然后使用ethtool -S eth0,查看veth pair另一端的设备号
calicoipip9
pod2 网卡另一端的设备好号是18,在node上查看编号为18的网络设备,可以发现该网络设备就是caliadce112d250
calicoipip9
所以,node上的路由,发送caliadce112d250的数据其实就是发送到pod2的网卡中
calicoipip16
查看一下pod2中的路由信息,发现该路由信息和pod1中是一样的
calicoipip8

在master网卡上抓包分析该过程
calicoipip10

calicoipip11

打开ICMP 285,pod1 ping pod2的数据包,能够看到该数据包一共5层,其中IP所在的网络层有两个,分别是pod之间的网络和主机之间的网络封装
calicoipip12
根据数据包的封装顺序,应该是在pod1 ping pod2的ICMP包外面多封装了一层主机之间的数据包
calicoipip13
两层IP封装的具体内容
calicoipip14

IPIP的连接方式

calicoipip15

BGP模式

在安装calico网络时,默认安装是IPIP网络,calico.yaml文件中,将CALICO_IPV4POOL_IPIP的值修改成 “off”,就能够替换成BGP网络

...
     -name: CALICO_IPV$POOL_IPIP
      value: off
...

对比IPIP

BGP网络相比较IPIP网络,最大的不同之处就是没有了隧道设备 tunl0。 前面介绍过IPIP网络pod之间的流量发送tunl0,然后tunl0发送对端设备。BGP网络中,pod之间的流量直接从网卡发送目的地,减少了tunl0这个环节

master节点上路由信息。从路由信息来看,没有tunl0设备
calicobgp1
同样创建一个daemonset,pod1在master节点上,pod2在node节点上
calicobgp2
pod1 ping pod2
calicobgp3
根据pod1中的路由信息,ping包通过eth0网卡发送到master节点上
master节点上路由信息。根据匹配到的 192.168.190.192 路由,该路由的意思是:去往网段192.168.190.192/26 的数据包,发送网段172.171.5.96,而5.96就是node节点,所以该数据包直接发送了5.96节点
calicobgp4
node节点上的路由信息。根据匹配到的192.168.190.192的路由,数据将发送给 cali6fcd7d1702e设备,该设备和上面分析的是一样,为pod2的veth pair 的一端,数据就直接发送给pod2的网卡
calicobgp5
当pod2对ping包做出回应之后,数据到达node节点上,匹配到192.168.236.0的路由,该路由说的是:去往网段192.168.236.0/26 的数据,发送给网关 172.171.5.95,数据包就直接通过网卡ens160,发送到master节点上
calicobgp6
通过在master节点上抓包,查看经过的流量,筛选出ICMP,找到pod1 ping pod2的数据包
calicobgp7
可以看到BGP网络下,没有使用IPIP模式,数据包是正常的封装
calicobgp8
值得注意的是mac地址的封装。192.168.236.0是pod1的ip,192.168.190.198是pod2的ip。而源mac地址是 master节点网卡的mac,目的mac是node节点的网卡的mac。这说明,在 master节点的路由接收到数据,重新构建数据包时,使用arp请求,将node节点的mac拿到,然后封装到数据链路层
calicobgp9

BGP的连接方式

calicobgp10

两种模式对比

IPIP网络

流量:tunlo设备封装数据,形成隧道,承载流量
适用网络类型:适用于互相访问的pod不在同一个网段中,跨网段访问的场景,外层封装的ip能够解决跨网段的路由问题
效率:流量需要tunl0设备封装,效率略低

BGP网络

流量:使用路由信息导向流量
适用网络类型:适用于互相访问的pod在同一个网段,适用于大型网络
效率:原生hostGW,效率高

Calico问题

  • 租户隔离问题

Calico的三层方案是直接在host上进行路由寻址,那么对于多租户如果使用同一个CIDR网络就面临着地址冲突的问题

  • 路由规模问题

通过路由规则可以看出,路由规模和pod分布有关,如果pod离散分布在host集群中,势必会产生较多的路由项

  • iptables 规则规模问题

1台Host上可能虚拟化十几或几十个容器实例,过多的iptables规则造成复杂性和不可调试性,同时也存在性能损耗

  • 跨子网时的网关路由问题

当对端网络不为二层可达时,需要通过三层路由机时,需要网关支持自定义路由配置,即pod的目的地址为本网段的网关地址,再由网关进行跨三层转发

文章作者: 鲜花的主人
版权声明: 本站所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 爱吃可爱多
Kubernetes Kubernetes
喜欢就支持一下吧
打赏
微信 微信
支付宝 支付宝