type
status
date
slug
summary
tags
category
icon
password
写在前面
CNI插件聚焦的是pod间的通信,本文主要讲的是CNI插件的部分实现方案。但仅使用此插件还有一个问题:pod 是经常变化的,故出现了service(kube-proxy)。作为service的补充,又出现ingress等方案。当然,还有更强大的server mesh解决方案。
service的缺陷:
- 首先,如果转发的 pod 不能正常提供服务,它不会自动尝试另一个 pod,当然这个可以通过
readiness probes
来解决。每个 pod 都有一个健康检查的机制,当有 pod 健康状况有问题时,kube-proxy 会删除对应的转发规则。
- 另外,
nodePort
类型的服务也无法添加 TLS 或者更复杂的报文路由机制。
1. k8s跨主机的网络实现
在 Docker 的默认配置下,不同宿主机上的容器通过 IP 地址进行互相访问是根本做不到的。为了解决这个问题,社区中出现了很多网络方案。同时k8s为了更好的控制网络的接入,推出了CNI即容器网络的API接口。
实际上CNI的容器网络通信流程跟前面的基础网络一样,只是CNI维护了一个单独的网桥来代替 docker0。这个网桥的名字就叫作:CNI 网桥,它在宿主机上的设备名称默认是:cni0。cni的设计思想,就是:Kubernetes 在启动 Infra 容器之后,就可以直接调用 CNI 网络插件,为这个 Infra 容器的 Network Namespace,配置符合预期的网络栈。
CNI插件三种网络实现模式:
- overlay (基于隧道)模式是基于隧道技术实现的,整个容器网络和主机网络独立,容器之间跨主机通信时将整个容器网络封装到底层网络中,然后到达目标机器后再解封装传递到目标容器。不依赖与底层网络的实现。实现的插件有flannel(UDP、vxlan)、calico(IPIP)等等
- 三层路由模式(基于路由)中容器和主机也属于不通的网段,他们容器互通主要是基于路由表打通,无需在主机之间建立隧道封包。但是限制条件必须依赖大二层同个局域网内。实现的插件有flannel(host-gw)、calico(BGP)等等
- underlay网络是底层网络,负责互联互通。 容器网络和主机网络依然分属不同的网段,但是彼此处于同一层网络,处于相同的地位。整个网络三层互通,没有大二层的限制,但是需要强依赖底层网络的实现支持.实现的插件有calico(BGP)等等
2. flannel插件
Kubernetes系统上Pod网络的实现依赖于第三方插件,而Flannel是由CoreOS主推的目前比较主流的容器网络解决方案,CNI插件有两种功能:网络配置和网络策略,由于flannel比较简单,并不支持网络策略,flannel项目自身只是一个框架,真正提供网络功能的是它的后端实现,目前,Flannel支持三种不同后端实现,分别是:
- UDP
- VXLAN(默认方案)
- host-gw
- Directrouting(VXLAN的另一种方案)
2.1 VXLAN模式
UDP是Flannel项目最早支持的一种方式,是性能最差的方式,目前已被废弃。用的最多的是
VXLAN
和host-gw
模式的部署。相比于两台宿主机之间的直接通信,基于 Flannel UDP 模式的容器通信多了一个额外的步骤,即 flanneld 的处理过程。而这个过程,由于使用到了 flannel0 这个 TUN 设备,仅在发出 IP 包的过程中,就需要经过三次用户态与内核态之间的数据拷贝,如下所示:
UDP 和 VXLAN 模式对比:
都是在现有的物理网络之上,通过软件创建一层虚拟的覆盖网络(Overlay Network),把不同宿主机上创建的虚拟设备连通,从而达到容器跨主机通信的目的。在每一个节点上启动flanneld进程,分配子网,创建虚拟设备,添加路由规则,维护相关表等。
模式 | OSI | 虚拟设备 | 拷贝次数 | 封装/解封装 | 维护表 | 内核原生支持 |
UDP | 三层 | flannel0(TUN) | 三次 | flanneld在用户态完成 | etcd
route | 否 |
VXLAN | 二层 | flannel.1(VTEP) | 一次 | flannel.1在内核态完成 | etcd、route
ARP、FDB | 是 |
VXLAN用的是大二层overlay网络模式,可以把flannel.1和cni0看成一个整体,如下图。和传统docker容器里的docker0网桥相比,docker0网桥只能让同一台节点的容器互通,而overlay网桥可以让整个集群的容器互通。
2.2 host-gw模式
由于VXLAN还存在额外的封包解包,导致其性能仍有部分损耗,所以Flannel就有了host-gw模式,即把宿主机eth0当作网关,除了本地路由之外没有额外开销,性能和calico差不多,由于没有叠加来实现报文转发,这样会导致路由表庞大。因为一个节点对应一个网络,也就对应一条路由条目。
根据实际的测试,host-gw 的性能损失大约在 10% 左右,而其他所有基于 VXLAN“隧道”机制的网络方案,性能损失都在 20%~30% 左右。
host-gw虽然VXLAN网络性能要强很多,但是种方式有个缺陷:要求各物理节点必须在同一个二层网络中,物理节点必须在同一网段中。这样会使得一个网段中的主机量会非常多,万一发一个广播报文就会产生干扰。在私有云场景下,宿主机不在同一网段是很常见的状态,所以就不能使用host-gw了。
2.3 Directrouting模式
VXLAN还有另外一种功能,VXLAN也支持类似host-gw的玩法:如果两个节点在同一网段时使用host-gw通信,如果不在同一网段中,即当前pod所在节点与目标pod所在节点中间有路由器,就使用VXLAN这种方式,使用叠加网络。
结合了Host-gw和VXLAN,这就是VXLAN的Directrouting模式
因此Flannel的VXLAN模式有两种:
- VXLAN: 原生的VXLAN,即扩展的虚拟LAN
- Directrouting:直接路由型
Directrouting模式设置:修改下载的kube-flannel.yml,将flannel的configmap对象改为
net-conf.json: | { "Network": "10.244.0.0/16", #默认网段 "Backend": { "Type": "VXLAN", # 注意格式 "Directrouting": true } }