逃脱只会部署集群系列 —— k8s集群的网络模型与跨主机通信

        

目录

一、k8s集群的网络环境的要求

二、k8s集群网络通信流向图

三、k8s集群网络通信流程分析 

1、如何满足集群Pod IP唯一

2、pause容器创建共享命名空间

3、pod网络插入网桥bridge

4、数据包本方通过vxlan隧道发送出去

5、数据包对方接收到解包

6、说说整个过程角色的充当

7、利用host-gw模式提升集群网络性能


原理类文章比比皆是,这里主要是利用自身理解将集群跨主机通信进行一遍梳理,属于总结性,建议多看几篇原理性介绍,然后看结论,豁然开朗。

首先确认下

一、k8s集群的网络环境的要求

1. CNI要求,集群中的每个Pod都必须分配唯一的Pod IP

2. k8s集群内的通信不是vxlan点对点通信,因为集群内的所有节点之间都需要互联

二、k8s集群网络通信流向图

        下面我们根据图片详细描述下集群网络要求实现过程:

三、k8s集群网络通信流程分析 

1、如何满足集群Pod IP唯一

既然要求POD地址唯一,flannel如何为每个节点分配唯一地址段:

        flannel部署时需要指定一个网段,本环境为10.244.0.0,然后每个节点部署flannel都会分配一个子网段,如图master节点pod地址永远是10.244.0.x,node1节点pod地址永远是10.244.1.x,node2节点pod地址永远是10.244.2.x,这样就不会存在重复现象了;

        节点之间通信时,利用route -n查看路由规则,master内部容器通信直接通过cni0路由,master访问node1时通过flannel.1路由即可

[root@k8s-master ~]# kubectl -n kube-system exec kube-flannel-ds-pbqj4 cat /etc/kube-flannel/net-conf.json
{
  "Network": "10.244.0.0/16",
  "Backend": {
    "Type": "vxlan"
  }
}
[root@k8s-master ~]# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
10.224.0.0      0.0.0.0         255.255.255.0   U     0      0        0 cni0
10.224.1.0      10.224.1.0      255.255.255.0   UG    0      0        0 flannel.1
10.224.2.0      10.224.2.0      255.255.255.0   UG    0      0        0 flannel.1
172.17.0.0      0.0.0.0         255.255.0.0     U     0      0        0 docker0
[root@k8s-master ~]# kubectl get po -owide -A
NAMESPACE     NAME                                 READY   STATUS    RESTARTS   AGE   IP              NODE         NOMINATED NODE   READINESS GATES
default       busybox-5d7b4b65d6-mk6c6             1/1     Running   0          16m   10.224.1.2      k8s-node1    <none>           <none>
kube-system   coredns-5644d7b6d9-7gw6t             1/1     Running   5          9d    10.224.0.11     k8s-master   <none>           <none>
kube-system   coredns-5644d7b6d9-vd5vk             1/1     Running   5          9d    10.224.0.10     k8s-master   <none>           <none>
[root@k8s-master ~]# cat /run/flannel/subnet.env 
FLANNEL_NETWORK=10.244.0.0/16
FLANNEL_SUBNET=10.224.0.1/24
FLANNEL_MTU=1450
FLANNEL_IPMASQ=true

2、pause容器创建共享命名空间

        k8s集群中每个pod对应pause容器创建的共享命名空间,实现容器互通,所以由图看来,所谓的集群跨主机通信的对象时POD,内部容器已经实现互通了,现在只要一致对外接口通信即可。找个图理解下。 

3、pod网络插入网桥bridge

        什么是虚拟网桥,就是用来集合容器网络然后统一分配,目的是给容器通信提供一个统一的调度,这里的网桥就是指cni0,cni0本质和docker0一样,容器所有通信全部要经过cni0,并且判断内部通信直接用cni0就可以了,毕竟pod都在同一座桥上,大家请留步,跨主机则继续下一步。

[root@k8s-master ~]# brctl show
bridge name	bridge id		STP enabled	interfaces
cni0		8000.86355d489a2a	no		veth523f7aca
							            veth8e5df844
                                        veth6e1df844
                                        veth9e4df844
docker0		8000.02426bf09add	no	

4、数据包本方通过vxlan隧道发送出去

        VXLAN 全称是虚拟可扩展的局域网( Virtual eXtensible Local Area Network),主要作用通过三层的网络来搭建虚拟的二层网络,VXLAN本质上是一种隧道技术,在源网络设备与目的网络设备之间的IP网络上,建立一条逻辑隧道,将用户侧报文经过特定的封装后通过这条隧道转发。从用户的角度来看,接入网络的服务器就像是连接到了一个虚拟的二层交换机的不同端口上。
         VTEP(VXLAN Tunnel Endpoints,VXLAN隧道端点)是VXLAN网络的边缘设备,是VXLAN隧道的起点和终点,VXLAN对用户原始数据帧的封装和解封装均在VTEP上进行。在K8s中对应的就是flannel.1
        VNI(VXLAN Network Identifier):VNI 是每个 vxlan 的标识,一般每个 VNI 对应一个租户,flannel.1的.1就是所谓的标识
        什么意思,要是一家人到了cni0就可以相互通信了,跨主机通信时cni0网桥通过路由信息确定目标,当前两个节点只有三层互通也就是IP地址互通,vxlan隧道就是将网络请求发送到vtep,vtep记录着A和B的地址mac之类的信息,通过封包后利用ens33网卡,A把数据包发送到B的ens33网卡。

VXLAN结构图: 

 

 VXLAN点对点的劣势:

5、数据包对方接收到解包

       B收到发送的封包后到达B.flannel.1站点,一看你的标识符是1,我也是1,对上了,开始解包,包解出来就可以看到A的地址等信息,我也不认识啊,交给路由,再到B的网桥,最终实现通信。反之亦然。至于flannel在这个过程的作用呢,因为vxlan默认是点对点模式,k8s集群自带etcd集群,flannel部署在节点上可以采集地址mac等信息上报,实现分布式注册中心,这也是flannel.1充当vtep的原因。

6、说说整个过程角色的充当

pause容器:创建个虚拟网络空间,给同一个pod内的容器找个家

cni0:网桥bridge角色,容器流量的出入口,容器通信的指挥官

flannel.1:vtep角色,解决vxlan单点问题,封包解包,利用.1标识符匹配

ens33:网络通信的实际接口,二层不给力只能封装起来从这走了

flannel:节点agent,记录主机信息上报etcd,维护flannel.1上面,保证其解包时都认识

vxlan:虚拟隧道技术,偷天换日的指挥官,实现了虚拟二层通信,也就是双方vtep直接通信

7、利用host-gw模式提升集群网络性能

        vxlan模式适用于三层可达的网络环境,对集群的网络要求很宽松,但是同时由于会通过VTEP设备进行额外封包和解包,因此给性能带来了额外的开销。

        host-gw目的其实就是将本机的cni0网桥的流量送到目的主机的cni0网桥。实际上有很多集群是部署在同一二层网络环境下的,可以直接利用二层的主机当作流量转发的网关。这样的话,可以不用进行封包解包,直接通过路由表去转发流量。

        什么意思,就是不用封包解包二层--三层--对方三层--对方二层了,一看大家原来可以直接通信啊,直接二层cni0通信即可,怎么判断我是二层可达还是三层可达呢?

1、走二层就是两端的接口的模式都在bridge网桥模式,通过access或trunk的方式互联。

2、走三层就是两端的接口模式都在route路由模式,直接在接口配置IP地址互联。

通俗理解,二层就同一网段查MAC转发,三层就是跨网段查路由转发,要是同一网段,果断用host-gw模式吧!

为什么三层可达的网络不直接利用网关转发流量?

内核当中的路由规则,网关必须在跟主机当中至少一个 IP 处于同一网段。
由于k8s集群内部各节点均需要实现Pod互通,因此,也就意味着host-gw模式需要整个集群节点都在同一二层网络内。

修改flannel的网络后端:

$ kubectl edit cm kube-flannel-cfg -n kube-system
...
net-conf.json: |
    {
      "Network": "10.244.0.0/16",
      "Backend": {
        "Type": "host-gw"
      }
    }
kind: ConfigMap
...
重建Flannel的Pod

$ kubectl -n kube-system delete po kube-flannel-ds-amd64-5dgb8 kube-flannel-ds-amd64-c2gdc kube-flannel-ds-amd64-t2jdd
# 等待Pod新启动后,查看日志,出现Backend type: host-gw字样
$  kubectl -n kube-system logs -f kube-flannel-ds-amd64-4hjdw
I0704 01:18:11.916374       1 kube.go:126] Waiting 10m0s for node controller to sync
I0704 01:18:11.916579       1 kube.go:309] Starting kube subnet manager
I0704 01:18:12.917339       1 kube.go:133] Node controller sync successful
I0704 01:18:12.917848       1 main.go:247] Installing signal handlers
I0704 01:18:12.918569       1 main.go:386] Found network config - Backend type: host-gw
I0704 01:18:13.017841       1 main.go:317] Wrote subnet file to /run/flannel/subnet.env
​
查看节点路由表:

$ route -n 
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
10.244.0.0      0.0.0.0         255.255.255.0   U     0      0        0 cni0
172.17.0.0      0.0.0.0         255.255.0.0     U     0      0        0 docker0

猜你喜欢

转载自blog.csdn.net/weixin_39855998/article/details/121412168