参考
补充内容
- 本篇文章主要为入门理解,可能部分有些误差或不够全面,若想更详细的内容,可以查看下面的文章
- 【k8s网络】梳理cni发展脉络-CSDN博客
calico几种模式对比
注意 Calico 不会有任何网桥!!!
会为每一个容器创建一个Veth pair 设备,一端在容器内,一端设置到宿主机上
数据的转发,靠 Calico 维护的路由规则
模式 | 数据包封包 | 优点 | 缺点 |
---|---|---|---|
vxlan | 封包, 在vxlan设备上将pod发来的数据包源、目的mac替换为本机vxlan网卡和对端节点vxlan网卡的mac。外层udp目的ip地址根据路由和对端vxlan的mac查fdb表获取 | 只要k8s节点间三层互通, 可以跨网段, 对主机网关路由没有特殊要求。各个node节点通过vxlan设备实现基于三层的”二层”互通, 三层即vxlan包封装在udp数据包中, 要求udp在k8s节点间三层可达;二层即vxlan封包的源mac地址和目的mac地址是自己的vxlan设备mac和对端vxlan设备mac。 | 需要进行vxlan的数据包封包和解包会存在一定的性能损耗 |
ipip | 封包,在tunl0设备上将pod发来的数据包的mac层去掉,留下ip层封包。 外层数据包目的ip地址根据路由得到。 | 只要k8s节点间三层互通, 可以跨网段, 对主机网关路由没有特殊要求。 | 需要进行ipip的数据包封包和解包会存在一定的性能损耗 |
bgp | 不需要进行数据包封包 | 不用封包解包,通过bgp协议可实现pod网络在主机间的三层可达, k8s节点不跨网段时和flannel的host-gw相似; 支持跨网段, 满足复杂的网络架构 | 跨网段时,需要主机网关路由也充当BGP Speaker能够学习到pod子网路由并实现pod子网路由的转发 |
其中Vxlan模式和ipip模式都可以设置crosssubnet, 即在跨网段的k8s节点的pod间通信时才使用vxlan或ipip进行封包, 同一网段的8s节点的pod间通信则直接使用bgp模式。使用同网段内的k8s节点作为BGP Speaker全互联交换各自的pod子网路由实现互通, 避免封包。
性能比较
fannel三种模式 | 效率 | calico 模式 |
---|---|---|
UDP(已废弃) | 性能较差,封包解包涉及到多次用户态和内核态交互 | 无 |
VXLAN | 性能较好,封包解包在内核态实现,内核转发数据,flanneld负责动态配置ARP和FDB(转发数据库)表项更新 | 类似IPIP |
host-gw | 性能最好,不需要再次封包,正常发包,目的容器所在的主机充当网关 flanneld 负责主机上路由表的刷新 | 类似 BGP |
vxlan
什么是VXLAN?
VXLAN,即Virtual Extensible LAN(虚拟可扩展局域网),是Linux本身支持的一网种网络虚拟化技术。VXLAN可以完全在内核态实现封装和解封装工作,从而通过“隧道”机制,构建出覆盖网络(Overlay Network)
VXLAN的设计思想是:
在现有的三层网络之上,“覆盖”一层虚拟的、由内核VXLAN模块负责维护的二层网络,使得连接在这个VXLAN二层网络上的“主机”(虚拟机或容器都可以),可以像在同一个局域网(LAN)里那样自由通信。
为了能够在二nfcu网络上打通“隧道”,VXLAN会在宿主机上设置一个特殊的网络设备作为“隧道”的两端,叫VTEP:VXLAN Tunnel End Point(虚拟隧道端点)
简而言之:
- 不需要关注 VTEP 与 VTEP 设备之间的通信(如何跨网段,如何进行三层网络的连通)
- 只需关注,将数据包传给当前 VTEP 设备后,如何获取目的 VTEP 的 MAC 地址,完成二层通信
基于三层的”二层“通信
三层 —— 指的是实际物理网络架构
”二层“通信 —— 指的是,需要维护「MAC 地址级别的信息」,即「虚拟IP」与「MAC 地址」的映射关系
基于三层的”二层“通信 —— 可实现跨网段的 Pod 通信
- 基于三层 —— 指的是利用三层网络进行跨网段通信 —— 也就是不同 VTEP 设备之间的通信 —— 这个通信的路径不需要进行考虑(VTEP 设备会自动处理)
- ”二层“通信 —— 主要是需要知道「目的 VTEP 设备的 MAC 地址」(类似与 ARP 获得 MAC 地址),之后完成通信
- 知道对方 MAC 便可直接完成通信, 这种类似二层通信
- 但是主要是 —— 如何由「目的容器 IP 」知道「目的 VTEP 设备的 MAC 地址」?传统网络是通过 ARP 协议
- 对于 Calico 则是通过「路由规则」
- 维护「每个 k8s 节点上 Pod 网段」 与 「节点上 VTEP 设备的 MAC 地址」的对应关系
- 因此知道 「目的容器 IP 」—— 便可判断在哪个「Pod 网段」—— 从而知道对应的「VTEP 设备的 MAC 地址」
通信总体流程解析
基础封包解包知识
封包是「自顶向下的」,解包是「自底向上的」
简单描述封包:
- 原始数据 —— 应用发送的一些数据 —— 基础数据单元
- 传输层封包 —— UDP、TCP 协议等 —— 添加「源、目的端口」,可以称之为「数据段」
- 网络层封包 —— IP 协议 —— 添加 「源、目的 IP」,可以称之为「数据包」
- 链路层封包 —— 以太网协议 —— 添加「源、目的 MAC 地址」,可以称之为「数据帧」
简单描述解包(反着来):
- 链路层解包 —— 拆去 MAC 包头 —— 传给网络层
- 网络层解包 —— 拆去 IP 包头 —— 传给传输层
- 传输层解包 —— 插曲 UDP/TCP 包头 —— 传到对应「目的端口」的应用
- 目的应用 获得真正数据
VXLAN 和 UDP 包结构
对比之下,可以看出:
-
外层以太网头(就是源、目的MAC地址)—— 相同 —— UDP 也具有,这里没画出来而已
-
外层 IP 头 —— 都具有
-
UDP 头 —— 都具有
-
因此不同的就是后面几部分 「VXLAN头,内侧以太网头、内层 IP 头、负载」,「UDP数据」
-
用 UDP 协议理解就是, 「VXLAN头,内侧以太网头、内层 IP 头、负载」 —— 相当于「UDP数据」
- 相当于用 UDP 封装一个 「VXLAN 数据包」
- 这里简单将 「VXLAN头,内侧以太网头、内层 IP 头、负载」 称为 「VXLAN 数据包」 —— 这是下文的基础
- 其实应该是整体(包含外层以太网头等)称为「VXLAN 数据包」
-
所以可以简单认为 「VXLAN协议相比于 UDP 多了更多控制功能,毕竟相当于将 UDP数据 分了 四层」
-
那么这么分配的原因是为了什么呢?
-
原因就是:宿主机的「虚拟IP」(如 Pod IP,容器IP等)无法利用「基础物理网络」进行「跨网段通信」
-
-
这四部分的作用是什么呢?
- 因为这么分配后,UDP 设备不能识别,所以需要一个新设备部署到宿主机上 —— 「VTEP设备」
- 宿主机支持 VXLAN 协议,因此通过 「VXLAN头」知道该传输给哪个「VTEP设备」
- 「VTEP设备」发现「内层以太网头」(即MAC地址)是自己,进行拆除
- 之后「VTEP设备」将「内层 IP 头、负载」传给下一个「网络处理设备」
- 这个「网络处理设备」由不同网络方案进行实现,calico就是「虚拟路由器」,fannel 就是「网桥」
- 之后这个「网络处理设备」进行解包,将真正的「负载」数据传输给应用
-
通信总体流程
我们结合这个 VXLAN 数据包结构进行讲解
下文基于这样讲解
- 简单将 「VXLAN头,内侧以太网头、内层 IP 头、负载」 称为 「VXLAN 数据包」
上面的「目的容器 IP 」,在这用「目的 Pod IP」这个概念
因为在 k8s 中,Pod 是最基础的运行单元,Pod 封装了容器,你可以把 「目的 Pod IP」近似看做「目的容器 IP 」
-
通过「目的 Pod IP」—— 得知「目的 VTEP 设备的 MAC 地址」 —— 「源 VTEP 设备」根据得到的信息构建 Vxlan 数据包
-
如何得知呢?
-
calico 会维护 「目的 Pod IP 网段」 —— 「目的 VTEP 设备的 MAC 地址」的路由条目,因此进行匹配后便可得知
-
fannel 会维护一个数据库,存储着 「目的 Pod IP 网段」 —— 「目的 VTEP 设备的 MAC 地址」的信息,因此也可以得知
-
因为这个过程我们需要管理,但需要「维护 Pod IP 与 VTEPS 设备 MAC 地址 的映射关系」,也就类似二层通信中的 ARP 广播
所以我们称之为 —— ”二层“通信
-
-
之后「源 VTEP 设备」 —— 会将此「 Vxlan 数据包」进行「UDP封装」,其中「 Vxlan 数据包」会视为「UDP数据包的基础数据信息」
-
封装 UDP 数据包 —— 用于三层网络通信,即跨网段 —— 也就是 VTEP 设备间的通信
-
可以把 VTEP 设备封装的 「 Vxlan 数据包」看做为 「UDP封包中的基础数据单元,或 UDP 的负载」
-
之后就属于传统网络的 UDP 发包过程,从「一台主机的VTEP 设备」发送到「另一台主机的 VTEP 设备」
-
这个过程我们不需要管理,仿佛直接将「 Vxlan 包 」直接传递到了「目标 VTEP 设备」,没有感知且不需要维护中间复杂的流程(UDP封包、拆包等),因此称之为 ——「 Vxlan 隧道」
实际上的 UDP 包发送和接收需要走「三层网络」—— 因此称之为 —— 三层通信
到此我们就全部理解了 —— 基于三层的”二层“通信
-
-
之后此封装好的「UDP数据包」,将会通过三层网络,到达目的容器所在的主机的「目的VTEP设备」
- 「UDP数据包」经过拆包后,「目的 VTEP 设备」 便获得了 「源 VTEP 设备」发来的「Vxlan数据包」
-
目的容器所在的主机的「VTEP设备」会进行解包,根据「 Vxlan 数据包」的内容及相应的路由规则,发送给对应的Pod 或容器
- 「VTEP设备」 将「Vxlan数据包」拆包后,会获得「目的 Pod 的 IP 信息」,之后根据「目的 Pod 的 IP 信息」便会转发到「相应的 Pod(也就是容器,可视为一样的概念)」
- 如何根据「目的 Pod 的 IP 信息」转发到「相应的 Pod(也就是容器,可视为一样的概念)」?
- calico有相应「路由规则」,会根据「目的 Pod 的 IP 信息」转发到对应的「calib开头的网卡」(此设备时 veth-pair),因此便可直接到达「容器内(也就是 veth-pair 的另一端)」
- fannel 的「目的VTEP设备」拆除「Vxlan 数据包的 Vxlan头」后,会直接将数据包转发给「docker0 网桥」(可理解为交换机,维护着 Pod IP、MAC 与端口的对应关系),因此可以直接将数据包转发到「容器内(容器也是通过veth-pair连接到docker0网桥上的)」
VXLAN 隧道
将「 Vxlan 包 」从「一个 VTEP 设备」传到「另一个 VTEP 设备」,利用 UDP 协议进行三层网络传输 —— 不要考虑封包解包
仿佛直接将「 Vxlan 包 」直接传递到了「目标 VTEP 设备」,没有感知且不需要维护中间复杂的流程(UDP封包、拆包等),因此称之为 ——「 Vxlan 隧道」
Fannel VXLAN 模式通信流程图
Calico IPIP 模式通信流程图
Fannel UDP 模式通信流程图
小结
- 但是其中 flannel UDP 涉及到 内核态和用户态切换较多,性能损耗大于 flannel VXLAN 模式
- flannel UDP 模式现在基本上被废弃了
- flannel VXLAN 模式性能应该和 calico IPIP 差不多
BGP
fannel-hostgw 只支持二层网络,不支持三层网络,因为路由器中不存在 【Pod IP】—— 【宿主机MAC地址】的映射信息
Calico BGP 解决了此问题,支持 BGP 的路由器中也会存储着 【Pod IP】—— 【宿主机MAC地址】的映射信息
- 因此知道该如何转发
- 这个信息的分发和维护,是BGP的内在机制 (好像是 Brid 组件)
fannel host-gw
- 必须二层连通
- Pod 通信时相当于,把对方的宿主机当做网关
- 本机上会有路由规则: 【对方 Pod IP 段】 —— 【对方主机 MAC 地址】
- 这样本机 Pod 要发送给对方 Pod,就会直接发给对方主机,对方主机上当然会有自己所有 Pod 的路由信息,这样完成了通信
- 同样,对方需要发回数据时,也是直接将数据发到本宿主机上,然后转发给对应的 Pod
- 封装的数据包为 【对方主机mac地址】【Pod IP 地址】【端口】 【数据信息】
- 因此这样要求必须二层连通,直接可以到达对方宿主机
- 若是三层,中间的路由器不认识【Pod IP 地址】,也无法解析到【下一跳】,因此【不知道该发到哪】,所以只能二层连通
- 不过 Calico BGP 解决了此问题,支持 BGP 的路由器中也会存储着 【Pod IP】—— 【宿主机MAC地址】的映射信息
- 因此知道该如何转发
- 这个信息的分发和维护,是BGP的内在机制 (好像是 Brid 组件)