第五章 Calico
官网: https://projectcalico.docs.tigera.io/about/about-calico
GitHub: https://github.com/projectcalico/calico/tree/master
Calico是一种开源网络和网络安全解决方案,适用于容器,虚拟机和基于主机的本机工作负载。符合CNI标准的网络插件,每个pod生成一个唯一的ip地址,并且把每个节点当做路由器。(未来 cilium ebpf)
Calico支持广泛的平台,包括 Kubernetes,docker,OpenStack 和裸机服务。
5.1 Calico网络模型主要工作组件:
-
Felix:运行在每一台Host的agent进程,主要负责网络接口管理和监听、路由、ARP管理、ACL管理和同步、状态上报等。
Felix会监听ETCD中心的存储,从它获取事件,比如说用户在这台机器上加了一个IP,或者创建了一个容器等。用户创建pod后,Felix将其网卡,MAC、IP都设置好,然后在内核的路由表里写一条,注明这个IP应该到这张网卡。同样用户若是设定了隔离策略,Felix同样会将该策略创建到ACL中,以实现隔离。
-
Etcd:分布式键值存储,主要负责网络元数据的一致性,确保Calico网络状态的准确性,可以与kubernetes共用。
-
BGP Client(BIRD):Calico为每一台Host部署一个BGP Client,使用BIRD实现,BIRD是一个单独的持续发展的项目,实现了众多动态路由协议比如BGP、OSPF、RIP等。在Calico中的角色是监听Host上由Felix注入的路由信息,然后通过BGP协议广播告诉剩余Host节点,从而实现网络互通。
BIRD是一个标准的路由程序,它会从内核里面获取哪一些IP的路由发生了变化,然后通过标准BGP的路由协议扩散到整个其他的宿主机上,让外界都知道这个IP在这里,你们路由的时候得到这里来。
-
BGP Route Reflector:在大型网络规模中,如果仅仅使用 BGP client 形成 mesh 全网互联的方案就会导致规模限制,因为所有节点之间俩俩互联,需要 N^2 个连接,为了解决这个规模问题,可以采用 BGP 的 Router Reflector 的方法,使所有
BGP Client 仅与特定 RR 节点互联并做路由同步
,从而大大减少连接数。
5.2 Calico 后端支持多种网络模式:
-
BGP模式:
边界网关协议(Border Gateway Protocol, BGP)是互联网上一个核心的去中心化自治路由协议。将节点作为虚拟路由器,通过BGP路由协议来实现集群内容器之间的网络访问。
-
IPIP模式:
在原有的IP报文中封装一个新的IP报文,新的IP报文中将源地址和目的地址IP都修改为对端宿主机IP。
默认情况下calico使用的是IPIP模式进行通信,所有节点之间建立tunl0隧道。每创建一个pod在宿主机上都会产生一个以cali开头的虚拟接口。
它的作用其实基本上就相当于一个基于IP层的网桥!一般来说,普通的网桥是基于mac层的,根本不需 IP,而这个 ipip 则是通过两端的路由做一个 tunnel,把两个本来不通的网络通过
点对点
连接起来。 -
cross-subnet:Calico-ipip 模式和 calico-bgp 模式都有对应的局限性,对于一些主机跨子网而又无法使网络设备使用 BGP 的场景可以使用 cross-subnet 模式,实现同子网机器使用 calico-BGP 模式,跨子网机器使用 calico-ipip 模式。
5.2.1 IPIP工作模式
1、环境:
[root@k8s-master01 ~]# kubectl get node -owide
NAME STATUS ROLES AGE VERSION INTERNAL-IP
k8s-master01 Ready <none> 8d v1.25.3 10.10.10.164
k8s-master02 Ready <none> 7d5h v1.25.3 10.10.10.31
k8s-master03 Ready <none> 7d22h v1.25.3 10.10.10.201
k8s-node01 Ready <none> 4d5h v1.25.3 10.10.10.112
k8s-node02 Ready <none> 2d23h v1.25.3 10.10.10.207
创建2个pod,IP地址分分别为172.16.58.194、172.16.85.194:
[root@k8s-master01 ~]# kubectl get pod -owide
NAME READY STATUS RESTARTS AGE IP NODE
busybox1 1/1 Running 0 143m 172.16.58.194 k8s-node02
busybox3 1/1 Running 0 6m35s 172.16.85.194 k8s-node01
pod busybox1 ping pod busybox3
[root@k8s-master01 ~]# kubectl exec -it busybox1 -- bash
bash-4.3# ping 172.16.85.195
PING 172.16.85.195 (172.16.85.195): 56 data bytes
2、 ping 包的旅程
pod busybox1的路由信息:
bash-4.3# route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 169.254.1.1 0.0.0.0 UG 0 0 0 eth0
169.254.1.1 0.0.0.0 255.255.255.255 UH 0 0 0 eth0
根据路由信息ping 172.16.85.195,会匹配到第一条。第一条路由信息的意思是:去往任何网段的数据包都发往网管169.254.1.1,然后从eth0网卡发送出去。
路由表中Flags标志的含义:
- U: up表示当前为启动状态
- H:Host表示该路由为一个主机,多为达到数据包的路由
- G:Gateway 表示该路由是一个网关,如果没有说明目的地是直连的
- D:Dynamicaly 表示该路由是重定向报文修改
- M:表示该路由已被重定向报文修改
3、node2节点上路由信息:
[root@k8s-node02 ~]# route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 10.10.10.1 0.0.0.0 UG 0 0 0 eth0
10.10.10.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0
169.254.0.0 0.0.0.0 255.255.0.0 U 1002 0 0 eth0
169.254.169.254 10.10.10.1 255.255.255.255 UGH 0 0 0 eth0
172.16.58.192 0.0.0.0 255.255.255.192 U 0 0 0 *
172.16.58.195 0.0.0.0 255.255.255.255 UH 0 0 0 cali4405ed05989
172.16.85.192 10.10.10.112 255.255.255.192 UG 0 0 0 tunl0
当ping 来到node2节点上,会匹配路由tunl0。该路由的意思是:去往172.16.85.192/26的网段的数据包都发往网关10.10.10.112,即为node1,所以数据包就通过设备tunl0发往到node1节点上。
4、node1节点上路由信息:
[root@k8s-node01 ~]# route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 10.10.10.1 0.0.0.0 UG 0 0 0 eth0
10.10.10.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0
169.254.0.0 0.0.0.0 255.255.0.0 U 1002 0 0 eth0
169.254.169.254 10.10.10.1 255.255.255.255 UGH 0 0 0 eth0
172.16.58.192 10.10.10.207 255.255.255.192 UG 0 0 0 tunl0
172.16.85.192 0.0.0.0 255.255.255.192 U 0 0 0 *
172.16.85.195 0.0.0.0 255.255.255.255 UH 0 0 0 cali0d5af60a6c5
172.16.85.196 0.0.0.0 255.255.255.255 UH 0 0 0 cali17a895e22ab
172.16.85.197 0.0.0.0 255.255.255.255 UH 0 0 0 cali33cc94a40c2
当node1节点网卡收到数据包之后,发现发往的目的ip为172.16.85.195,匹配到路由,该路由的意思是:172.16.85.195是本机直连设备,去往设备的数据包发往cali0d5af60a6c5。
每个pod发出去的数据包会直接转发到cali开头的网卡,这个接口跟pod里的网卡是veth pair的关系。
veth pair最直接的理解就是“网线直连
”,pod1发出去的所有数据包,“闭着眼”转发给calixxxxx,calixxxxx从其他地方收到的数据包“闭着眼”转发给pod1。
cali 开头的网卡会连接到tunl0,pod1和pod2通信时,pod1发出的数据先到达caliXXXXX,然后进入到node节点 vms71的tunl0接口,然后到达隧道的另一端node节点vms72的tunl0接口,然后转发到caliyyyyy,最终到达pod2。所以tunl0隧道的作用是封装所有pod之间的流量。
顾名思义,IPIP网络就是将IP网络封装在IP网络里。IPIP网络的特点是所有pod的数据流量都从隧道tunl0发送,并且在tunl0这增加了一层传输层的封包。