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 地址」
通信总体流程解析
基础封包解包知识
封包是「自顶向下的」,解包是「自底向上的」
简单描述封包:
1.原始数据 —— 应用发送的一些数据 —— 基础数据单元
2.传输层封包 —— UDP、TCP 协议等 —— 添加「源、目的端口」,可以称之为「数据段」
3.网络层封包 —— IP 协议 —— 添加 「源、目的 IP」,可以称之为「数据包」
4.链路层封包 —— 以太网协议 —— 添加「源、目的 MAC 地址」,可以称之为「数据帧」
简单描述解包(反着来):
1.链路层解包 —— 拆去 MAC 包头 —— 传给网络层
2.网络层解包 —— 拆去 IP 包头 —— 传给传输层
3.传输层解包 —— 插曲 UDP/TCP 包头 —— 传到对应「目的端口」的应用
4.目的应用 获得真正数据
VXLAN和UDP包结构
对比之下,可以看出:
1.外层以太网头(就是源、目的MAC地址)—— 相同 —— UDP也具有,这里没画出来而已
2.外层IP头 —— 都具有
3.UDP头 —— 都具有
4.因此不同的就是后面几部分「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 」
1.通过「目的 Pod IP」—— 得知「目的 VTEP 设备的 MAC 地址」 —— 「源 VTEP 设备」根据得到的信息构建 Vxlan 数据包
如何得知呢?
calico 会维护 「目的 Pod IP 网段」 —— 「目的 VTEP 设备的 MAC 地址」的路由条目,因此进行匹配后便可得知
fannel 会维护一个数据库,存储着 「目的 Pod IP 网段」 —— 「目的 VTEP 设备的 MAC 地址」的信息,因此也可以得知
因为这个过程我们需要管理,但需要「维护 Pod IP 与 VTEPS 设备 MAC 地址 的映射关系」,也就类似二层通信中的 ARP 广播
所以我们称之为 —— ”二层“通信
2.之后「源 VTEP 设备」 —— 会将此「 Vxlan 数据包」进行「UDP封装」,其中「 Vxlan 数据包」会视为「UDP数据包的基础数据信息」
封装 UDP 数据包 —— 用于三层网络通信,即跨网段 —— 也就是 VTEP 设备间的通信
可以把 VTEP 设备封装的 「 Vxlan 数据包」看做为 「UDP封包中的基础数据单元,或 UDP 的负载」
之后就属于传统网络的 UDP 发包过程,从「一台主机的VTEP 设备」发送到「另一台主机的 VTEP 设备」
这个过程我们不需要管理,仿佛直接将「 Vxlan 包 」直接传递到了「目标 VTEP 设备」,没有感知且不需要维护中间复杂的流程(UDP封包、拆包等),因此称之为 ——「 Vxlan 隧道」
实际上的 UDP 包发送和接收需要走「三层网络」—— 因此称之为 —— 三层通信
到此我们就全部理解了 —— 基于三层的”二层“通信
3.之后此封装好的「UDP数据包」,将会通过三层网络,到达目的容器所在的主机的「目的VTEP设备」
「UDP数据包」经过拆包后,「目的 VTEP 设备」 便获得了 「源 VTEP 设备」发来的「Vxlan数据包」
4.目的容器所在的主机的「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 组件)
Calico host-gw(BGP) 模式通信流程图