42、K8S-网络机制之calico、calicoctl

发布时间 2023-04-03 15:23:50作者: 小粉优化大师

Kubernetes学习目录

1、基础知识

1.1、简介

Calico是一个开源的虚拟化网络方案,用于为云原生应用实现互联及策略控制.相较于 Flannel 来
说,Calico 的优势是对网络策略(network policy),它允许用户动态定义 ACL 规则控制进出容器的数据
报文,实现为 Pod 间的通信按需施加安全策略.不仅如此,Calico 还可以整合进大多数具备编排能力的环
境,可以为 虚机和容器提供多主机间通信的功能。
 Calico 本身是一个三层的虚拟网络方案,它将每个节点都当作路由器,将每个节点的容器都当作是节点
路由器的一个终端并为其分配一个 IP 地址,各节点路由器通过 BGP(Border Gateway Protocol)学习
生成路由规则,从而将不同节点上的容器连接起来.因此,Calico 方案其实是一个纯三层的解决方案,通过每
个节点协议栈的三层(网络层)确保容器之间的连通性,这摆脱了 flannel host-gw 类型的所有节点必须
位于同一二层网络的限制,从而极大地扩展了网络规模和网络边界。

1.2、官网文档地址

官方地址:https://www.tigera.io/project-calico/

项目地址:https://github.com/projectcalico/calico

当前版本:3.26.0

1.3、网络模型

Calico为了实现更广层次的虚拟网络的应用场景,它支持多种网络模型来满足需求。
underlay network - BGP
overlay network  - IPIP、VXLAN

1.4、设计思想

Calico不使用隧道或者NAT来实现转发,而是巧妙的把所有二三层流量转换成三层流量,并通过host上路由配置完成跨host转发。

2、模型简介

2.1、BGP

2.1.1、BGP-简介

BGP(Border Gateway Protocol - 边界网关协议) ,这是一种三层虚拟网络解决方案,也是Calico广为人知的一种网络模型。
 它是互联网上一个核心的去中心化自治路由协议。
 - 每个工作节点都是一个网络主机边缘节点。
 由一个虚拟路由(vrouter)和一系列其他节点组成的一个自治系统(AS)。
 - 各个节点上的vrouter基于BGP协议,通过互相学习的方式,动态生成路由规则,实现各节点之间的网络互通性。
 BGP不使用传统的内部网关协议(IGP)的指标,而使用基于路径、网络策略或规则集来决定路由规则
它属于矢量路由协议。
 
这也是很多人从flannel切换到Calico之上的一个重要的考虑因素,VGP是一种纯粹的三层路由解决方案,并没有叠加,而是一种承载网络。
它有点类似于flannel的host-gw模型,但是与host-gw的区别在于,host-gw是由flanneld通过
kube-apiserver来操作etct内部的各种网络配置,进而实时更新到当前节点上的路由表中。
BGP方案中,各节点上的vRouter通过BGP协议学习生成路由表,基于路径、网络策略或规则集来动态生成路由规则

2.1.2、BGP模型划分

BGP模型根据主机容量来划分,可以分层两种网络模型:
小规模网络:BGP peer,以一对多(N-1)的方式,彼此更新网络信息,主机量多的时候,性能不好。因为每个节点都要进行(N-1)的网络信息更新,形成了mesh(网格)的效果
大规模网络:BGP Reflector,他以中央反射器的方式收集所有节点主机的信息,然后将收集后的信息,发布给所有节点,从而减轻集群中的路由同步的报文效率。但是我们需要对中央BGP反射器进行冗余处理。

简单来说,BGP就是通过动态生成的路由表的方式,以类似flannel的host-gw方式,来完成pod之间报文的直接路由,通信效率较高。
它要求所有的节点处于一个二层网络中,同时所有的主机也需要支持BGP协议。

2.1.3、BGP流程图

注意:如果节点是跨网段的话,会因为目标地址找不到,而无法发送数据包

 

2.2、IPIP

通过把一个IP数据包又套在一个IP包里,即把IP层封装到IP层的一个 tunnel,实现跨网段效果

2.3、VXLAN

2.3.1、vxlan简介

把数据包封装在UDP中,并使用物理网络的IP/MAC作为outer-header进行封装标识,然后在物理IP网上传输,"根据标识"到达目的地后由隧道终结点解封并将数据发送给目标虚拟机。

BGP要求所有的节点处于一个二层网络中,同时所有的主机也需要支持BGP协议。但是一旦我们要构建大
规模的网络集群,比如是一个B类网站,放了很多的节点主机,这个时候,由于网络报文无法被隔离,所以一
旦安全措施做的不到位的话,就会导致广播风暴,对我们产生很大的影响。所以,正常情况下,我们一般不推
荐在一个子网内创建大量的节点主机。所以一旦跨子网,BGP就不支持了。

所以VXLAN就实现了这样一种类似于 flannel的 VXLAN with directrouting的机制,演变出了一种 Vxlan With BGP的效果。
- 如果是同一网段,就使用BGP - 如果不是同一网段,就用VXLAN机制

2.3.2、vxlan流程图

注意:calico默认的配置清单中,使用的是 IPIP方式,因为它默认节点中不支持BGP协议。

 

3、工作模型

3.1、前提

如果我们要使用calico的时候,必须要提前将 flannel 功能禁用,然后再安装calico。因为对于k8s来说,cni配置的是谁,他就用谁。

如删除flannel
 kubectl delete -f flannel/kube-flannel.yml 

3.1、软件架构

3.1.1、安装方式

calico支持的模式很多,但是默认情况下,calico不知道我们的节点是否支持 BGP,所以,默认情况下,
我们在安装calico的时候,它采用的模式是 IPIP模式。如果我们非要使用BGP模型的话,需要自己修改配置
清单文件或者选择适合我们自己的BGP配置。
参考资料: https://docs.projectcalico.org/getting-started/kubernetes/quickstart

3.1.2、Calico-架构图

3.1.3、架构说明

注意:以下三点不是calico的组成部分。
1、每个黑色的背景就是一个边缘自治节点,里面有很多工作中的pod对象
2、每个pod对象不像flannel通过一对虚拟网卡连接到cni0,而是直接连接到内核中。
3、借助于内核中的iptables 和 routers(路由表)来完成转发的功能

3.1.4、关键组件

组件            解析
Felix           每个节点都有,负责配置路由、ACL、向etcd宣告状态等
BIRD            每个节点都有,负责把 Felix 写入Kernel的路由信息 分发到整个Calico网络,确保workload 连通
etcd            存储calico自己的状态数据,可以结合kube-apiserver来工作
RouteReflector  路由反射器,用于集中式的动态生成所有主机的路由表,非必须选项
Calico          编排系统插件 实现更广范围的虚拟网络解决方案。

参考资料:https://docs.projectcalico.org/reference/architecture/overview

3.2、组件解析

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

3.2.1、Calico网络模型主要工作组件 - Felix

运行在每一台host的agent进程,主要负责网络接口管理和监听、路由规划、ARP管理、ACL管理和同步、状
态报告等。Felix会监听Etcd中心的存储,从它获取事件,比如说用户在这台机器上加了一个IP,或者是创
建了一个容器等,用户创建Pod后,Felix负责将其网卡、IP、MAC都设置好,然后在内核的路由表里面写一
条,注明这个IP应该到这张网卡。同样,用户如果制定了隔离策略,Felix同样会将该策略创建到ACL中,以实现隔离。
注意:这里的策略规则是通过内核的iptables方式实现的

3.2.2、Calico网络模型主要工作组件 - Etcd

分布式键值存储,主要负责网络元数据一致性,确保Calico网络状态的准确性,可以与Kubernetes共用。
简单来说:ETCD是所有calico节点的通信总线,也是calico对接到到其他编排系统的通信总线。
官方推荐;
 < 50节点,可以结合 kube-apiserver 来实现数据的存储
 > 50节点,推荐使用独立的ETCD集群来进行处理。
 
参考资料:https://docs.projectcalico.org/getting-started/kubernetes/self-managedonprem/onpremises

3.2.3、Calico网络模型主要工作组件 - BIRD

Calico为每一台host部署一个BGP Client,使用BIRD实现,BIRD是一个单独的持续发展的项目,实现了
众多动态路由协议比如:BGP、OSPF、RIP等。在Calico的角色是监听Host上由Felix注入的路由信息,然
后通过BGP协议广播告诉剩余Host节点,从而实现网络互通。BIRD是一个标准的路由程序,它会从内核里面
获取哪一些IP的路由发生了变化,然后通过标准BGP的路由协议扩散到整个其他的宿主机上,让外界都知道这
个IP在这里,你们路由的时候得到这里来。

3.2.4、Calico网络模型主要工作组件 - Route Reflector

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

4、软件部署

4.1、准备工作

4.1.1、部署解析

对于calico在k8s集群上的部署来说,为了完成上面四个组件的部署,这里会涉及到两个部署组件

组件名                  组件作用
calico-node             需要部署到所有集群节点上的代理守护进程,提供封装好的Felix和BIRD
calico-kube-controller   专用于k8s上对calico所有节点管理的中央控制器。负责calico与k8s集群的协同及calico核心功能实现。

4.1.2、部署步骤

1、获取资源配置文件
   从calico官网获取相关的配置信息
2、定制CIDR配置
   定制calico自身对于pod网段的配置信息,并且清理无关的网络其他插件
3、定制pod的manifest文件分配网络配置
   默认的k8s集群在启动的时候,会有一个cidr的配置,有可能与calico进行冲突,那么我们需要修改一下
4、应用资源配置文件

4.1.3、注意事项

对于calico来说,它自己会生成自己的路由表,如果路由表中存在响应的记录,默认情况下会直接使
用,而不是覆盖掉当前主机的路由表
 所以如果我们在部署calico之前,曾经使用过flannel,尤其是flannel的host-gw模式的话,一定
要注意,在使用calico之前,将之前所有的路由表信息清空,否则无法看到calico的tunl的封装效果。

4.2、环境部署

4.2.1、删除之前布署的flannel

kubectl delete -f flannel/kube-flannel.yml

# 为了确保不受flannel之前多余的路由影响,建议重启一下节点,确保cni0、flannel、flannel.1接口是不存在。

4.2.2、获取资源配置清单

# 建议单独下载
https://github.com/projectcalico/calico/blob/master/manifests/calico.yaml

4.2.3、准备本地镜像

# 查看需要的镜像
]# grep docker.io calico/calico.yaml | uniq 
          image: docker.io/calico/cni:master
          image: docker.io/calico/node:master
          image: docker.io/calico/kube-controllers:master

# 准备离线镜像
# 1)、下载node:master
docker pull calico/node:master
docker tag calico/node:master 192.168.10.33:80/k8s/calico/node:master
docker push 192.168.10.33:80/k8s/calico/node:master

# 2)、下载kube-controllers:master
docker pull kube-controllers:master
docker tag calico/kube-controllers:master 192.168.10.33:80/k8s/calico/kube-controllers:master
docker push 192.168.10.33:80/k8s/calico/kube-controllers:master

# 3)、下载cni:master
docker pull cni:master
docker tag calico/cni:master 192.168.10.33:80/k8s/calico/cni:master
docker push 192.168.10.33:80/k8s/calico/cni:master


# 修改下载镜像地址
sed -i 's#docker.io/calico#192.168.10.33:80/k8s/calico#g' calico.yaml

# 修改成功
master1 calico]# grep 'k8s/calico' calico.yaml 
          image: 192.168.10.33:80/k8s/calico/cni:master
          image: 192.168.10.33:80/k8s/calico/cni:master
          image: 192.168.10.33:80/k8s/calico/node:master
          image: 192.168.10.33:80/k8s/calico/node:master
          image: 192.168.10.33:80/k8s/calico/kube-controllers:master

4.2.4、配置CIDR

# 开放默认注释的 CALICO_IPV4POOL_CIDR 变量,然后定制我们当前的pod的网段范围即可
master1 calico]# vi calico.yaml
   4800             - name: CALICO_IPV4POOL_CIDR
   4801               value: "10.244.0.0/16"

4.2.5、定制pod的manifest文件分配网络配置

# 这里我们直接让calico使用kube-controller-manager为节点分配的网段信
master1 calico]# vi calico.yaml
71           "ipam": {
72               "type": "host-local",
73               "subnet": "usePodCidr"
74           },

4.2.6、应用资源配置清单

kubectl apply -f calico/calico.yaml

4.2.7、检查pod状态

master1 ~]# kubectl -n kube-system get pod -o wide| grep calico 
calico-kube-controllers-74846594dd-tt6t8   1/1     Running                0                    2m21s   10.244.3.3      node1     <none>           <none>
calico-node-2gxlc                          1/1     Running                0                    2m21s   192.168.10.28   master3   <none>           <none>
calico-node-8bjxx                          1/1     Running                0                    2m21s   192.168.10.27   master2   <none>           <none>
calico-node-8gfbc                          1/1     Running                0                    2m21s   192.168.10.29   node1     <none>           <none>
calico-node-dx8zx                          1/1     Running                0                    2m21s   192.168.10.30   node2     <none>           <none>
calico-node-jhshc                          1/1     Running                0                    2m21s   192.168.10.26   master1   <none>           <none>

4.2.8、查看节点主机的进程

node2 ~]# ps -ef | grep calico
root      79038  79036  0 17:27 ?        00:00:00 calico-node -confd
root      79039  79037  0 17:27 ?        00:00:00 calico-node -monitor-token
root      79040  79032  0 17:27 ?        00:00:00 calico-node -allocate-tunnel-addrs
root      79041  79033  0 17:27 ?        00:00:00 calico-node -status-reporter
root      79044  79031  0 17:27 ?        00:00:00 calico-node -monitor-addresses
root      79045  79030  0 17:27 ?        00:00:02 calico-node -felix
root      79477  79035  0 17:27 ?        00:00:00 bird6 -R -s /var/run/calico/bird6.ctl -d -c /etc/calico/confd/config/bird6.cfg
root      79478  79034  0 17:27 ?        00:00:00 bird -R -s /var/run/calico/bird.ctl -d -c /etc/calico/confd/config/bird.cfg

4.2.9、创建pod,验证calico是否生效

]# kubectl create deployment pod-dept --replicas=3 --image=192.168.10.33:80/k8s/pod_test:v0.1

]# kubectl get pods -o wide
NAME                        READY   STATUS    RESTARTS   AGE   IP           NODE    NOMINATED NODE   READINESS GATES
pod-dept-75cb4f74c8-888kd   1/1     Running   0          10s   10.244.4.5   node2   <none>           <none>
pod-dept-75cb4f74c8-bklxw   1/1     Running   0          10s   10.244.3.5   node1   <none>           <none>
pod-dept-75cb4f74c8-xpd6t   1/1     Running   0          10s   10.244.4.4   node2   <none>           <none>

# 暴露一个service
]# kubectl expose deployment pod-dept --port=80 --target-port=80

# 访问测试
]# curl 10.111.204.254
kubernetes pod-test v0.1!! ClientIP: 10.244.137.64, ServerName: pod-dept-75cb4f74c8-888kd, ServerIP: 10.244.4.5!

]# curl 10.111.204.254
kubernetes pod-test v0.1!! ClientIP: 10.244.137.64, ServerName: pod-dept-75cb4f74c8-xpd6t, ServerIP: 10.244.4.4!

]# curl 10.111.204.254
kubernetes pod-test v0.1!! ClientIP: 10.244.137.64, ServerName: pod-dept-75cb4f74c8-bklxw, ServerIP: 10.244.3.5!

5、calico-网络解析

5.1、自动生成一个api版本信息

]# kubectl api-versions | grep crd
crd.projectcalico.org/v1

5.2、自动生成很多api资源

5.2.1、查询生成的资源

]# kubectl api-resources | grep crd.pro
bgpconfigurations                              crd.projectcalico.org/v1               false        BGPConfiguration
bgpfilters                                     crd.projectcalico.org/v1               false        BGPFilter
bgppeers                                       crd.projectcalico.org/v1               false        BGPPeer
blockaffinities                                crd.projectcalico.org/v1               false        BlockAffinity
caliconodestatuses                             crd.projectcalico.org/v1               false        CalicoNodeStatus
clusterinformations                            crd.projectcalico.org/v1               false        ClusterInformation
felixconfigurations                            crd.projectcalico.org/v1               false        FelixConfiguration
globalnetworkpolicies                          crd.projectcalico.org/v1               false        GlobalNetworkPolicy
globalnetworksets                              crd.projectcalico.org/v1               false        GlobalNetworkSet
hostendpoints                                  crd.projectcalico.org/v1               false        HostEndpoint
ipamblocks                                     crd.projectcalico.org/v1               false        IPAMBlock
ipamconfigs                                    crd.projectcalico.org/v1               false        IPAMConfig
ipamhandles                                    crd.projectcalico.org/v1               false        IPAMHandle
ippools                                        crd.projectcalico.org/v1               false        IPPool
ipreservations                                 crd.projectcalico.org/v1               false        IPReservation
kubecontrollersconfigurations                  crd.projectcalico.org/v1               false        KubeControllersConfiguration
networkpolicies                                crd.projectcalico.org/v1               true         NetworkPolicy
networksets                                    crd.projectcalico.org/v1               true         NetworkSet

5.2.2、测试查询ippools资源

]# kubectl get ippools
NAME                  AGE
default-ipv4-ippool   178m

5.3、查询网络的模型

5.3.1、默认是ipip模型

]# kubectl describe ippools default-ipv4-ippool 
Name:         default-ipv4-ippool
Namespace:    
Labels:       <none>
Annotations:  projectcalico.org/metadata: {"uid":"1d92a905-4c11-4d84-a53d-4999a4d64666","creationTimestamp":"2023-04-02T09:27:06Z"}
API Version:  crd.projectcalico.org/v1
Kind:         IPPool
Metadata:
  Creation Timestamp:  2023-04-02T09:27:06Z
  Generation:          1
  Managed Fields:
    API Version:  crd.projectcalico.org/v1
    Fields Type:  FieldsV1
    fieldsV1:
      f:metadata:
        f:annotations:
          .:
          f:projectcalico.org/metadata:
      f:spec:
        .:
        f:allowedUses:
        f:blockSize:
        f:cidr:
        f:ipipMode:
        f:natOutgoing:
        f:nodeSelector:
        f:vxlanMode:
    Manager:         Go-http-client
    Operation:       Update
    Time:            2023-04-02T09:27:06Z
  Resource Version:  1194008
  UID:               ef561fbc-59df-4aae-8d39-21f83dac43da
Spec:
  Allowed Uses:
    Workload
    Tunnel
  Block Size:     26
  Cidr:           10.244.0.0/16
  Ipip Mode:      Always
  Nat Outgoing:   true
  Node Selector:  all()
  Vxlan Mode:     Never
Events:           <none>

5.3.2、说明

这里的calico采用的模型就是ipip模型,分配的网段是使我们定制的cidr网段,而且子网段也是我们定制的16位掩码。

5.4、查看calico启动后,节点网口的情况

]# ifconfig 
tunl0: flags=193<UP,RUNNING,NOARP>  mtu 1480
        inet 10.244.136.0  netmask 255.255.255.255

master3 ]# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         192.168.10.2    0.0.0.0         UG    100    0        0 ens33
10.244.3.2      192.168.10.29   255.255.255.255 UGH   0      0        0 tunl0
10.244.3.3      192.168.10.29   255.255.255.255 UGH   0      0        0 tunl0
10.244.3.4      192.168.10.29   255.255.255.255 UGH   0      0        0 tunl0
10.244.3.5      192.168.10.29   255.255.255.255 UGH   0      0        0 tunl0
10.244.4.2      192.168.10.30   255.255.255.255 UGH   0      0        0 tunl0
10.244.4.3      192.168.10.30   255.255.255.255 UGH   0      0        0 tunl0
10.244.4.4      192.168.10.30   255.255.255.255 UGH   0      0        0 tunl0
10.244.4.5      192.168.10.30   255.255.255.255 UGH   0      0        0 tunl0
10.244.104.0    192.168.10.30   255.255.255.192 UG    0      0        0 tunl0
10.244.136.0    0.0.0.0         255.255.255.192 U     0      0        0 *
10.244.137.64   192.168.10.26   255.255.255.192 UG    0      0        0 tunl0
10.244.166.128  192.168.10.29   255.255.255.192 UG    0      0        0 tunl0
10.244.180.0    192.168.10.27   255.255.255.192 UG    0      0        0 tunl0
172.17.0.0      0.0.0.0         255.255.0.0     U     0      0        0 docker0
192.168.10.0    0.0.0.0         255.255.255.0   U     100    0        0 ens33

环境创建完毕后,会生成一个tunl0的网卡,所有的流量会走这个tunl0网卡

5.5、捉包分析ipip网络模式

5.5.1、node2节点的pod发出一个icmp包

# node2节点的pod发出一个icmp包
master1 ~]# kubectl exec -it pod-dept-75cb4f74c8-888kd -- /bin/sh
[root@pod-dept-75cb4f74c8-888kd /]# ping -c 1 10.244.3.5

5.5.2、分析总结-捉到的包

# 192.168.10.29192.168.10.30 是node1和node2的物理IP地址
node1 ~]# tcpdump -i ens33 -nn ip host 192.168.10.29 and host 192.168.10.30
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on ens33, link-type EN10MB (Ethernet), capture size 262144 bytes
20:43:44.424164 IP 192.168.10.30 > 192.168.10.29: IP 10.244.4.5 > 10.244.3.5: ICMP echo request, id 8704, seq 0, length 64 (ipip-proto-4)
20:43:44.424271 IP 192.168.10.29 > 192.168.10.30: IP 10.244.3.5 > 10.244.4.5: ICMP echo reply, id 8704, seq 0, length 64 (ipip-proto-4)

每个数据包都是基于双层ip嵌套的方式来进行传输,而且协议是 ipip-proto-4
结合路由的分发详情,可以看到具体的操作效果。
具体效果:10.244.4.5 -> 192.168.10.30 -> 192.168.10.29 -> 10.244.4.5 

6、Calico-BGP网络

6.1、简单介绍

calico本身是一个复杂的系统,复杂到它自己提供一个非常重要的Restful接口,结合calicoctl命
令来管理自身的相关属性信息,calicoctl可以直接与etcd进行操作,也可以通过kube-apiserver的方式
与etcd来进行操作。默认情况下,它与kube-apiserver通信的认证方式与kubectl的命令使用同一个
context。但是我们还是推荐,使用手工定制的一个配置文件。

calicoctl 是运行在集群之外的,用于管理集群功能的一个重要的组件。calicoctl 的安装方式很 多,常见的方式有:单主机方式、kubectl命令插件方式、pod方式、主机容器方式。我们需要自己选择一种适合自己的方式
参考资料:https:
//docs.projectcalico.org/gettingstarted/clis/calicoctl/install

6.2、calicoctl

6.2.1、安装calicoctl

curl -o /usr/local/bin/calicoctl -O -L https://github.com/projectcalico/calico/releases/download/v3.25.1/calicoctl-linux-amd64
chmod +x /usr/local/bin/calicoctl


# 测试
]# calicoctl ipam show --allow-version-mismatch
+----------+---------------+-----------+------------+--------------+
| GROUPING |     CIDR      | IPS TOTAL | IPS IN USE |   IPS FREE   |
+----------+---------------+-----------+------------+--------------+
| IP Pool  | 10.244.0.0/16 |     65536 | 5 (0%)     | 65531 (100%) |
+----------+---------------+-----------+------------+--------------+

6.2.2、关联kube-apiserver

mkdir /etc/calico
cat >/etc/calico/calicoctl.cfg<<'EOF'
apiVersion: projectcalico.org/v3
kind: CalicoAPIConfig
metadata:
spec:
  datastoreType: "kubernetes"
  kubeconfig: "/etc/kubernetes/admin.conf"
EOF

master1 ~]# calicoctl get nodes --allow-version-mismatch
NAME      
master1   
master2   
master3   
node1     
node2  

我们可以通过 calicoctl 来操作kubectl操作的资源了,只不过显式的格式稍微有一点点的区别.

6.2.3、命令操作

]# calicoctl ipam show  --allow-version-mismatch
+----------+---------------+-----------+------------+--------------+
| GROUPING |     CIDR      | IPS TOTAL | IPS IN USE |   IPS FREE   |
+----------+---------------+-----------+------------+--------------+
| IP Pool  | 10.244.0.0/16 |     65536 | 5 (0%)     | 65531 (100%) |
+----------+---------------+-----------+------------+--------------+

]# calicoctl ipam show  --show-configuration --allow-version-mismatch
+--------------------+-------+
|      PROPERTY      | VALUE |
+--------------------+-------+
| StrictAffinity     | false |
| AutoAllocateBlocks | true  |
| MaxBlocksPerHost   |     0 |
+--------------------+-------+

6.2.4、定制kubectl 插件子命令

cp -p /usr/local/bin/calicoctl /usr/local/bin/kubectl-calico
]# kubectl calico  node status  --allow-version-mismatch
Calico process is running.

IPv4 BGP status
+---------------+-------------------+-------+----------+-------------+
| PEER ADDRESS  |     PEER TYPE     | STATE |  SINCE   |    INFO     |
+---------------+-------------------+-------+----------+-------------+
| 192.168.10.27 | node-to-node mesh | up    | 01:31:06 | Established |
| 192.168.10.29 | node-to-node mesh | up    | 01:31:06 | Established |
| 192.168.10.30 | node-to-node mesh | up    | 01:31:06 | Established |
| 192.168.10.28 | node-to-node mesh | up    | 01:31:13 | Established |
+---------------+-------------------+-------+----------+-------------+

IPv6 BGP status
No IPv6 peers found.

6.3、配置BGP网络

6.3.1、修改配置

# 查看ipv4 ippool资源
]# kubectl calico --allow-version-mismatch get ipPools
NAME                  CIDR            SELECTOR   
default-ipv4-ippool   10.244.0.0/16   all()      

# 导出资源配置文件
]# kubectl calico --allow-version-mismatch get ipPools default-ipv4-ippool -o yaml >calico/default-ipv4-ippool.yml

# 修改资源配置清单 
]# cat default-ipv4-ippool.yml 
apiVersion: projectcalico.org/v3
kind: IPPool
metadata:
  name: default-ipv4-ippool
spec:
  allowedUses:
  - Workload
  - Tunnel
  blockSize: 26
  cidr: 10.244.0.0/16
  ipipMode: CrossSubnet
  natOutgoing: true
  nodeSelector: all()
  vxlanMode: Never

主要修改如下:
    1、pipMode: Always 修改为 ipipMode: CrossSubnet
这样子就可以实现所谓的 BGP with vxlan的效果

6.3.2、应用资源配置清单

]# kubectl calico --allow-version-mismatch apply -f default-ipv4-ippool.yml 
Successfully applied 1 'IPPool' resource(s)

6.3.3、分析节点路由变化

]# ip route list
default via 192.168.10.2 dev ens33 proto static metric 100 
blackhole 10.244.0.0/26 proto bird 
10.244.1.2 via 192.168.10.27 dev ens33 proto bird 
10.244.1.3 via 192.168.10.27 dev ens33 proto bird 
10.244.1.4 via 192.168.10.27 dev ens33 proto bird 
10.244.2.0/26 via 192.168.10.28 dev ens33 proto bird 
10.244.3.0/26 via 192.168.10.29 dev ens33 proto bird 
10.244.4.0/26 via 192.168.10.30 dev ens33 proto bird 
10.244.180.0/26 via 192.168.10.27 dev ens33 proto bird 
172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1 
192.168.10.0/24 dev ens33 proto kernel scope link src 192.168.10.26 metric 100 

# 更新完毕配置后,动态路由的信息就发生改变了,不再完全是 tunl0 网卡了,而是变成了通过具体的,物理网卡ens33 转发出去了。

6.4、捉包验证

6.4.1、开启deployment控制器 3个pod

master1 ~]# kubectl create deployment dp-test --replicas=3 --image=192.168.10.33:/k8s/pod_test:v0.1

6.4.2、node开启捉包并且发出icmp包验证

master1 ~]# kubectl get pod -o wide
NAME                      READY   STATUS    RESTARTS   AGE    IP           NODE    NOMINATED NODE   READINESS GATES
dp-test-55b67b496-c79hd   1/1     Running   0          110m   10.244.3.4   node1   <none>           <none>
dp-test-55b67b496-kst8x   1/1     Running   0          110m   10.244.3.5   node1   <none>           <none>
dp-test-55b67b496-stffx   1/1     Running   0          110m   10.244.4.3   node2   <none>           <none>

master1 ~]# kubectl exec -it dp-test-55b67b496-stffx -- /bin/sh
[root@dp-test-55b67b496-stffx /]# ping -c 1 10.244.3.4
64 bytes from 10.244.3.4: seq=0 ttl=62 time=0.385 ms


# Node1开启捉包
node1 ~]# tcpdump -i ens33 -nn ip host 10.244.3.4
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on ens33, link-type EN10MB (Ethernet), capture size 262144 bytes
14:11:14.063730 IP 10.244.4.3 > 10.244.3.4: ICMP echo request, id 5888, seq 0, length 64
14:11:14.063837 IP 10.244.3.4 > 10.244.4.3: ICMP echo reply, id 5888, seq 0, length 64

# 可以实现正常的通信效果,没有再次使用ipip的方式了。

7、BGP reflecter-进阶

7.1、基础知识

7.1.1、查询当前节点的网络情况

master1 ~]# kubectl calico node status
Calico process is running.

IPv4 BGP status
+---------------+-------------------+-------+----------+-------------+
| PEER ADDRESS  |     PEER TYPE     | STATE |  SINCE   |    INFO     |
+---------------+-------------------+-------+----------+-------------+
| 192.168.10.27 | node-to-node mesh | up    | 01:31:06 | Established |
| 192.168.10.29 | node-to-node mesh | up    | 01:31:06 | Established |
| 192.168.10.30 | node-to-node mesh | up    | 01:31:06 | Established |
| 192.168.10.28 | node-to-node mesh | up    | 01:31:13 | Established |
+---------------+-------------------+-------+----------+-------------+

IPv6 BGP status
No IPv6 peers found.

当前的calico节点的网络状态是 BGP peer 的模型效果,也就是说 每个节点上都要维护 n-1 个路
由配置信息,整个集群中需要维护 n*(n-1) 个路由效果,这在节点量非常多的场景中,不是我们想要的。
所以我们需要实现一种 BGP reflecter 的效果。

7.1.2、反射器方案

一个集群中,至少需要一个反射器角色。

如果我们要做 BGP reflecter 效果的话,需要对反射器角色做冗余,如果我们的集群是一个多主集群 的话,可以将集群的master节点作为bgp的reflecter角色,从而实现反射器的冗余。

7.1.3、操作步骤

1、定制反射器角色
2、后端节点使用反射器
3、关闭默认的网格效果

7.2、设置为BGP reflecter模型

7.2.1、创建反射器角色

# 定义calico资源配置清单
kubectl calico --allow-version-mismatch apply -f - <<EOF
apiVersion: projectcalico.org/v3
kind: Node
metadata:
  labels:
    route-reflector: "true"
  name: master1
spec:
  bgp:
    ipv4Address: 192.168.10.26/24
    ipv4IPIPTunnelAddr: 10.244.0.1
    routeReflectorClusterID: 1.1.1.1
EOF
# Successfully applied 1 'Node' resource(s)

属性解析;
metadata.labels                  是非常重要的,因为它需要被后面的节点来进行获取
metadata.name                    是通过 calicoctl get nodes 获取到的节点名称。
spec.bgp.ipv4Address             是指定节点的IP地址
spec.bgp.ipv4IPIPTunnelAddr      是指定节点上tunl0的IP地址
spec.bgp.routeReflectorClusterID 是BGP网络中的唯一标识,所以这里的集群标识只要唯一就可以了

7.2.2、将节点的网络模型更换为 reflecter模型

kubectl calico --allow-version-mismatch apply -f - <<EOF
kind: BGPPeer
apiVersion: projectcalico.org/v3
metadata:
  name: bgppeer-demo
spec:
  nodeSelector: all()
  peerSelector: route-reflector=="true"
EOF


属性解析;
spec.nodeSelector  指定的所有后端节点
spec.peerSelector  指定的是反射器的标签,标识所有的后端节点与这个反射器进行数据交流

master1 ~]# kubectl calico get BGPPeer --allow-version-mismatch
NAME           PEERIP   NODE    ASN   
bgppeer-demo            all()   0   


master1 ~]# kubectl calico node status
IPv4 BGP status
+---------------+---------------+-------+----------+-------------+
| PEER ADDRESS  |   PEER TYPE   | STATE |  SINCE   |    INFO     |
+---------------+---------------+-------+----------+-------------+
| 192.168.10.27 | node specific | up    | 07:00:30 | Established |
| 192.168.10.28 | node specific | up    | 07:00:30 | Established |
| 192.168.10.29 | node specific | up    | 07:00:30 | Established |
| 192.168.10.30 | node specific | up    | 07:00:30 | Established |
+---------------+---------------+-------+----------+-------------+

这个时候,节点的状态发生了改变,原来是PEER TYPE:node-to-node mesh 现在变成 PEER TYPE: node specific

7.2.3、关闭默认的网格效果

注意:
    我使用的版本是Calico Cluster Version:  3.26.0,默认自动会做如下操作


如果node-to-node mesh与node specific并存的时候,请做如下操作:
kubectl calico --allow-version-mismatch apply -f - <<EOF
apiVersion: projectcalico.org/v3
kind: BGPConfiguration
metadata:
  name: default
spec:
  logSeverityScreen: Info
  nodeToNodeMeshEnabled: false
  asNumber: 63400
EOF
# Successfully applied 1 'BGPConfiguration' resource(s)

属性解析;
metadata.name                   在这里最好是default,因为我们要对BGP默认的网络效果进行关闭
spec.nodeToNodeMeshEnabled      关闭后端节点的BGP peer默认状态 -- 即点对点通信关闭
spec.asNumber                   指定的是后端节点间使用反射器的时候,我们要在一个标志号内,这里随意写一个

# 查看资源运行
master1 ~]# kubectl calico get BGPConfiguration --allow-version-mismatch
NAME      LOGSEVERITY   MESHENABLED   ASNUMBER   
default   Info          false         63400

# 效果如下:
master1 ~]# kubectl calico node status
Calico process is running.

IPv4 BGP status
+---------------+---------------+-------+----------+-------------+
| PEER ADDRESS  |   PEER TYPE   | STATE |  SINCE   |    INFO     |
+---------------+---------------+-------+----------+-------------+
| 192.168.10.27 | node specific | up    | 07:08:47 | Established |
| 192.168.10.29 | node specific | up    | 07:08:47 | Established |
| 192.168.10.30 | node specific | up    | 07:08:47 | Established |
| 192.168.10.28 | node specific | up    | 07:08:47 | Established |
+---------------+---------------+-------+----------+-------------+

此时点对点已经没有,剩下反射器模式