一、Kubernetes集群网络组件-Flannel

1.1 初识Flannel

flannel是一个专为kubernetes定制的 三层 网络解决方案,主要用于解决容器的跨主机通信问题。

优势:

  • Kubernetes发行版都可以默认安装Flannel;
  • 容易安装和配置;
  • 中小型网络架构首选;
  • 不需要专用的数据存储;

劣势:

  • 性能损耗高;
  • 不支持Network Policy;

1.2 Flannel的三种后端实现

  • UDP模式(弃用):使用设备flannel.0进行封包解包,不是内核原生支持,上下文切换较大,性能差。

  • VXLAN:Overlay Network方案。

  • Host-GW模式,一种纯三层网络方案。

1.2.1 VXLAN(默认)

Day01-kubernetes基础架构解读-图13

docker0(CNI):网桥设备,每创建一个pod都会创建一对 veth pair;

Flannel.1:overlay 网络的设备,用来进行 vxlan 报文的处理(封包和解包);

Flanneld:Flannel 在每个主机中运行 flanneld 作为 agent,它会为所有主机从集群的网络地址空间中,获取一个小的网段。维护了各个节点之间的路由表信息。

数据流传输流程:

  • 1、源容器A向目标容器发送数据,数据首先发送给 cni0 网桥;
  • 2、cni0 网桥接受到数据后,将其转交给 flannel.1 虚拟网卡处理;
  • 3、flannel.1 接受到数据后,对数据进行封装,并发给Node1宿主机的 eth0;
  • 4、目标容器Node2宿主机的eth0接收到数据后发现是vxlan的包,对数据包进行拆封,并转发给flannel.1虚拟网卡;
  • 5、flannel.1 虚拟网卡接受到数据,然后将数据发送给docker0网桥;
  • 6、最后,数据到达目标容器B,完成容器之间的数据通信;

这样通过一层层的封装和解包实现了一个跨节点的大VLAN数据传输;

缺点:先进行二层帧封装,再通过宿主机网络封装,解封装也一样,所以增加性能开销

1.2.2 节点内通信

节点内的容器间通信通过 cni0 网桥就能完成,不涉及任何VXLAN报文的封包解包。

例如在下面的图例中,Node1的子网为10.244.0.1/24, PodA 10.244.0.20 和 PodB 10.224.0.21通过 cni0 网桥实现互通。

Day01-kubernetes基础架构解读-图14

1.2.3 Host-GW

Flannel的host-gw模式是一种纯三层的网络互通方案,Pod之间互相访问是通过路由方式实现。host-gw模式下跨节点网络通信网络通信需要通过节点上的路由表实现,因此必须要通信双方所在宿主机能够直接路由。这就要求该模式下集群中所有节点必须处于同一个网络内。

数据流传输流程:

在host-gw模式下,由于不涉及VXLAN的封包解包,不再需要 flannel.1虚机网卡。flanneld 负责为各节点设置路由 ,将对应节点Pod子网的下一跳地址指向对应的节点的IP;

Day01-kubernetes基础架构解读-图15

缺点:host-gw另外一个限制则是随着集群中节点规模的增大,flanneld维护主机上成千上万条路由表的动态更新也是一个不小的压力,因此在路由方式下,路由表规则的数量是限制网络规模的一个重要因素。

1.3 总结

VXLAN特点:

  • 先进行二层帧封装,再通过宿主机网络封装,解封装也一样,所以增加性能开销
  • 对宿主机网络要求低,只要三层网络可达

Host-GW特点:

  • 直接路由转发,性能损失小
  • 对宿主机网络要求二层可达

二、Kubernetes集群网络组件-Calico

2.1 网络基础知识

2.1.1 基础概念

广播域

01 交换机在转发数据时会先进行广播这个广播可以发送的区域就是一个广播域
02 交换机之间对广播帧是透明的所以交换机之间组成的网络是一个广播域
03 路由器的一个接口下的网络是一个广播域所以路由器可以隔离广播域

ARP(地址解析协议)

01 发送这个广播帧是由ARP协议实现
02 ARP是通过IP地址获取物理地址的一个TCP/IP协议

三层交换机

01 二层交换机只工作在数据链路层
02 路由器则工作在网络层
03 三层交换机可同时工作在数据链路层和网络层并根据MAC地址或IP地址转发数据包

VLAN(Virtual Local Area Network):虚拟局域网

01 VLAN是一种将局域网设备从逻辑上划分成一个个网段
02 一个VLAN就是一个广播域VLAN之间的通信是通过第3层的路由器来完成的 03 VLAN应用非常广泛基本上大部分网络项目都会划分vlan

VLAN的主要好处

01 分割广播域减少广播风暴影响范围
02 提高网络安全性根据不同的部门用途应用划分不同网段

2.1.2 路由技术

路由器主要分为两个端口类型

路由器主要分为两个端口类型:LAN口和WAN口

  • WAN口:配置公网IP,接入到互联网,转发来自LAN口的IP数据包。
  • LAN口:配置内网IP(网关),连接内部交换机

功能

  • 路由器是连接两个或多个网络的硬件设备
  • 将从端口上接收的数据包,根据数据包的目的地址智能转发出去

路由器的功能

  • 路由
  • 转发
  • 隔离子网
  • 隔离广播域

路由

  • 01、静态路由:指人工手动指定到目标主机的地址然后记录在路由表中,如果其中某个节点不可用则需要重新指定。
  • 02、动态路由:则是路由器根据动态路由协议自动计算出路径永久可用,能实时地适应网络结构的变化。
  • 03、常用的动态路由协议:
  • RIP( Routing Information Protocol ,路由信息协议)
  • OSPF(Open Shortest Path First,开放式最短路径优先)
  • BGP(Border Gateway Protocol,边界网关协议)

2.1.3 K8S网络模型

回看Docker容器网络模型

Day01-kubernetes基础架构解读-图16

相关概念

  • 01、Linux在网络栈中引入网络命名空间,将独立的网络协议栈隔离到不同的命名空间中, 彼此间无法通信;

  • 02、Docker利用这一特性,实现不同容器间的网络隔离。

  • Veth设备对:Veth设备对的引入是为了实现在不同网络命名空间的通信。

  • Iptables/Netfilter:Docker使用Netfilter实现容器网络转发。

  • 网桥(docker0):网桥是一个二层网络设备,通过网桥可以将Linux支持的不同的端口连接起来,并实现类似交换机那样的多对多的通信。

  • 路由:Linux系统包含一个完整的路由功能,当IP层在处理数据发送或转发的时候,会使用路由表来决定发往哪里。

容器之间通信

二层网络之间的通信

容器访问外网

通过docker0,NAT转发到外网

2.1.4 Pod网络

Day01-kubernetes基础架构解读-图17

infra container

Pod是K8s最小调度单元,一个Pod由一个容器或多个容器组成,当多个容器时,怎么都用这一 个Pod IP?

  • 01、k8s会在每个Pod里先启动一个infra container小容器,然后让其他的容器连接进来 这个网络命名空间
  • 02、其他容器看到的网络就完全一样了。即网络设备、IP地址、Mac地址等。
  • 03、在Pod的IP地址就是infra container的IP地址

pod通信

在 Kubernetes 中,每一个 Pod 都有一个真实的 IP 地址,并且每一个 Pod 都可以使用此IP地址与其他Pod通信。Pod之间通信会有两种情况:

  • 两个Pod在同一个Node上
  • 两个Pod在不同Node上

两个Pod在同一个Node上

Day01-kubernetes基础架构解读-图18

  • 01、对 Pod1 来说,eth0 通过虚拟以太网设备(veth0)连接到 root namespace;
  • 02、网桥cbr0中为veth0配置了一个网段。一旦数据包到达网桥,网桥使用ARP协议解析出 其正确的目标网段veth1;
  • 03、网桥 cbr0 将数据包发送到 veth1;
  • 04、数据包到达 veth1 时,被直接转发到Pod2的network namespace中的eth0 网络 设备。

两个Pod在不同Node上

Day01-kubernetes基础架构解读-图19

相比同节点Pod通信,这里源Pod发出的数据包需要传递到目标节点,但是源Pod并不知道目标 Pod在哪个节点上?

因此,为了实现容器跨主机通信需求,就需要部署网络组件,这些网络组件都必须满足如下要求:

  • 一个Pod一个IP
  • 所有的 Pod 可以与任何其他 Pod 直接通信
  • 所有节点可以与所有 Pod 直接通信
  • Pod 内部获取到的 IP 地址与其他 Pod 或节点与其通信时的 IP 地址是同一个(pod绑定IP生命周期)

2.1.5 CNI(容器网络接口)

CNI(Container Network Interface,容器网络接口):是一个容器网络规范,网络采用的就是这个CNI规范,负责初始化infra容器的网络设备。

2.2 架构实现

Calico在每个计算节点都利用Linux Kernel实现了一个高效的vRouter来负责数据转发。 每个vRouter都通过BGP协议把在本节点上运行的容器的路由信息向整个Calico网络广播,并自动设置到达其他节点的路由转发规则。

Calico 项目还实现了 Kubernetes 网络策略,提供ACL功能。

BGP 举个例子:

Day01-kubernetes基础架构解读-图20

01 在这个图中有两个自治系统autonomous system简称为AS):AS 1  AS 2
02 在互联网中一个自治系统(AS)是一个有权自主地决定在本系统中应采用何种路由协议的小型单位
03 这个网络单位可以是一个简单的网络也可以是一个由一个或多个普通的网络管理员来控制的网络群体它是一个单独的可管理的网络单元例如一所大学一个企业或者一个公司个体)。
04 一个自治系统有时也被称为是一个路由选择域routing domain)。一个自治系统将会分配一个全局的唯一的16位号码有时我们把这个号码叫做自治系统号ASN)。
05 在正常情况下自治系统之间不会有任何来往如果两个自治系统里的主机要通过IP地址直接进行通信我们就必须使用路由器把这两个自治系统连接起来BGP协议就是让他们互联的一种方式

Calico组件功能:

  • Felix:daemonSet部署,主要负责维护宿主机路有规则及ACL;
  • BGP:把Felix写入的路由信息分发到集群;
  • ETCD:保存calico策略和路由信息;
  • BGP Route Reflector(BIRD):大规模部署时使用,摒弃所有节点互联的mesh模 式,通过一个或者多个 BGPRoute Reflector 来完成集中式的路由分发;

区别:

Flannel使用flanneld进程来维护路由信息;

Calico使用BGP协议来维护整个集群路由信息;

2.3 Calico架构图

Calico 通过巧妙的引导 workload 所有的流量至一个特殊的网关 169.254.1.1,从而引流 到 host 的 calixxx 网络设备上,形成了二三层流量全部转换 host 的三层流量转发。

Day01-kubernetes基础架构解读-图21

不同宿主机间的pod访问流程如下:

  • 1、容器1的所有报文都会通过eth0发送到下一跳169.254.1.1;
  • 2、主机上的calixx网卡接收到报文后,再根据路由表转发;
  • 3、数据包会通过tun0设备发送到下一跳,也就是容器2的宿主机 192.168.2.132/32;
  • 4、通过路由表转发,接着从cali34af9914629网卡,发送到容器2。

2.4 Calico的具体实现

全互联模式(node-to-node mesh)

1、IPIP模式:

和flannel的vxlan差不多模式,基于二层数据的封装和解封;也会创建一个 虚拟网卡 tunl0,把两个本来不通的网络通过点对点连接起来,都是一种复杂的网络方案,IPIP和 vxlan模式的性能基本上接近,所以在性能方面要相对于路由方面损失10-20%。

2、BGP模式:

和flannel的host-gw模式几乎一样,Calico 项目实际上将集群里的所有节点,都当作是边界路由器来处理,它们一起组成了一个全连通的网络,互相之间通过 BGP 协议交换路由规则。

路由反射模式Router Reflection(RR)

指定一个或多个BGP Speaker为RouterReflection,它与网络中其他Speaker建立连接, 每个Speaker只要与Router Reflection建立BGP就可以获得全网的路由信息。

2.4.1 IPIP模式改为BGP模式

1、容器方式安装的calico修改模式

(1)在k8s-master01节点上更改calico-node配置

#会进入vim编辑模式
[root@master01 1]# k edit ds calico-node -n kube-system -oyaml
搜索下面两行
        - name: CALICO_IPV4POOL_IPIP
          value: Always

在它的下面增加
        - name: CALICO_AUTODETECTION_METHOD
          value: interface=ens33

如果不是yaml格式,则通过以下格式在搜索内容后面进行添加

{"name":"CALICO_AUTODETECTION_METHOD","value":"interface=eth0"}

保存即可生效

(2)在k8s-master01节点上更改ippool,搜索ipipMode,将ipipMode: Always 改为 ipipMode: Never保存即可生效

[root@master01 1]# k edit ippool

(3)查看ip,会发现所有机器的tunl0都没有IP地址了

[root@master01 1]# ip -4 a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    inet 192.168.1.31/24 brd 192.168.1.255 scope global ens33
       valid_lft forever preferred_lft forever
    inet 192.168.1.38/32 scope global ens33
       valid_lft forever preferred_lft forever
5: kube-ipvs0: <BROADCAST,NOARP> mtu 1500 qdisc noop state DOWN group default
    inet 10.0.0.10/32 scope global kube-ipvs0
       valid_lft forever preferred_lft forever
    inet 10.0.179.106/32 scope global kube-ipvs0
       valid_lft forever preferred_lft forever
    inet 10.0.175.237/32 scope global kube-ipvs0
       valid_lft forever preferred_lft forever
    inet 10.0.135.70/32 scope global kube-ipvs0
       valid_lft forever preferred_lft forever
    inet 10.0.187.20/32 scope global kube-ipvs0
       valid_lft forever preferred_lft forever
    inet 10.0.154.239/32 scope global kube-ipvs0
       valid_lft forever preferred_lft forever
    inet 10.0.0.1/32 scope global kube-ipvs0
       valid_lft forever preferred_lft forever

(4)查看route,使用BGP模式不再显示tunl0

[root@master01 1]# ip route
default via 192.168.1.1 dev ens33
169.254.0.0/16 dev ens33 scope link metric 1002
172.17.125.0/26 via 10.0.0.61 dev ens33 proto bird
172.18.195.0/26 via 192.168.1.33 dev ens33 proto bird
172.25.92.64/26 via 192.168.1.32 dev ens33 proto bird
blackhole 172.25.244.192/26 proto bird
172.25.244.218 dev cali4c6a037f519 scope link
172.25.244.219 dev calia2acd01c93c scope link
172.27.14.192/26 via 192.168.1.35 dev ens33 proto bird
192.168.1.0/24 dev ens33 proto kernel scope link src 192.168.1.31

(5)如果使用BGP模式,172.17.125.18访问172.25.244.219时,它的路由是172.25.244.219 dev calia2acd01c93c scope link,但此时并不需要借助tunl0了,而是直接通过ens33来。

Day01-kubernetes基础架构解读-图22

2、calicoctl方式修改模式

官方文档:安装Calicoctl

官方Github地址:Calicoctl

Calico和k8s版本对应关系:主要搜索System requirements

(1)calicoctl二进制安装

提前查看集群calico版本信息,观察到为v3.24.5

[root@master01 ~]# kubectl get daemonset calico-node -n kube-system -o jsonpath='{.spec.template.spec.containers[0].image}'
registry.cn-beijing.aliyuncs.com/dotbalo/node:v3.24.5

使用以下命令下载calicoctl二进制文件

[root@master01 ~]# curl -L https://github.com/projectcalico/calico/releases/download/v3.24.5/calicoctl-linux-amd64 -o calicoctl

将文件设置为可执行

[root@master01 ~]# mv calicoctl-linux-amd64 calicoctl
[root@master01 ~]# chmod +x calicoctl && cp calicoctl /usr/local/bin/

(2)修改网络模式

#显示 Calico 中所有 IP 池的详细信息,包括每个 IP 池的名称、CIDR、IP 范围等
[root@master01 ~]# calicoctl get ippool -owide
NAME                  CIDR            NAT    IPIPMODE   VXLANMODE   DISABLED   DISABLEBGPEXPORT   SELECTOR
default-ipv4-ippool   172.16.0.0/12   true   Always     Never       false      false              all()

#导出yaml文件,并修改网络模式。搜索ipipMode,将ipipMode: Always 改为 ipipMode: Never保存即可生效
[root@master01 ~]# calicoctl get ippool -oyaml > ippool.yaml
[root@master01 ~]# vim ippool.yaml
apiVersion: projectcalico.org/v3
items:
- apiVersion: projectcalico.org/v3
  kind: IPPool
  metadata:
    creationTimestamp: "2023-11-01T10:14:30Z"
    name: default-ipv4-ippool
    resourceVersion: "7861"
    uid: ae7baad2-76fb-4e47-ba52-d1a2595f4b43
  spec:
    allowedUses:
    - Workload
    - Tunnel
    blockSize: 26
    cidr: 172.16.0.0/12
    ipipMode: Never #主要修改这里
    natOutgoing: true
    nodeSelector: all()
    vxlanMode: Never
kind: IPPoolList
metadata:
  resourceVersion: "1271482"

#重新应用
[root@master01 ~]# calicoctl apply -f ippool.yaml
Successfully applied 1 'IPPool' resource(s)

验证,观察到IPIPMODE变更为Never。现在没有配置IP了,通过这个可以判断有没有成功

#验证
[root@master01 ~]#  calicoctl get ippool -owide
NAME                  CIDR            NAT    IPIPMODE   VXLANMODE   DISABLED   DISABLEBGPEXPORT   SELECTOR
default-ipv4-ippool   172.16.0.0/12   true   Never      Never       false      false              all()

#二次验证
[root@master01 ~]# ip addr
...
...
3: tunl0@NONE: <NOARP,UP,LOWER_UP> mtu 1480 qdisc noqueue state UNKNOWN group default qlen 1000
    link/ipip 0.0.0.0 brd 0.0.0.0
...
...

这里tul0网卡就没用了,因为不需要封包,所以容器内部的数据到达到宿主机直接从网卡出去了,BGP模式相对于ipip模式少了tul0设备的介入,数据的封装。

[root@master01 ~]# ip route
default via 192.168.1.1 dev ens33 proto static metric 100
172.18.71.0/26 via 192.168.1.64 dev ens33 proto bird
172.20.59.192/26 via 192.168.1.63 dev ens33 proto bird
172.21.231.128/26 via 192.168.1.62 dev ens33 proto bird
172.29.55.0/26 via 192.168.1.61 dev ens33 proto bird
blackhole 172.31.112.128/26 proto bird
172.31.112.160 dev cali9be94a208a6 scope link
172.31.112.161 dev cali33c5e9de29d scope link
172.31.112.162 dev caliebfd47342f3 scope link
172.31.112.163 dev calibfce1d7ceef scope link
172.31.112.164 dev calid4e9272734b scope link
192.168.1.0/24 dev ens33 proto kernel scope link src 192.168.1.60 metric 100

说明:这里没有tul0的路由了,数据包到达宿主机上面了,根据这个路由表去转发。这个和flannel的host-gw是一样的。

2.4.2 BGP模式改为路由反射(Route Reflector)模式

Calico集群中的节点之间都会相互建立连接,用于路由交换。但是随着集群规模的扩 大,mesh模式将形成一个巨大服务网格,连接数成倍增加,就会产生性能问题。

Day01-kubernetes基础架构解读-图23

我们来具体看下路由信息:(集群5节点,如下节点维护了另外4条node节点的路由)

[root@master01 ~]# calicoctl node status
Calico process is running.

IPv4 BGP status
+--------------+-------------------+-------+----------+-------------+
| PEER ADDRESS |     PEER TYPE     | STATE |  SINCE   |    INFO     |
+--------------+-------------------+-------+----------+-------------+
| 192.168.1.63 | node-to-node mesh | up    | 08:35:42 | Established |
| 192.168.1.64 | node-to-node mesh | up    | 08:35:40 | Established |
| 192.168.1.61 | node-to-node mesh | up    | 08:35:42 | Established |
| 192.168.1.62 | node-to-node mesh | up    | 08:35:45 | Established |
+--------------+-------------------+-------+----------+-------------+

IPv6 BGP status
No IPv6 peers found.

BGP client里面有个进程叫bird,这个bird就是负责BGP协议的通信完成路由表学习,随着连接的增多,下面这两个也会增多,使用的端口是179。

[root@master01 ~]# ss -antp | grep ESTAB | grep bird
ESTAB      0      0      192.168.1.60:179                192.168.1.64:52369               users:(("bird",pid=4315,fd=8))
ESTAB      0      0      192.168.1.60:179                192.168.1.61:60661               users:(("bird",pid=4315,fd=9))
ESTAB      0      0      192.168.1.60:179                192.168.1.63:43823               users:(("bird",pid=4315,fd=10))
ESTAB      0      0      192.168.1.60:179                192.168.1.62:44493               users:(("bird",pid=4315,fd=11))

[root@node02 ~]# ss -antp | grep bird
LISTEN     0      8            *:179                      *:*                   users:(("bird",pid=4868,fd=7))
ESTAB      0      0      192.168.1.62:179                192.168.1.64:56141               users:(("bird",pid=4868,fd=8))
ESTAB      0      0      192.168.1.62:44493              192.168.1.60:179                 users:(("bird",pid=4868,fd=9))
ESTAB      0      0      192.168.1.62:33015              192.168.1.61:179                 users:(("bird",pid=4868,fd=10))
ESTAB      0      0      192.168.1.62:179                192.168.1.63:56397               users:(("bird",pid=4868,fd=11))

如果节点达到了100+节点,这样当业务出现高并发场景,巨大的网络路由会造成很大的损耗,这时就需要使用 Route Reflector(路由器反射)模式解决这个问题。

Route Reflector模式下的实现:

Day01-kubernetes基础架构解读-图24

从集群当中找出多台性能较好的节点,当作路由反射器,让其他的BGP client通过这两个节点获取路由表的信息,这两个路由反射器相对于代理的角色(Nginx),其他人都是从这获取路由表的学习,那么压力就集中在这两台,做路由的集中下发,BGP client就是从这里面获取所有的路由表。所以每个节点只要和路由反射器建立关系就行,有两个路由反射器就建立两个链接,这样就避免了一个节点需要建立其它上千台node节点损耗的问题。

1、关闭node-to-node模式

关闭node to node模式就代表网络不通(一旦更改,整个集群网路就会断掉!!!线上一定要先评估!!)

#显示 Calico 中所有 BGP 配置的详细信息包括每个 BGP 配置的名称AS 数字节点选择器Peer配置等
[root@master01 1]# calicoctl get bgpconfig
NAME   LOGSEVERITY   MESHENABLED   ASNUMBER

#获取Calico中所有节点的详细信息
[root@master01 1]# calicoctl get node -o wide
NAME       ASN       IPV4              IPV6
master01   (64512)   192.168.1.60/24
master02   (64512)   192.168.1.63/24
master03   (64512)   192.168.1.64/24
node01     (64512)   192.168.1.61/24
node02     (64512)   192.168.1.62/24

调整as的编号

#定义bgp配置文件
[root@master01 1]# vim bgpconfig.yaml
apiVersion: projectcalico.org/v3
kind: BGPConfiguration
metadata:
  name: default
spec:
  logSeverityScreen: Info
  nodeToNodeMeshEnabled: false
  asNumber: 64512 #主要修改这里

#应用
[root@master01 1]# calicoctl apply -f bgpconfig.yaml
Successfully applied 1 'BGPConfiguration' resource(s)

#验证
[root@master01 1]# calicoctl get bgpconfig
NAME      LOGSEVERITY   MESHENABLED   ASNUMBER
default   Info          false         64512

在其他节点访问不了Pod

[root@master01 1]# calicoctl node status
Calico process is running.

IPv4 BGP status
No IPv4 peers found.

IPv6 BGP status
No IPv6 peers found.

2、配置指定节点充当路由反射器

从当前节点找两个节点充当路由反射器,作为路由反射器。

为方便让BGPPeer轻松选择节点,通过标签选择器匹配。给路由器反射器节点打标签:

[root@master01 1]# k label node node01  route-reflector=true

给选定的节点指定路由反射器 ID: routeReflectorClusterID 这个可以写任意集群当中没有使用的ip

# 导出yaml文件
[root@master01 ~]# calicoctl get node node01 -oyaml > rr-node.yaml

# 修改yaml文件
[root@master01 ~]# vim rr-node.yaml
...
...
  bgp:
    ipv4Address: 10.0.0.61/24
    routeReflectorClusterID: 244.0.0.1 # 集群ID保证唯一性
...
...

# 应用
[root@master01 ~]# calicoctl apply -f rr-node.yaml
Successfully applied 1 'Node' resource(s)

# 如果应用失败,则参考下面命令进行执行
[root@master01 1]# calicoctl apply -f rr-node.yaml
Failed to apply 'Node' resource: [update conflict: Node(node01)]

[root@master01 1]# calicoctl patch node node01 \
  --patch '{"spec": {"bgp": {"routeReflectorClusterID": "244.0.0.1"}}}'
Successfully patched 1 'Node' resource

3、配置路由反射器节点配置为对等

匹配所有节点带有这个标签的作为路由反射器,这就是非路由反射器和路由反射器建立关系

# 定义bgppeer.yaml文件
[root@master01 ~]# vim bgppeer.yaml
apiVersion: projectcalico.org/v3
kind: BGPPeer
metadata:
  name: peer-with-route-reflectors
spec:
  nodeSelector: all()
  peerSelector: route-reflector == 'true'

# 应用
[root@master01 ~]# calicoctl apply -f bgppeer.yaml
Successfully applied 1 'BGPPeer' resource(s)

查看节点的BGP连接状态

[root@master01 1]# calicoctl node status
Calico process is running.

IPv4 BGP status
+--------------+---------------+-------+----------+-------------+
| PEER ADDRESS |   PEER TYPE   | STATE |  SINCE   |    INFO     |
+--------------+---------------+-------+----------+-------------+
| 10.0.0.61    | node specific | up    | 06:34:03 | Established |
+--------------+---------------+-------+----------+-------------+

IPv6 BGP status
No IPv6 peers found.

查看规则

[root@master01 ~]# calicoctl get bgppeer
NAME                         PEERIP   NODE    ASN
peer-with-route-reflectors            all()   0

检测网络

[root@master01 ~]# ss -antp | grep ESTAB | grep 179 | grep bird
ESTAB      0      0      10.0.0.60:179                10.0.0.61:43417               users:((bird",pid=109145,fd=9))

[root@node01 ~]# ss -antp | grep ESTAB | grep 179 | grep bird
ESTAB      0      0      10.0.0.61:179                10.0.0.63:57845               users:((bird",pid=90875,fd=9))
ESTAB      0      0      10.0.0.61:43417              10.0.0.60:179                 users:((bird",pid=90875,fd=8))
ESTAB      0      0      10.0.0.61:179                10.0.0.64:38717               users:((bird",pid=90875,fd=12))
ESTAB      0      0      10.0.0.61:179                10.0.0.62:57069               users:((bird",pid=90875,fd=10))

当然rr和nginx也是一致的,也需要高可用,所以我们尽量配置2台以上的节点!这里新增node02节点

# 打标签
[root@master01 ~]# k label node node02  route-reflector=true

# 导出yaml文件
[root@master01 ~]# calicoctl get node node02 -oyaml > rr-node02.yaml

# 修改yaml文件
[root@master01 ~]# vim rr-node02.yaml
...
...
  bgp:
    ipv4Address: 10.0.0.62/24
    routeReflectorClusterID: 244.0.0.1 # 集群ID保证唯一性
...
...

# 应用
[root@master01 ~]# calicoctl apply -f rr-node02.yaml
Successfully applied 1 'Node' resource(s)

# 再次查看
[root@master01 1]# calicoctl node status
Calico process is running.

IPv4 BGP status
+--------------+---------------+-------+----------+-------------+
| PEER ADDRESS |   PEER TYPE   | STATE |  SINCE   |    INFO     |
+--------------+---------------+-------+----------+-------------+
| 10.0.0.61    | node specific | up    | 06:34:03 | Established |
| 10.0.0.62    | node specific | up    | 06:36:45 | Established |
+--------------+---------------+-------+----------+-------------+

IPv6 BGP status
No IPv6 peers found.

2.5 性能验证

Calico中BGP&IPIP&RR性能数据( qperf测试工具):测试分两阶段进行,分别测试“主机到pod”、“pod到pod”两种网络模型

Nginx测试方案

模式 网络模式 nginx文件大小 响应时间 流量 并发量
host to pod bgp 10k 1.026ms, 39.649ms 10K 10000
host to pod bgp 100M 534.611μs, 1.514ms 100M 100
host to pod ipip 10k 1.048ms, 28.248ms 10K 10000
host to pod ipip 100M 592.597μs, 1.858ms 100M 100
pod to pod bgp 10k 1.037ms, 43.26ms 10K 10000
pod to pod bgp 100M 546.812μs, 5.712ms 100M 100
pod to pod ipip 10k 1.585ms, 108.748m 10K 10000
pod to pod ipip 100M 573.216μs, 9.602ms 100M 100
  • 1、calico BGP模式相对于IPIP模式,约有5%网络传输速率的提升。
  • 2、calico BGP模式相对于IPIP模式,约有10%-30%延迟的减少。
  • 3、calico IPIP模式支持跨网段访问,BGP模式不支持跨网段访问。
  • 4、在nginx测试中,pod之间的小包延迟降低约33%
  • 5、在nginx测试中,pod之间的大包延迟降低约40%

结论:

  • calico使用BGP网络模式通信网络传输速率较好!
  • 但是跨节点后pod不能通信!

2.6 小结

  • Calico作为kubernetes的网络组件之一已经在云原生众多开源项目中脱颖而出。
  • Calico与flannel(大二层网络方案)对比,由于使用BGP网络协议代替二层网络中flannel进程的封包解包过程从而大大提高本身的传输性能;
  • Calico可以配合使用Network Policy做pod和pod之前的访问控制,对于实际生产环境也是非常重要的一项安全功能。

CNI 网络方案优缺点及最终选择:

先考虑几个问题:

1、需要细粒度网络访问控制?--> flannel不支持,calico支持(ACL);

2、追求网络性能? --> flannel(host-gw),calico(BGP);

3、当前架构下是否可以跑BGP协议? --> 公有云有些不支持;

4、集群规模多大? --> 100台node左右推荐(flannel,host-gw)维护方便;

5、是否有维护能力? --> calico维护复杂,路由表!