Calico学习:实现原理
文章目录
Calico 组网方式
Calico提供了一种纯三层的网络模型,任意两个Pod都是基于IP地址进行通信,不存在Pod在同一子网,通过二层交换数据的情形。
Calico网络有以下特点,在Pod的网络命名空间,可以看到:
- Pod在独立的子网中,IP为xx.xx.xx.xx/32
- Pod的默认路由指向一个虚拟地址169.254.1.1
在宿主机的网络命名空间中,可以看到:
- 宿主机上没有网桥设备,veth的一端直接暴露在宿主机上
- Pod在宿主机有一条独立的路由记录,报文到达宿主机后根据目的地址直接从veth进入容器
calico将IPPool地址池划分为多个子网,并分配给每台主机。但是每台主机上的veth没有在宿主机上接入网桥或者虚拟交换机中,Pod之间没有打通二层网络。 子网只是作为划分路由信息的依据,并且用户可以通过nodeSelect对子网进行非常灵活的划分。
以下是某个Kubernetes节点上的路由信息:
假设veth0和veth1是一对veth pair,分别位于Pod网络命名空间和宿主机网络命名空间。
Calico为了让veth0发出的报文能够在宿主机网络命名空间中被正确路由,利用了veth1的Proxy ARP功能。Proxy ARP能够让veth1响应针对本网络不存在的IP地址的ARP查询,并以自己的MAC地址进行响应。当veth1收到169.254.1.1的ARP请求时会向veth0回复一个虚假的MAC地址,veth0收到ARP回复后将报文发出。在宿主机网络中veth1接受到报文后,会根据报文目的地址以及宿主机上的路由表,再将报文转发到其他网卡中。
由于veth两端是直通的,因此网关地址169.254.1.1以及响应的MAC可以是任意值。
通 ip neigh 可以查看主机的arp缓存
开启网络设备的Proxy ARP echo 1 » /proc/sys/net/ipv4/conf/<设备名称>/proxy_arp
BGP 协议
Calico 作为一个纯三层的网络插件,其核心在于每个Node上拥有整个集群的完整路由信息,而这一能力正是基于BGP协议实现的。
BGP全称是Border Gateway Protocol,对应中文是边界网关协议,是当今互联网中最为核心的去中心化自治路由协议。
关于路由协议,包括以下几个概念:
- AS:自治系统,即一个独立的整体网络,每个AS都有自己唯一的编号(在互联网场景中,每个AS的编号都是需要专门申请的,全球唯一)。
- IGP:内部网关协议。IGP是用在AS内部的一种路由协议。AS内部可能并非2层互通,而是包含了多个路由器。在这种情形下,AS内部可以借助IGP协议实现网络互通。常见的IGP协议包括:RIP和OSPF。
- EGP:外部网关协议,在多个AS之间使用的一种路由协议。BGP是当前最新的EGP协议!
虽然BGP是为了替代EGP而创建的,但是他同样可以应用在AS内部。因此BGP包括:
- IBGP
- EBGP
BGP是一种路径矢量协议。在应用BGP的网络中,若干台运行的着BGP服务的设备构成网络拓扑。可以将拓扑中每个BGP服务角色称为BGP Router,而与BGP Router连接的对端叫BGP peer。
BGP Router 主要完成以下工作:
- 每个BGP Router会接受对端发来的路由信息,并根据本地的Policy对路由信息进行合并、筛选并存储到本地BGP路由表中或者同步这些信息到主机的主路由表中。
- BGP Router还会修改收到的路由信息,将自己加入到信息中,并对其他BGP Peer发送。
BGP协议使用TCP作为数据传输层,默认端口号为179。
BGP是应用在互联网场景的标准协议,为了将其运用在数据中心或者Kubernetes中,Calico、OpenStack等开源项目实际上对其作出了相当多的修改和优化。
当前BGP的开源实现包括:
- bird / projectcalico/bird
- FRRouting
- OpenBGPD
- XORP
- Quagga
- osrg/gobgp :golang实现的BGP协议
BGP in the Data Center:https://www.oreilly.com/library/view/bgp-in-the/9781491983416/
中文翻译:https://arthurchiao.art/blog/bgp-in-data-center-zh/
BIRD
Kubernetes部署Calico时,会在Node节点部署以下三个进程:
- BIRD:一个守护进程,它使用 BGP 协议将路由信息分发到其他节点
- Felix:监视 Felix 数据存储,构建POD的路由信息,并配置当前节点的Iptables或者IPVS
- Confd:监视 Calico 数据存储以获取配置更改,并更新 BIRD 配置文件
BIRD是一款可运行在Linux和其他类Unix系统上的路由软件,它实现了包括BGP、OSPF、RIP在内的多种路由协议,是Calico中最核心组件。
关于BIRD一些简单介绍可以参考:https://blog.csdn.net/alex_yangchuansheng/article/details/116810677?spm=1001.2014.3001.5501
Calico/Node容器集成了bird客户端birdcl,使用该工具我们可以查看对应节点的bird运行状态。
BGP Peer
默认情况下Calico工作在IBGP模式中,并且在IBGP Peer中学习到的路由信息不会再次被转发(BGP协议为了避免在AS内部出现环路),因此默认情况下Calico工作在nodeToNodeMesh模式中,所有Node之间两两形成Peer,以此来收集集群的完整路由信息。
通过以下命令,可以查看当前Peer的连接状态
|
|
输出如下:
|
|
BGP Speaker RR模式
NodeMesh模式下,网络中BGP总连接数是按照O(n^2)增长的,有太多Kubernetes节点时会消耗大量的连接。因此在大集群中通常使用BGP Speaker RR模式,来同步整个集群的路由信息。
BGP Speaker RR模式下,用户指定一个或多个Calico Node作为Router Reflection,RR与其他所有Node建立连接。其他Node只需要通过RR就可以获取整个集群完整的路由信息。
通过以下命令为Calico创建配置信息,并关闭nodeToNodeMeshEnabled开关:
|
|
关闭NodeMesh之后可以运行calicoctl node status
发现节点BGP Session全部消失,Pod已经无法跨节点Ping通。
假设Kubernetes中选择node1和node2作为RR服务器,我们需要手动为这两个Node指定routeReflectorClusterID,并打上指定的Label:
|
|
routeReflectorClusterID 通常是未使用过的IP地址
创建BGPPeer,含义是:所有节点(nodeSelector:all())都和包含指定标签的节点(peerSelector: route-reflector == ‘true’)建立BGP连接:
|
|
关于CRD的字段含义可以参考:https://docs.projectcalico.org/reference/resources/overview
文章作者 yoaz
上次更新 2021-11-17
许可协议 MIT