Kubernetes 网络插件工作原理

简介: 网络插件的主要工作就在于为容器提供网络环境,包括为 pod 设置 ip 地址、配置路由保证集群内网络的通畅。目前比较流行的网络插件是 Flannel 和 Calico。

Kubernetes 网络插件工作原理

容器的网络解决方案有很多种,每支持一种网络实现就进行一次适配显然是不现实的,而 CNI 就是为了兼容多种网络方案而发明的。CNI 是 Container Network Interface 的缩写,是一个标准的通用的接口,用于连接容器管理系统和网络插件。

简单来说,容器 runtime 为容器提供 network namespace,网络插件负责将 network interface 插入该 network namespace 中并且在宿主机做一些必要的配置,最后对 namespace 中的 interface 进行 IP 和路由的配置。

所以网络插件的主要工作就在于为容器提供网络环境,包括为 pod 设置 ip 地址、配置路由保证集群内网络的通畅。目前比较流行的网络插件是 Flannel 和 Calico。

Flannel

Flannel 主要提供的是集群内的 Overlay 网络,支持三种后端实现,分别是:UDP 模式、VXLAN 模式、host-gw 模式。

UDP 模式

UDP 模式,是 Flannel 项目最早支持的一种方式,却也是性能最差的一种方式。这种模式提供的是一个三层的 Overlay 网络,即:它首先对发出端的 IP 包进行 UDP 封装,然后在接收端进行解封装拿到原始的 IP 包,进而把这个 IP 包转发给目标容器。工作原理如下图所示。

node1 上的 pod1 请求 node2 上的 pod2 时,流量的走向如下:

  1. pod1 里的进程发起请求,发出 IP 包;
  2. IP 包根据 pod1 里的 veth 设备对,进入到 cni0 网桥;
  3. 由于 IP 包的目的 ip 不在 node1 上,根据 flannel 在节点上创建出来的路由规则,进入到 flannel0 中;
  4. 此时 flanneld 进程会收到这个包,flanneld 判断该包应该在哪台 node 上,然后将其封装在一个 UDP 包中;
  5. 最后通过 node1 上的网关,发送给 node2;

flannel0 是一个 TUN 设备(Tunnel 设备)。在 Linux 中,TUN 设备是一种工作在三层(Network Layer)的虚拟网络设备。TUN 设备的功能:在操作系统内核和用户应用程序之间传递 IP 包。

可以看到,这种模式性能差的原因在于,整个包的 UDP 封装过程是 flanneld 程序做的,也就是用户态,而这就带来了一次内核态向用户态的转换,以及一次用户态向内核态的转换。在上下文切换和用户态操作的代价其实是比较高的,而 UDP 模式因为封包拆包带来了额外的性能消耗。

VXLAN 模式

VXLAN,即 Virtual Extensible LAN(虚拟可扩展局域网),是 Linux 内核本身就支持的一种网络虚似化技术。通过利用 Linux 内核的这种特性,也可以实现在内核态的封装和解封装的能力,从而构建出覆盖网络。其工作原理如下图所示:

VXLAN 模式的 flannel 会在节点上创建一个叫 flannel.1 的 VTEP (VXLAN Tunnel End Point,虚拟隧道端点) 设备,跟 UDP 模式一样,该设备将二层数据帧封装在 UDP 包里,再转发出去,而与 UDP 模式不一样的是,整个封装的过程是在内核态完成的。

node1 上的 pod1 请求 node2 上的 pod2 时,流量的走向如下:

  1. pod1 里的进程发起请求,发出 IP 包;
  2. IP 包根据 pod1 里的 veth 设备对,进入到 cni0 网桥;
  3. 由于 IP 包的目的 ip 不在 node1 上,根据 flannel 在节点上创建出来的路由规则,进入到 flannel.1 中;
  4. flannel.1 将原始 IP 包加上一个目的 MAC 地址,封装成一个二层数据帧;然后内核将数据帧封装进一个 UDP 包里;
  5. 最后通过 node1 上的网关,发送给 node2;

抓包验证

在 node1 上部署一个 nginx pod1,node2 上部署一个 nginx pod2。然后在 pod1 的容器中 curl pod2 容器的 80 端口。

集群网络环境如下:

node1 网卡 ens33:192.168.50.10
pod1 veth:10.244.0.7
node1 cni0:10.244.0.1/24
node1 flannel.1:10.244.0.0/32

node2 网卡 ens33:192.168.50.11
pod2 veth:10.244.1.9
node2 cni0:10.244.1.1/24
node2 flannel.1:10.244.1.0/32

node1 上的路由信息如下:

➜  ~ ip route
default via 192.168.50.1 dev ens33
10.244.0.0/24 dev cni0 proto kernel scope link src 10.244.0.1
10.244.1.0/24 via 10.244.1.0 dev flannel.1 onlink
10.244.2.0/24 via 10.244.2.0 dev flannel.1 onlink
172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1
192.168.50.0/24 dev ens33 proto kernel scope link src 192.168.50.10 metric 100

node1 的网卡 ens33 的抓包情况:

只能看到源 ip 为 node1 ip、目的 ip 为 node2 ip 的 UDP 包。由于 flannel.1 进行了一层 UDP 封包,这里我们在 Wireshark 中设置一下将 UDP 包解析为 VxLAN 格式(端口为 8472),设置过程为 Analyze->Decode As:

然后再来看一下 node1 网卡上收到的包:

可以看到源 ip 为 pod1 ip、目的 ip 为 pod2 ip,并且该 IP 包被封装在 UDP 包中。

host-gw 模式

最后一种 host-gw 模式是一种纯三层网络方案。其工作原理为将每个 Flannel 子网的“下一跳”设置成了该子网对应的宿主机的 IP 地址,这台主机会充当这条容器通信路径里的“网关”。这样 IP 包就能通过二层网络达到目的主机,而正是因为这一点,host-gw 模式要求集群宿主机之间的网络是二层连通的,如下图所示。

宿主机上的路由信息是 flanneld 设置的,因为 flannel 子网和主机的信息保存在 etcd 中,所以 flanneld 只需要 watch 这些数据的变化,实时更新路由表即可。在这种模式下,容器通信的过程就免除了额外的封包和解包带来的性能损耗。

node1 上的 pod1 请求 node2 上的 pod2 时,流量的走向如下:

  1. pod1 里的进程发起请求,发出 IP 包,从网络层进入链路层封装成帧;
  2. 根据主机上的路由规则,数据帧从 Node 1 通过宿主机的二层网络到达 Node 2 上;

Calico

Calico 没有使用 CNI 的网桥模式,而是将节点当成边界路由器,组成了一个全连通的网络,通过 BGP 协议交换路由。所以,Calico 的 CNI 插件还需要在宿主机上为每个容器的 Veth Pair 设备配置一条路由规则,用于接收传入的 IP 包。

Calico 的组件:

  1. CNI 插件:Calico 与 Kubernetes 对接的部分
  2. Felix:负责在宿主机上插入路由规则(即:写入 Linux 内核的 FIB 转发信息库),以及维护 Calico 所需的网络设备等工作。
  3. BIRD (BGP Route Reflector):是 BGP 的客户端,专门负责在集群里分发路由规则信息。

三个组件都是通过一个 DaemonSet 安装的。CNI 插件是通过 initContainer 安装的;而 Felix 和 BIRD 是同一个 pod 的两个 container。

工作原理

Calico 采用的 BGP,就是在大规模网络中实现节点路由信息共享的一种协议。全称是 Border Gateway Protocol,即:边界网关协议。它是一个 Linux 内核原生就支持的、专门用在大规模数据中心里维护不同的 “自治系统” 之间路由信息的、无中心的路由协议。

由于没有使用 CNI 的网桥,Calico 的 CNI 插件需要为每个容器设置一个 Veth Pair 设备,然后把其中的一端放置在宿主机上,还需要在宿主机上为每个容器的 Veth Pair 设备配置一条路由规则,用于接收传入的 IP 包。如下图所示:

可以使用 calicoctl 查看 node1 的节点连接情况:

~ calicoctl get no
NAME
node1
node2
node3
~ calicoctl node status
Calico process is running.

IPv4 BGP status
+---------------+-------------------+-------+------------+-------------+
| PEER ADDRESS  |     PEER TYPE     | STATE |   SINCE    |    INFO     |
+---------------+-------------------+-------+------------+-------------+
| 192.168.50.11 | node-to-node mesh | up    | 2020-09-28 | Established |
| 192.168.50.12 | node-to-node mesh | up    | 2020-09-28 | Established |
+---------------+-------------------+-------+------------+-------------+

IPv6 BGP status
No IPv6 peers found.

可以看到整个 calico 集群上有 3 个节点,node1 和另外两个节点处于连接状态,模式为 “Node-to-Node Mesh”。再看下 node1 上的路由信息如下:

~ ip route
default via 192.168.50.1 dev ens33 proto static metric 100
10.244.104.0/26 via 192.168.50.11 dev ens33 proto bird
10.244.135.0/26 via 192.168.50.12 dev ens33 proto bird
10.244.166.128 dev cali717821d73f3 scope link
blackhole 10.244.166.128/26 proto bird
172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1
192.168.50.0/24 dev ens33 proto kernel scope link src 192.168.50.10 metric 100

其中,第 2 条的路由规则表明 10.244.104.0/26 网段的数据包通过 bird 协议由 ens33 设备发往网关 192.168.50.11。这也就定义了目的 ip 为 node2 上 pod 请求的走向。第 3 条路由规则与之类似。

抓包验证

与上面一样,从 node1 上的 pod1 发送一个 http 请求到 node2 上的 pod2。

集群网络环境如下:

node1 网卡 ens33:192.168.50.10
pod1 ip:10.244.166.128

node2 网卡 ens33:192.168.50.11
pod2 ip:10.244.104.1

node1 的网卡 ens33 的抓包情况:

IPIP 模式

IPIP 模式为了解决两个 node 不在一个子网的问题。只要将名为 calico-node 的 daemonset 的环境变量 CALICO_IPV4POOL_IPIP 设置为 "Always" 即可。如下:

            - name: CALICO_IPV4POOL_IPIP
              value: "Off"

IPIP 模式的 calico 使用了 tunl0 设备,这是一个 IP 隧道设备。IP 包进入 tunl0 后,内核会将原始 IP 包直接封装在宿主机的 IP 包中;封装后的 IP 包的目的地址为下一跳地址,即 node2 的 IP 地址。由于宿主机之间已经使用路由器配置了三层转发,所以这个 IP 包在离开 node 1 之后,就可以经过路由器,最终发送到 node 2 上。如下图所示。

由于 IPIP 模式的 Calico 额外多出了封包和拆包的过程,集群的网络性能受到了影响,所以在集群的二层网络通的情况下,建议不要使用 IPIP 模式。

看下 node1 上的路由信息:

~ ip route
default via 192.168.50.1 dev ens33 proto static metric 100
10.244.104.0/26 via 192.168.50.11 dev tunl0 proto bird onlink
10.244.135.0/26 via 192.168.50.12 dev tunl0 proto bird onlink
blackhole 10.244.166.128/26 proto bird
10.244.166.129 dev calif3c799362a5 scope link
172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1
192.168.50.0/24 dev ens33 proto kernel scope link src 192.168.50.10 metric 100

可以看到,与之前不一样的是,目的 IP 为 node2 上的 Pod 的数据包是经由 tunl0 发送到网关 192.168.50.11。

抓包验证

从 node1 上的 pod1 发送一个 http 请求到 node2 上的 pod2。

集群网络环境如下:

node1 网卡 ens33:192.168.50.10
node1 tunl0:10.244.166.128/32
pod1 ip:10.244.166.129

node2 网卡 ens33:192.168.50.11
pod2 ip:10.244.104.2
node2 tunl0:10.244.104.0/32

tunl0 设备的抓包情况:

node1 网卡 ens33 的抓包情况:

可以看到,IP 包在 tunl0 设备中被封装进了另一个 IP 包,其目的 IP 为 node2 的 IP,源 IP 为 node1 的 IP。

总结

Kubernetes 的集群网络插件实现方案有很多种,本文主要分析了社区比较常见的两种 Flannel 和 Calico 的工作原理,针对集群内不同节点的 pod 间通信的场景,抓包分析了网络包的走向。

Flannel 主要提供了 Overlay 的网络方案,UDP 模式由于其封包拆包的过程涉及了多次上下文的切换,导致性能很差,逐渐被社区抛弃;VXLAN 模式的封包拆包过程均在内核态,性能要比 UDP 好很多,也是最经常使用的模式;host-gw 模式不涉及封包拆包,所以性能相对较高,但要求节点间二层互通。

Calico 主要采用了 BGP 协议交换路由,没有采用 cni0 网桥,当二层网络不通的时候,可以采用 IPIP 模式,但由于涉及到封包拆包的过程,性能相对较弱,与 Flannel 的 VXLAN 模式相当。

相关实践学习
通过Ingress进行灰度发布
本场景您将运行一个简单的应用,部署一个新的应用用于新的发布,并通过Ingress能力实现灰度发布。
容器应用与集群管理
欢迎来到《容器应用与集群管理》课程,本课程是“云原生容器Clouder认证“系列中的第二阶段。课程将向您介绍与容器集群相关的概念和技术,这些概念和技术可以帮助您了解阿里云容器服务ACK/ACK Serverless的使用。同时,本课程也会向您介绍可以采取的工具、方法和可操作步骤,以帮助您了解如何基于容器服务ACK Serverless构建和管理企业级应用。 学习完本课程后,您将能够: 掌握容器集群、容器编排的基本概念 掌握Kubernetes的基础概念及核心思想 掌握阿里云容器服务ACK/ACK Serverless概念及使用方法 基于容器服务ACK Serverless搭建和管理企业级网站应用
相关文章
|
1月前
|
人工智能 弹性计算 运维
ACK Edge与IDC:高效容器网络通信新突破
本文介绍如何基于ACK Edge以及高效的容器网络插件管理IDC进行容器化。
|
10天前
|
机器学习/深度学习 算法 PyTorch
深度强化学习中SAC算法:数学原理、网络架构及其PyTorch实现
软演员-评论家算法(Soft Actor-Critic, SAC)是深度强化学习领域的重要进展,基于最大熵框架优化策略,在探索与利用之间实现动态平衡。SAC通过双Q网络设计和自适应温度参数,提升了训练稳定性和样本效率。本文详细解析了SAC的数学原理、网络架构及PyTorch实现,涵盖演员网络的动作采样与对数概率计算、评论家网络的Q值估计及其损失函数,并介绍了完整的SAC智能体实现流程。SAC在连续动作空间中表现出色,具有高样本效率和稳定的训练过程,适合实际应用场景。
47 7
深度强化学习中SAC算法:数学原理、网络架构及其PyTorch实现
|
19天前
|
前端开发 网络协议 安全
【网络原理】——HTTP协议、fiddler抓包
HTTP超文本传输,HTML,fiddler抓包,URL,urlencode,HTTP首行方法,GET方法,POST方法
|
19天前
|
域名解析 网络协议 关系型数据库
【网络原理】——带你认识IP~(长文~实在不知道取啥标题了)
IP协议详解,IP协议管理地址(NAT机制),IP地址分类、组成、特殊IP地址,MAC地址,数据帧格式,DNS域名解析系统
|
19天前
|
存储 JSON 缓存
【网络原理】——HTTP请求头中的属性
HTTP请求头,HOST、Content-Agent、Content-Type、User-Agent、Referer、Cookie。
|
19天前
|
安全 算法 网络协议
【网络原理】——图解HTTPS如何加密(通俗简单易懂)
HTTPS加密过程,明文,密文,密钥,对称加密,非对称加密,公钥和私钥,证书加密
|
19天前
|
XML JSON 网络协议
【网络原理】——拥塞控制,延时/捎带应答,面向字节流,异常情况
拥塞控制,延时应答,捎带应答,面向字节流(粘包问题),异常情况(心跳包)
|
21天前
|
Kubernetes 网络协议 应用服务中间件
Kubernetes Ingress:灵活的集群外部网络访问的利器
《Kubernetes Ingress:集群外部访问的利器-打造灵活的集群网络》介绍了如何通过Ingress实现Kubernetes集群的外部访问。前提条件是已拥有Kubernetes集群并安装了kubectl工具。文章详细讲解了Ingress的基本组成(Ingress Controller和资源对象),选择合适的版本,以及具体的安装步骤,如下载配置文件、部署Nginx Ingress Controller等。此外,还提供了常见问题的解决方案,例如镜像下载失败的应对措施。最后,通过部署示例应用展示了Ingress的实际使用方法。
45 2
|
21天前
|
网络协议 安全 网络安全
探索网络模型与协议:从OSI到HTTPs的原理解析
OSI七层网络模型和TCP/IP四层模型是理解和设计计算机网络的框架。OSI模型包括物理层、数据链路层、网络层、传输层、会话层、表示层和应用层,而TCP/IP模型则简化为链路层、网络层、传输层和 HTTPS协议基于HTTP并通过TLS/SSL加密数据,确保安全传输。其连接过程涉及TCP三次握手、SSL证书验证、对称密钥交换等步骤,以保障通信的安全性和完整性。数字信封技术使用非对称加密和数字证书确保数据的机密性和身份认证。 浏览器通过Https访问网站的过程包括输入网址、DNS解析、建立TCP连接、发送HTTPS请求、接收响应、验证证书和解析网页内容等步骤,确保用户与服务器之间的安全通信。
84 1
|
19天前
|
网络协议 算法 Java
【JavaEE】——初始网络原理
局域网,广域网,局域网连接方式,交换机,集线器,路由器,网络通信,五元组(源IP,源端口,目的IP,目的端口,协议),协议分层,TCP/IP五层网络协议,封装和分用,交换机和路由器的封装和分用