42、K8S-网络机制之Calico、calicoctl
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、软件架构
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
关于删除的方法,请看小节:https://www.cnblogs.com/ygbh/p/17278112.html#_label3
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.29、192.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 | +---------------+---------------+-------+----------+-------------+
此时点对点已经没有,剩下反射器模式
8、验证当前calico网络是否正常
8.1、定义资源配置清单
kubectl apply -f - <<EOF apiVersion: v1 kind: Namespace metadata: name: develop labels: kubernetes.io/metadata.name: develop --- apiVersion: apps/v1 kind: Deployment metadata: labels: app: pod-deployment1 name: pod-deployment1 namespace: develop spec: replicas: 3 selector: matchLabels: app: pod-deployment1 template: metadata: labels: app: pod-deployment1 spec: containers: - image: 192.168.10.33:80/k8s/pod_test:v0.1 name: pod-test --- apiVersion: v1 kind: Service metadata: labels: app: pod-deployment1 name: pod-deployment1 namespace: develop spec: ports: - port: 80 protocol: TCP targetPort: 80 selector: app: pod-deployment1 type: ClusterIP EOF
8.2、查看运行效果
master1 ~]# kubectl get ns develop NAME STATUS AGE develop Active 29s master1 ~]# kubectl get pods -n develop NAME READY STATUS RESTARTS AGE pod-deployment1-84f8987c58-8d58z 1/1 Running 0 32s pod-deployment1-84f8987c58-jd44l 1/1 Running 0 32s pod-deployment1-84f8987c58-mgvwp 1/1 Running 0 32s master1 ~]# kubectl get svc -n develop NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE pod-deployment1 ClusterIP 10.104.252.17 <none> 80/TCP 55s master1 ~]# curl 10.104.252.17 kubernetes pod-test v0.1!! ClientIP: 192.168.10.26, ServerName: pod-deployment1-84f8987c58-8d58z, ServerIP: 10.244.3.6! [root@master1 ~]# curl 10.104.252.17 kubernetes pod-test v0.1!! ClientIP: 192.168.10.26, ServerName: pod-deployment1-84f8987c58-mgvwp, ServerIP: 10.244.4.4! # 证明当前使用calico,pod的网络是正常的