day05 K8S网络组件的深度剖析 (1.10.1 -1.10.3)

发布时间 2023-11-26 09:55:53作者: zhan0

一、K8S网络组件的深度剖析上

1、认识Flannel

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

优势:

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

劣势:

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

2、Flannel的三种后端实现

  • UDP模式(弃用):使用设备Flannel.0进行封包解包,不是内核原生支持,上下文切换较大,性能差
  • VXLAN:Overlay Network方案
  • Host-GW模式,纯三层网络方案

2.1 VXLAN(默认)

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

Fannel.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数据传输

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

2.2 节点内通信

节点内的容器间通信通过cin0 网桥完成,不涉及任何VCLAN报文的封装和解包

例如上图中,Node1的子网为10.244.0.1/24,PodA 10.244.0.20 和PodB 10.244.0.21 通过cni0实现互通

2.3 Host-GW模式

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

数据流传输流程

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

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

3、总结

VXLAN:

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

Host-gw:

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

二、K8S网络组件的深度剖析中

1、k8s网络组件

1.1、网络基础知识

广播域

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

ARP(地址解析协议)

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

三层交换机

  1. 二层交换机只工作在数据链路层
  2. 路由器这是工作在网络层
  3. 三层交换机可同时工作在数据链路层和网络层,并根据MAC地址或IP地址转发数据包

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

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

VLAN的主要好处

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

1.2 路由技术

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

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

功能

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

路由器的功能

  • 路由
  • zhuanf 
  • 隔离子网
  • 隔离广播域

路由

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

1.3 K8S网络模型

相关概念

  1. Linux在网络栈中引入网络命名空间,将独立的网络协议栈隔离到不同的命名空间中,彼此之间无法通信
  2. Docker利用这一特性,实现不同容器间的网络隔离
    Veth设备对:Veth设备对的引入是为了实现在不同网络命名空间的通信。
    Iptables/Netfilter:Docker使用Netfilter实现容器网络转发
    网桥(docker0):网桥是一个二层网络设备,通过网桥可以将Linux支持的不同的端口连接起来,并实现类似交换机那样的多对多的通信
    路由:Linux系统包含一个完整的路由功能,当IP层在处理数据发送或转发的时候,会使用路由表来决定发往哪里

容器间通信

  • 二层网络之间的通信

容器访问外网

  • 通过docker0,NAT转发到外网

1.4 Pod网络

infra Container

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

  1. K8S会在每个Pod先启动一个infra container 小容器,然后让其他容器连接进这个网络命名空间
  2. 其他容器看到的网络完全一样。即网络设备、IP地址、Mac地址等
  3. 在Pod的IP地址就是infra container的IP地址

Pod通信

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

  1. 两个Pod在同一个Node
  2. 两个Pod在不同的Node

两个Pod在同一个Node上

  1. 对于Pod1,eth0通过虚拟以太设备(Veth0)连接到root namespace
  2. 网桥cbr0中veth0配置一个网段。一旦数据包到达网桥,网桥使用ARP协议解析出正确的目标网段veth1
  3. 网桥cbr0将数据包发送到veth1
  4. 数据包到达veth1时,被直接转发Pod2的network namespace中的eth0网络设备

两个Pod在不同Node上

 

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

一次为了实现跨主机通信需求,需要部署网络插件,这些网络插件需要满足以下要求:

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

1.5 CNI(容器网络接口)

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

2、架构实现

Calico在每个计算节点都利用Linux Kernel实现了一个高效的vRouter来负责数据转发

每个vRouter 都通过BGP协议把在本节点上运行鹅容器的路由信息向整个Calico网络广播,并自动设置到达其他节点的路由转发规则

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

BGP举例:

 

  1. 在图中,有两个自治系统(autonous system,简称AS):AS1 和AS2
  2. 在互联网中,一个自治系统(AS)是一个有权自主地决定在本系统中应采用何种路由协议的小型单温
  3. 这个网络单位可是一个简单的网络也可是一个由一个或多个普通的网络管理员来控制的网络群体,他说一个独立的可管理的网络单元
  4. 一个自治系统也被称为路由选择域(routing domain)。一个自治系统将会分配一个全局的唯一的16位号码,这个号码也叫自治系统号(ASN)
  5. 在正常情况下,自治系统之间不会有任何来玩。如歌两个自治系统的主机,要通过IP地址直接进行通信,必须使用路由器把这两个自治系统连接起来。BGP协议就是让他们互联的一种方式。

Calico组件功能:

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

区别:

Flannel还有flanneld进程来维护路由信息

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

3、Calico架构图

Calico通过引导workload所有的流量至一个特殊的网关192..254.1.1 从而引流到host的calixx网络设备上,形成了二三层流量全部转换为host的三层流量转发

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

  1. 容器1的所有报文都会通过eth0发送到下一跳192.254.1.1
  2. 主机上的calixxx网卡收到报文后,再根据路由表转发
  3. 数据包通过tun0设备发送到下一跳,也就是容器2的宿主机192.168.2.132/32
  4. 通过路由表转发,接着才能够calixxx网卡发送到容器2

 

三、K8S网络组件的深度剖析下

4、Calico的具体实现

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

1) IPIP模式

和flannel的xvlan差不多,基于二层数据的封装和解封,也会创建一个虚拟网卡tunl0,把两个本来不通的网络通过点对点连接起来,都是一个负责的网络法案,IPIP和vxlan模式的性能基本接近。

2)BGP模式

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

路由反射模式Router Reflection(RR)

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

4.1 IPIP莫斯改为BGP模式

安装calicoctl

wget https://github.com/projectcalico/calico/releases/download/v3.25.0/calicoctl-linux-amd64
cp calicoctl-linux-amd64 /sbin/calicoctl 
chmod +x /sbin/calicoctl 
calicoctl  version
Client Version:    v3.25.0
Git commit:        3f7fe4d29
Cluster Version:   v3.25.0
Cluster Type:      k8s,bgp,kubeadm,kdd
[root@master-1-230 1]# calicoctl  get ippool -o wide
NAME                  CIDR            NAT    IPIPMODE   VXLANMODE   DISABLED   DISABLEBGPEXPORT   SELECTOR   
default-ipv4-ippool   10.244.0.0/16   true   Always     Never       false      false              all()
[root@master-1-230 1]# calicoctl  get ippool -o yaml >ippool.yaml

这里是启用了ipip模式,设置为never就是关闭了ipip模式就会采用BGP模式

[root@master-1-230 1]# cat ippool.yaml 
apiVersion: projectcalico.org/v3
items:
- apiVersion: projectcalico.org/v3
  kind: IPPool
  metadata:
    creationTimestamp: "2023-11-10T16:34:31Z"
    name: default-ipv4-ippool
    resourceVersion: "1225"
    uid: 2e57e0b5-7e49-4277-b945-f8ce96106e2a
  spec:
    allowedUses:
    - Workload
    - Tunnel
    blockSize: 26
    cidr: 10.244.0.0/16
    ipipMode: Never
    natOutgoing: true
    nodeSelector: all()
    vxlanMode: Never
kind: IPPoolList
metadata:
  resourceVersion: "222119"
[root@master-1-230 1]# cat ippool.yaml 
apiVersion: projectcalico.org/v3
items:
- apiVersion: projectcalico.org/v3
  kind: IPPool
  metadata:
    creationTimestamp: "2023-11-10T16:34:31Z"
    name: default-ipv4-ippool
    resourceVersion: "1225"
    uid: 2e57e0b5-7e49-4277-b945-f8ce96106e2a
  spec:
    allowedUses:
    - Workload
    - Tunnel
    blockSize: 26
    cidr: 10.244.0.0/16
    ipipMode: Never
    natOutgoing: true
    nodeSelector: all()
    vxlanMode: Never
kind: IPPoolList
metadata:
  resourceVersion: "222119"


[root@master-1-230 1]# calicoctl  apply -f ippool.yaml 
Successfully applied 1 'IPPool' resource(s)
[root@master-1-230 1]# calicoctl get ippool -o wide
NAME                  CIDR            NAT    IPIPMODE   VXLANMODE   DISABLED   DISABLEBGPEXPORT   SELECTOR   
default-ipv4-ippool   10.244.0.0/16   true   Never      Never       false      false              all()      

没有配置IP,可判断是否配置生效

[root@master-1-230 1]# ip addr
9: 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@master-1-230 1]# ip route
default via 192.168.1.1 dev ens33 proto static metric 100 
10.244.29.0/26 via 192.168.1.232 dev ens33 proto bird 
10.244.154.0/26 via 192.168.1.233 dev ens33 proto bird 
10.244.167.128/26 via 192.168.1.231 dev ens33 proto bird 

没有tul0路由,数据包到达宿主机上,根据路由表转发。和fannel的host-ge是一样的

4.2 BGP模式改为路由反射(Router Reflector)模式

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

查看路由信息:(集群4节点,如下节点还维护另外3条node节点路由)

[root@master-1-230 1]# calicoctl  node status
Calico process is running.

IPv4 BGP status
+---------------+-------------------+-------+----------+-------------+
| PEER ADDRESS  |     PEER TYPE     | STATE |  SINCE   |    INFO     |
+---------------+-------------------+-------+----------+-------------+
| 192.168.1.231 | node-to-node mesh | up    | 00:18:03 | Established |
| 192.168.1.232 | node-to-node mesh | up    | 00:18:03 | Established |
| 192.168.1.233 | node-to-node mesh | up    | 08:52:27 | Established |
+---------------+-------------------+-------+----------+-------------+

IPv6 BGP status
No IPv6 peers found.

BGPclient 有个bird进程负责维护BGP协议的通信完成路由表学习,随着连接数的增多,这两个也会增多使用的端口是179

[root@master-1-230 1]# netstat  -antp|grep ESTAB|grep bird
tcp        0      0 192.168.1.230:179       192.168.1.233:34712     ESTABLISHED 4167/bird           
tcp        0      0 192.168.1.230:179       192.168.1.232:49857     ESTABLISHED 4167/bird           
tcp        0      0 192.168.1.230:179       192.168.1.231:38444     ESTABLISHED 4167/bird

[root@node-1-231 ~]# netstat  -antp|grep ESTAB|grep bird
tcp        0      0 192.168.1.231:179       192.168.1.232:58241     ESTABLISHED 2899/bird           
tcp        0      0 192.168.1.231:38444     192.168.1.230:179       ESTABLISHED 2899/bird           
tcp        0      0 192.168.1.231:179       192.168.1.233:50025     ESTABLISHED 2899/bird           
您在 /var/spool/mail/root 中有新邮件

[root@node-1-232 ~]# netstat  -antp|grep ESTAB|grep bird
tcp        0      0 192.168.1.232:49857     192.168.1.230:179       ESTABLISHED 2825/bird           
tcp        0      0 192.168.1.232:179       192.168.1.233:34580     ESTABLISHED 2825/bird           
tcp        0      0 192.168.1.232:58241     192.168.1.231:179       ESTABLISHED 2825/bird    

[root@node-1-233 ~]#  netstat  -antp|grep ESTAB|grep bird
tcp        0      0 192.168.1.233:34580     192.168.1.232:179       ESTABLISHED 2861/bird           
tcp        0      0 192.168.1.233:34712     192.168.1.230:179       ESTABLISHED 2861/bird           
tcp        0      0 192.168.1.233:50025     192.168.1.231:179       ESTABLISHED 2861/bird   

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

Route Reflector模式下的实现:

从集群中找出多台性能好的节点,当做路由反射器,让其他BGP client通过这两个节点获取路由表信息,这两个路由反射器相党羽代理的角色,其他节点都是从这里获取路由表信息,name压力都在这两个节点,做路由的集中下发,BGP client就是从这里获取所有的路由表。每个节点只要和路由反射器建立关系就行,有两个路由反射去就建立两个链接。避免一个节点需要建立洽谈上千台节点损耗的问题

1、关闭node-to-node模式

关闭node to node 模式就代表网络不通 (一旦更改,集群网络虎断掉。线上操作要先评估。)

[root@master-1-230 1]# calicoctl  get bgpconfig
NAME   LOGSEVERITY   MESHENABLED   ASNUMBER   

[root@master-1-230 1]# calicoctl  get node -o wide
NAME           ASN       IPV4               IPV6   
master-1-230   (64512)   192.168.1.230/24          
node-1-231     (64512)   192.168.1.231/24          
node-1-232     (64512)   192.168.1.232/24          
node-1-233     (64512)   192.168.1.233/24   

调整AS编号

cat << EOF | calicoctl create -f -
 apiVersion: projectcalico.org/v3
 kind: BGPConfiguration
 metadata:
   name: default
 spec:
   logSeverityScreen: Info
   nodeToNodeMeshEnabled: false  
   asNumber: 63400
EOF

[root@master-1-230 1]# calicoctl  get bgpconfig
NAME      LOGSEVERITY   MESHENABLED   ASNUMBER   
default   Info          false         63400 

其他节点访问不了Pod

[root@master-1-230 1]# calicoctl node status
Calico process is running.

IPv4 BGP status
No IPv4 peers found.

IPv6 BGP status
No IPv6 peers found.

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

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

给路由器反射器节点打标签:

[root@master-1-230 1]# kubectl label node node-1-231 route-reflector=true
node/node-1-231 labeled

 给选定节点指定路由反射器ID: routeReflectorClusterID ,可以是集群中没有使用的IP

[root@master-1-230 1]# calicoctl  get node node-1-231 -o yaml >rr-node.yaml

vim rr-node.yaml
  bgp:
    ipv4Address: 192.168.1.231/24
    routeReflectorClusterID: 244.0.0.1 # 集群ID,保证唯一性
    
[root@master-1-230 1]# calicoctl  apply -f rr-node.yaml 
Successfully applied 1 'Node' resource(s)

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

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

# cat bgppeer.yaml
apiVersion: projectcalico.org/v3
kind: BGPPeer
metadata:
  name: peer-with-route-reflectors
spec:
  nodeSelector: all()
  peerSelector: route-reflector == 'true'
  
  
[root@master-1-230 1]# calicoctl  apply -f bgppeer.yaml 
Successfully applied 1 'BGPPeer' resource(s)

 查看节点的BGP连接状态:

[root@master-1-230 1]# calicoctl  node status
Calico process is running.

IPv4 BGP status
+---------------+---------------+-------+----------+-------------+
| PEER ADDRESS  |   PEER TYPE   | STATE |  SINCE   |    INFO     |
+---------------+---------------+-------+----------+-------------+
| 192.168.1.231 | node specific | up    | 14:11:55 | Established |
+---------------+---------------+-------+----------+-------------+

IPv6 BGP status
No IPv6 peers found.

查看规则

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

现在网络可以通了

[root@master-1-230 1]# ss -antp|grep ESTAB|grep 179|grep bird
ESTAB      0      0      192.168.1.230:56741              192.168.1.231:179                 users:(("bird",pid=4167,fd=9))
[root@master-1-230 1]# 

[root@node-1-232 ~]# ss -antp|grep ESTAB|grep 179|grep bird
ESTAB      0      0      192.168.1.232:36881              192.168.1.231:179                 users:(("bird",pid=2825,fd=8))
您在 /var/spool/mail/root 中有新邮件
[root@node-1-232 ~]# 

[root@node-1-233 ~]# ss -antp|grep ESTAB|grep 179|grep bird
ESTAB      0      0      192.168.1.233:51962              192.168.1.231:179                 users:(("bird",pid=2861,fd=8))

rr和nginx一样需要高可用,我们配置2台以上节点。如果运行最好找2台单独服务器!

[root@master-1-230 1]# kubectl label node node-1-232 route-reflector=true
node/node-1-232 labeled

[root@master-1-230 1]# calicoctl  get node node-1-232 -o yaml >rr-node2.yaml

[root@master-1-230 1]# cat rr-node2.yaml
  bgp:
    ipv4Address: 192.168.1.232/24
    routeReflectorClusterID: 244.0.0.2
    
[root@master-1-230 1]# calicoctl  apply -f rr-node2.yaml 
Successfully applied 1 'Node' resource(s)

再次查看node状态

[root@master-1-230 1]# calicoctl  node status
Calico process is running.

IPv4 BGP status
+---------------+---------------+-------+----------+-------------+
| PEER ADDRESS  |   PEER TYPE   | STATE |  SINCE   |    INFO     |
+---------------+---------------+-------+----------+-------------+
| 192.168.1.231 | node specific | up    | 14:11:56 | Established |
| 192.168.1.232 | node specific | up    | 14:20:14 | Established |
+---------------+---------------+-------+----------+-------------+

IPv6 BGP status
No IPv6 peers found.

5、性能验证

Calico中BGP 、IPIP、RR性能数据(qperf测试工具):测试分两阶段:主机到pod、pod到pod

结论:

  • calico使用BGP网络模式通信网络传输效率较高
  • 但是跨节点后Pod不能通信

6、总结:

CNI网络方案优缺点:

  1. 需要细粒度网络访问控制?         fannel不支持,calico支持(ACL)
  2. 追求网络性能?    flannel(host-gw) calico(BGP)
  3. 当前架构是否可以支持BGP协议?   有些公有云不支持
  4. 集群规模大小?  100台node 推荐(fannel,host-gw)维护方便
  5. 是否有维护能力?    calico维护复杂,路由表!