欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

人人都能理解的 Calico-BGP 原则

最编程 2024-06-18 10:27:27
...

简介

Calico是一个纯三层的协议,为OpenStack虚机和Docker容器提供多主机间通信。Calico不使用重叠网络比如flannel和libnetwork重叠网络驱动,使用虚拟路由代替虚拟交换,每一台虚拟路由通过BGP协议传播可达信息(路由)到剩余数据中心。

Calico架构

架构图:

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

  • Felix:calico的核心组件,运行在每个节点上。主要的功能有接口管理、路由规则、ACL规则和状态报告,Felix会监听ECTD中心的存储,从它获取事件,比如说用户在这台机器上加了一个IP,或者是创建了一个容器等。用户创建pod后,Felix负责将其网卡、IP、MAC都设置好,然后在内核的路由表里面写一条,注明这个IP应该到这张网卡。同样如果用户制定了隔离策略,Felix同样会将该策略创建到ACL中,以实现隔离。

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

  • BGP Client(BIRD):Calico 为每一台 Host 部署一个 BGP Client,它的作用是将Felix的路由信息读入内核,并通过BGP协议在集群中分发。当Felix将路由插入到Linux内核FIB中时,BGP客户端将获取这些路由并将它们分发到部署中的其他节点。这可以确保在部署时有效地路由流量

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

  • Calicoctl:calico 命令行管理工具

架构特点

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

Calico 工作原理

Calico把每个操作系统的协议栈认为是一个路由器,然后把所有的容器认为是连在这个路由器上的网络终端,在路由器之间跑标准的路由协议——BGP的协议,然后让它们自己去学习这个网络拓扑该如何转发。所以Calico方案其实是一个纯三层的方案,也就是说让每台机器的协议栈的三层去确保两个容器,跨主机容器之间的三层连通性。

对于控制平面,它每个节点上会运行两个主要的程序,一个是Felix,它会监听ECTD中心的存储,从它获取事件,比如说用户在这台机器上加了一个IP,或者是分配了一个容器等。接着会在这台机器上创建出一个容器,并将其网卡、IP、MAC都设置好,然后在内核的路由表里面写一条,注明这个IP应该到这张网卡。绿色部分是一个标准的路由程序,它会从内核里面获取哪一些IP的路由发生了变化,然后通过标准BGP的路由协议扩散到整个其他的宿主机上,让外界都知道这个IP在这里,你们路由的时候得到这里来。

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

Calico是纯三层的SDN 实现,它基于BPG 协议和Linux自身的路由转发机制,不依赖特殊硬件,容器通信也不依赖iptables NAT或Tunnel 等技术

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地址,最佳访问路由是由网络上的骨干路由器根据路由跳数与其它技术指标来确定的,不会占用服务器的任何系统。

BGP 工作模式 


BGP是怎么工作的?

Calico 项目提供的 BGP 网络解决方案,与 Flannel 的 host-gw 模式几乎一样。也就是说,Calico也是基于路由表实现容器数据包转发,但不同于Flannel使用flanneld进程来维护路由信息的做法,而Calico项目使用BGP协议来自动维护整个集群的路由信息

修改配置

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

image-20220105171531663

和IPIP模式对比

BGP网络相比较IPIP网络,最大的不同之处就是没有隧道设备tunl0,pod之间的流量直接从·宿主机通过arp下一跳到目的地宿主机,减少了tunl0环节。

master节点上路由信息,从路由信息来看,没有tunl0设备。  image-20220106142858029 node上路由信息 image-20220106142843062

5.3 网络抓包测试

以其中2个pod为例展示,从A(10.244.123.135)【node01】pingB(10.244.140.64)【node02】

image-20220107101821262

进入pod地址为 10.244.123.135 kubectl exec -it myapp-deployment-79f56db86b-84pgs sh -n test123123

查看路由及ip addr

/ # ip route
default via 169.254.1.1 dev eth0 
169.254.1.1 dev eth0 scope link 
/ # ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
3: eth0@if34: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP 
    link/ether 22:e9:77:e0:ed:f0 brd ff:ff:ff:ff:ff:ff
    inet 10.244.123.135/32 scope global eth0
       valid_lft forever preferred_lft forever
/ # 

我们看到pod的eth0网卡的IP地址为10.244.123.135,veth pair的设备为if34,又因为该pod部署在node01,因此我们在node01主机通过匹配路由route -n|grep '10.244.123.135'找到的设备为cali52074d225a7,因此我们对cali52074d225a7设备抓包

该pod所在node节点上查看路由信息,重点关注这个网卡cali52074d225a7Flex默认会为分配到该node上的pod容器生成一条pod地址 calixxxx的路由信息

image-20220106143951841

我们在该node01上抓包tcpdump -i cali52074d225a7

# ping 10.244.140.64
PING 10.244.140.64 (10.244.140.64): 56 data bytes
64 bytes from 10.244.140.64: seq=0 ttl=62 time=1.184 ms
64 bytes from 10.244.140.64: seq=1 ttl=62 time=0.552 ms
^C
--- 10.244.140.64 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.552/0.868/1.184 ms
/ # 

image-20220106145335208

通过上面的抓包发现Ping的请求包源地址:10.244.123.135,目的地址为:10.244.140.64。 同时发送了两个ARP请求who-has 10.244.123.135 和who-has 169.254.1.1。

同时在node01的eth0(10.10.10.6)网卡上抓包: tcpdump -i eth0 -ne host 10.244.140.64

[root@WT-SAASMYSQL-10-6 ~]#tcpdump -i eth0 -ne host 10.244.140.64
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
10:05:01.065325 e2:17:1e:22:1a:43 > 9a:40:f3:72:9c:ab, ethertype IPv4 (0x0800), length 98: 10.244.123.135 > 10.244.140.64: ICMP echo request, id 7680, seq 0, length 64
10:05:01.066242 9a:40:f3:72:9c:ab > e2:17:1e:22:1a:43, ethertype IPv4 (0x0800), length 98: 10.244.140.64 > 10.244.123.135: ICMP echo reply, id 7680, seq 0, length 64

上面看到转包的源地址是10.244.123.135(源容器的IP地址),源MAC是e2:17:1e:22:1a:43,这个Mac地址就是 node01(10.10.10.6)主机的mac地址

上面看到转包的目的地址是10.244.123.135(目的容器的IP地址),目的MAC是9a:40:f3:72:9c:ab,这个Mac地址就是 node02(10.10.10.108)主机的mac地址

服务器发现要发到10.244.140.64,而10.244.140.64/26 via 10.10.10.108 dev eth0 proto bird指定的网关是10.10.10.108,广播找到10.10.10.108的mac地址是9a:40:f3:72:9c:ab,因此将数据包的目的mac地址改成9a:40:f3:72:9c:ab

image-20220107101003418

同时也在node02的eth0(10.10.10.108)网卡上抓包

[root@node02 ~]# tcpdump -i eth0 -ne host 10.244.140.64
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
10:05:13.908051 e2:17:1e:22:1a:43 > 9a:40:f3:72:9c:ab, ethertype IPv4 (0x0800), length 98: 10.244.123.135 > 10.244.140.64: ICMP echo request, id 7680, seq 0, length 64
10:05:13.908593 9a:40:f3:72:9c:ab > e2:17:1e:22:1a:43, ethertype IPv4 (0x0800), length 98: 10.244.140.64 > 10.244.123.135: ICMP echo reply, id 7680, seq 0, length 64


总结:两种网络对比

IPIP网络

流量:tunlo设备封装数据,形成隧道,承载流量。

适用网络类型:适用于互相访问的pod不在同一个网段中,跨网段访问的场景。外层封装的ip能够解决跨网段的路由问题。

效率:流量需要tunl0设备封装,效率略低

BGP网络

流量:使用路由信息导向流量

适用网络类型:适用于互相访问的pod在同一个网段,适用于大型网络。

效率:原生hostGW,效率高

存在问题 

(1) 缺点租户隔离问题

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

(2) 路由规模问题

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

(3) iptables 规则规模问题

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

(4) 跨子网时的网关路由问题

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

参考链接

cloud.tencent.com/developer/a…

www.asznl.com/post/85

cloud.tencent.com/developer/a…

推荐阅读