Skip to content

Commit

Permalink
更新第三章
Browse files Browse the repository at this point in the history
  • Loading branch information
isno committed Sep 24, 2024
1 parent 9384e50 commit 7bf38b5
Show file tree
Hide file tree
Showing 11 changed files with 29 additions and 31 deletions.
10 changes: 4 additions & 6 deletions network/DPDK.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,22 @@

起初,DPDK 实际上是 Intel 为了卖自家的硬件,针对 Intel 处理器和网卡开发的一款高性能的网络驱动组件。DPDK 开源之后,越来越多的厂商参与进来贡献代码,这使得 DPDK 支持更多的处理器和网卡,如处理器不仅支持 Intel,还支持 AMD、ARM 等厂商的处理器,网卡支持的范围也包括 Intel 网卡、Mellanox 网卡、ARM 集成网卡等。

图 3-17 对比展示了 DPDK 与传统内核网络。在 Linux 系统中,位于用户空间的 DPDK Lib 和 APP 被视为一个普通的用户进程,其编译、连接和加载方式和普通程序没什么区别。但两者网络数据包在 Linux 系统中的传输路径完全不同:
图 3-6 对比展示了 DPDK 与传统内核网络。在 Linux 系统中,位于用户空间的 DPDK Lib 和 APP 被视为一个普通的用户进程,其编译、连接和加载方式和普通程序没什么区别。但两者网络数据包在 Linux 系统中的传输路径完全不同:

- 左侧展示的是传统内核方式:网络数据包自网络接口卡(NIC)出发,经过驱动程序,内核协议栈,最后通过 Socket 接口传递至业务逻辑。
- 右侧则展示的是 DPDK 方式:在该方案中,网络数据包利用用户空间 I/O(UIO)技术,直接绕过内核协议栈,从网卡转移到 DPDK 基础库,然后传递至业务逻辑。也就是说 DPDK 绕过了 Linux 内核协议栈对数据包的处理过程,在用户空间直接对数据包进行收发与处理。


:::center
![](../assets/dpdk.png)<br/>
图 3-17 DPDK 与传统内核网络对比
图 3-6 DPDK 与传统内核网络对比
:::



图 3-18 展示了基于 DPDK 的高性能四层负载均衡 DPVS 与基于 Linux 内核网络的 LVS 四层负载均衡性能对比。从每秒转发数据包数量(PPS)这一指标来看,DPVS 的表现比 LVS 高出 300%。对于海量用户规模的互联网应用来说,动辄需要部署数千、甚至数万台服务器,如果能将单机性能提升十倍甚至百倍,无论是从硬件投入还是运营成本上来看都能带来非常可观的成本削减,这样的技术变革带来的潜在效益非常诱人。
图 3-7 展示了基于 DPDK 的高性能四层负载均衡 DPVS 与基于 Linux 内核网络的 LVS 四层负载均衡性能对比。从每秒转发数据包数量(PPS)这一指标来看,DPVS 的表现比 LVS 高出 300%。对于海量用户规模的互联网应用来说,动辄需要部署数千、甚至数万台服务器,如果能将单机性能提升十倍甚至百倍,无论是从硬件投入还是运营成本上来看都能带来非常可观的成本削减,这样的技术变革带来的潜在效益非常诱人。

:::center
![](../assets/dpvs-performance.png)<br/>
图 3-18 DPVS 与 LVS 的 PPS 性能指标对比 [图片来源](https://github.com/iqiyi/dpvs)
图 3-7 DPVS 与 LVS 的 PPS 性能指标对比 [图片来源](https://github.com/iqiyi/dpvs)
:::


8 changes: 4 additions & 4 deletions network/RDMA.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@

RDMA(Remote Direct Memeory Access,远程直接内存访问)是一种绕过远程主机操作系统访问其内存中数据的技术,概念源自于 DMA 技术。在 DMA 技术中,外部设备(PCIe 设备)能够绕过 CPU 直接访问主机内存;而 RDMA 则是指外部设备绕过 TCP/IP 网络协议栈,一次跨主机的网络请求就像读取本地内存一样。

RDMA 的工作原理如下图所示,RDMA 绕过了传统以太网复杂的 TCP/IP 协议栈,直接从网卡硬件上开始网络数据传递。由于不经过操作系统,不仅节省了大量 CPU 资源,还提高了系统吞吐量,降低了系统的网络通信延迟。
RDMA 的工作原理如图 3-10 所示,RDMA 绕过了传统以太网复杂的 TCP/IP 协议栈,直接从网卡硬件上开始网络数据传递。由于不经过操作系统,不仅节省了大量 CPU 资源,还提高了系统吞吐量,降低了系统的网络通信延迟。

:::center
![](../assets/RDMA.png)<br/>
图 RDMA 技术栈
3-10 RDMA 技术栈
:::

RDMA 网络主要由三种协议实现:Infiniband、RoCE 和 iWARP,它们的含义与区别如下:
Expand All @@ -19,12 +19,12 @@ InfiniBand 贸易协会)在 2000 年提出。构建 Infiniband 网络需要配
- 为了降低 RDMA 使用成本,以及使 RDMA 技术走向通用数据中心领域,2010 年,IBTA 发布了 RoCE(RDMA over Converged Ethernet,融合以太网的远程直接内存访问)技术,将 Infiniband 的四层传输协议 RDMA“移植”到以太网。这样,只要有支持 RoCE 的特殊网卡 + 普通的以太网交换机就能享受 RDMA 高性能。RoCE 的发展过程中出现了两个协议版本 RoCEv1 和 RoCEv2:RoCEv1 是一种链路层协议,仅支持在二层在一个广播域内互通;而 RoCEv2 是一种网络层协议,允许不同广播域下的主机通过三层 IP 网络互通。可以看出,RoCEv2 解除了 RoCEv2 无法跨子网的限制,同时结合本身固有的低成本以及兼容性优势,开始被广泛应用于分布式存储以及分布式并行计算等通用数据中心场景。根据云计算平台 Azure 公开的信息,2023 年 Azure 整个数据中心 70% 的流量已经是 RDMA 流量了。
:::center
![](../assets/RoCE_Header_format.png)<br/>
图 RoCE v1 只能在广播域内通信,RoCE v2 支持 L3 路由
3-11 RoCE v1 只能在广播域内通信,RoCE v2 支持 L3 路由
:::

值得注意的是,RDMA 技术对网络丢包极为敏感,任何一个报文丢失都可能引发大量的重传,严重影响 RDMA 的传输性能。Infiniband 网络从专用设备层面确保网络的高性能与低延迟。而 RoCE 网络是在标准以太网基础设施上实现 RDMA 技术,这要求基础设施层面必须支持无损以太网络,以避免数据丢包对性能的影响。

目前,大多数数据中心使用微软和 Mellanox 提出的 DCQCN 以及阿里巴巴提出的 HPCC 算法来为 RoCE 网络提供可靠性保障。由于这些算法涉及非常底层的技术(笔者的知识盲区),超出了本书的讨论范围。笔者就不再详细介绍,有兴趣的读者可以通过网络搜索进一步了解相关内容。
目前,大多数数据中心使用微软和 Mellanox 提出的 DCQCN 以及阿里巴巴提出的 HPCC 算法来为 RoCE 网络提供可靠性保障。由于这些算法涉及非常底层的技术(笔者的知识盲区),也超出了本书的讨论范畴。笔者就不再详细介绍了,有兴趣的读者可以通过网络搜索进一步了解相关内容。



4 changes: 2 additions & 2 deletions network/XDP.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ DPDK 技术是完全绕过内核,直接将数据包传递到用户空间进行

:::center
![](../assets/xdp.png)<br/>
图 3-13 XDP 钩子在 Linux 系统的位置与 5 个动作
图 3-8 XDP 钩子在 Linux 系统的位置与 5 个动作
:::

假设我们已经清楚 eBPF 程序逻辑的编写,那么它是如何被加载、验证并执行的呢?请看下面的步骤:
Expand All @@ -39,7 +39,7 @@ DPDK 技术是完全绕过内核,直接将数据包传递到用户空间进行

:::center
![](../assets/ebpf-go.webp)<br/>
图 3-13 eBPF 的技术架构
图 3-9 eBPF 的技术架构
:::

正是由于这些突出的特性,eBPF 可以附加到各种内核子系统,包括网络、跟踪和 Linux 安全模块(LSM)。比如 Facebook 开源的高性能网络负载均衡器 Katran,内核跟踪排错工具 BCC 和 bpftrace,以及 Isovalent 开源的容器网络方案 Cilium 等等都是利用 eBPF 技术实现的。以 Cilium 为例,它在 eBPF 和 XDP 钩子(也有其他的钩子)基础上,实现了一套全新的 conntrack 和 NAT 机制。并以此为基础,构建出如 L3/L4 负载均衡、网络策略、观测和安全认证等各类高级功能。
Expand Down
4 changes: 2 additions & 2 deletions network/conntrack.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,15 @@ conntrack 连接记录是 iptables 连接状态匹配的基础,也是网络地

conntrack 维护的连接记录包含了从客户端到服务的 DNAT 映射(10.0.0.10:80 到 192.168.1.2:8080)以及从服务到客户端的 SNAT 映射(192.168.1.2:8080 到 10.0.0.10:80)。这样有来有回,是一条完整的 NAT 映射关系。

但如果发起请求的 Pod 和处理请求的 Pod 在同一个主机内,问题就来了:
但如果发起请求的 Pod 和处理请求的 Pod 在同一个主机内(图 3-5),问题就来了:
- 发起请求时,数据包经过网络层时,内核中的 conntrack 模块根据 iptables 规则,判断是否需要进行 DNAT;
- 返回响应时,如果 Linux 网桥检测到目的 IP 位于同一网桥上,则直接通过二层转发(即链路层通信),并没有触发网络层的 conntrack 模块,也就是不进行 SNAT。

因此,通信双方不在同一“频道”上,与 NAT 相关的连接记录不完整,进而影响容器间通信,产生各类异常。

:::center
![](../assets/bridge-call-iptables.svg)<br/>
图 3-13 请求和响应不在一个“频道”上,双方通信失败
图 3-5 请求和响应不在一个“频道”上,双方通信失败
:::

针对上述问题,Linux 内核提供了 bridge-nf-call-iptables 配置,决定内核是否将通过网桥的流量交由 iptables 规则匹配处理,也就是处理 NAT 保证 conntrack 连接记录的完整性。这也是为什么部署 Kubernetes 集群时,务必开启 Linux 系统配置 bridge-nf-call-iptables(设置为 1)的原因。
Expand Down
8 changes: 4 additions & 4 deletions network/iptables.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,11 @@ iptables 把一些常用数据包管理操作总结成具体的动作,当数
- security 表:安全增强,一般用于 SELinux 中,其他情况并不常用。


一个链上可以关联的表可以有多个,所以这 5 张表在一个链上执行的时候得有个顺序:raw --> mangle --> nat --> filter --> security,即先去连接追踪,再改数据包,然后做源或目标地址转换,最后是过滤和安全。数据包具体经过的表、链的关系和顺序如图 3-6 所示。
一个链上可以关联的表可以有多个,所以这 5 张表在一个链上执行的时候得有个顺序:raw --> mangle --> nat --> filter --> security,即先去连接追踪,再改数据包,然后做源或目标地址转换,最后是过滤和安全。数据包具体经过的表、链的关系和顺序如图 3-3 所示。

:::center
![](../assets/Netfilter-packet-flow.svg)<br/>
图 3-6 数据包通过 Netfilter 时的流向过程 [图片来源](https://en.wikipedia.org/wiki/Netfilter)
图 3-3 数据包通过 Netfilter 时的流向过程 [图片来源](https://en.wikipedia.org/wiki/Netfilter)
:::


Expand Down Expand Up @@ -75,11 +75,11 @@ iptables 把一些常用数据包管理操作总结成具体的动作,当数

为解决 iptables 模式的性能问题,kube-proxy 新增了 IPVS 模式,该模式使用 Linux 内核四层负载均衡模块 IPVS 实现容器间请求和负载均衡,性能和 Service 规模无关。不过需要注意的是,内核中的 IPVS 模块只负责上述的负载均衡和代理功能。而一个完整的 Service 流程正常工作所需要的包过滤、SNAT 等操作,还是要靠 iptables 来实现。只不过,这些辅助性的 iptables 规则数量有限,不会随着 Pod 数量的增加而增加。

如图 3-9 展示了 iptables 与 IPVS 两种模式的性能对比。可以看出,当 Kubernetes 集群有 1,000 个 Service(10,000 个 Pod)时,两者的性能表现开始出现明显差异。
如图 3-4 展示了 iptables 与 IPVS 两种模式的性能对比。可以看出,当 Kubernetes 集群有 1,000 个 Service(10,000 个 Pod)时,两者的性能表现开始出现明显差异。

:::center
![](../assets/iptables-vs-ipvs.png)<br/>
图 3-9 iptables 与 IPVS 的性能差异 [图片来源](https://www.tigera.io/blog/comparing-kube-proxy-modes-iptables-or-ipvs/)
图 3-4 iptables 与 IPVS 的性能差异 [图片来源](https://www.tigera.io/blog/comparing-kube-proxy-modes-iptables-or-ipvs/)
:::

所以,当 Kubernetes 集群的规模较大时,应该避免使用 iptables 模式。如果容器间通信解决方案使用的是 Cilium,还可以创建没有 kube-proxy 组件的 Kubernetes 集群,利用笔者稍后介绍的“内核旁路”技术越过 iptables 影响,全方位提升容器网络性能。
4 changes: 2 additions & 2 deletions network/linux-bridge.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@ Linux bridge 作为一个虚拟的交换机,和物理交换机有相似的功
- 如找到记录,则将数据帧转发到对应的接口。


笔者举一个具体的例子帮你加深理解:使用 Linux bridge 将两个命名空间接入到同一个二层网络。该例子的网络拓扑结构如图 3-23 所示。
笔者举一个具体的例子帮你加深理解:使用 Linux bridge 将两个命名空间接入到同一个二层网络。该例子的网络拓扑结构如图 3-15 所示。

:::center
![](../assets/linux-bridge.svg)<br/>
图 3-23 veth 网卡与 Linux Bridge
图 3-15 veth 网卡与 Linux Bridge
:::

创建 Linux bridge 与创建其他虚拟网络设备类似,只需要指定 type 参数为 bridge。
Expand Down
2 changes: 1 addition & 1 deletion network/netfilter.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ Netfilter 干预 Linux 网络通信的方式,是围绕网络协议栈(主要

:::center
![](../assets/netfilter-hook.svg)<br/>
图 3-2
图 3-2 Netfilter 的 5 个钩子
:::


Expand Down
2 changes: 1 addition & 1 deletion network/network-namespace.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Linux 内核处于对资源隔离的需要,从 2.4.19 版本起,它开始逐

:::center
![](../assets/linux-namespace.svg)<br/>
图 3-19 不同网络命名空间内的网络资源都是隔离的
图 3-12 不同网络命名空间内的网络资源都是隔离的
:::

Linux ip 工具的子命令 netns 集成了网络命名空间的增删查改功能。笔者使用 ip 命令演示操作网络命名空间,帮助你加深理解网络命名空间的隔离性。
Expand Down
4 changes: 2 additions & 2 deletions network/tuntap.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ tun 和 tap 是Linux 内核 2.4.x 版本之后引入的虚拟网卡设备,是

在 Linux 中,内核空间和用户空间之间数据传输有多种方式,字符设备文件是其中一种。tap/tun 对应的字符设备文件为 /dev/net/tun。当用户空间的程序 open() 字符设备文件时,会返回一个 fd 句柄,同时字符设备驱动就会创建并注册相应的虚拟网卡网络接口,并以 tunX 或 tapX 命名。当用户空间的程序向 fd 执行 read()/write() 时,就可以和内核网络协议栈读写数据了。

tap 和 tap 的工作方式基本相同,只是两者工作的层面不一样。以使用 tap 设备建立的 VPN 隧道为例说明其工作原理(如图 3-20):普通的用户程序发起一个网络请求,数据包进入内核协议栈时查找路由,下一跳是 tunX 设备。tunX 发现自己的另一端由 VPN 程序打开,所以收到数据包后传输给 VPN 程序。VPN 程序对数据包进行封装操作,“封装”是指将一个数据包包装在另一个数据包中,就像将一个盒子放在另一个盒子中一样。封装后的数据再次被发送到内核,最后通过 eth0 接口(也就是图中的物理网卡)发出。
tap 和 tap 的工作方式基本相同,只是两者工作的层面不一样。以使用 tap 设备建立的 VPN 隧道为例说明其工作原理(如图 3-13):普通的用户程序发起一个网络请求,数据包进入内核协议栈时查找路由,下一跳是 tunX 设备。tunX 发现自己的另一端由 VPN 程序打开,所以收到数据包后传输给 VPN 程序。VPN 程序对数据包进行封装操作,“封装”是指将一个数据包包装在另一个数据包中,就像将一个盒子放在另一个盒子中一样。封装后的数据再次被发送到内核,最后通过 eth0 接口(也就是图中的物理网卡)发出。

:::center
![](../assets/tun.svg)<br/>
图 3-20 VPN 中数据流动示意图
图 3-13 VPN 中数据流动示意图
:::

将一个数据包封装到另一个数据包的处理方式被称为 “隧道”,隧道技术是构建虚拟逻辑网络的经典做法。容器网络插件 Flannel 早期曾使用 tun 设备实现了 UDP 模式下的跨主网络相互访问,但使用 tun 设备传输数据需要经过两次协议栈,且有多次的封包/解包过程,产生额外的性能损耗。这是后来 Flannel 弃用 UDP 模式的主要原因。
4 changes: 2 additions & 2 deletions network/virtual-nic.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ Linux 内核 2.6 版本支持网络命名空间的同时,也提供了专门的

veth 的典型应用是连接各类虚拟设备,让原本隔离的网络名称空间可以互相通信。当我们创建一个 veth 设备时,会自动创建另一个关联的 veth 设备(网线的另一头)。将关联的 veth 设备其移动到其他网络命名空间后,两个 veth 设备之间的数据包传输被视为在一个以太网连接上传输。

假设我们已经有两个相互隔离的网络命名空间 ns1 和 ns2,它们的网络拓扑结构如下图。下面笔者进行操作演示,帮助你理解 veth 设备如何实现网络命名空间的互通。
假设我们已经有两个相互隔离的网络命名空间 ns1 和 ns2,它们的网络拓扑结构如图 3-14。下面笔者进行操作演示,帮助你理解 veth 设备如何实现网络命名空间的互通。

:::center
![](../assets/linux-veth.svg)<br/>
图 3-21 Veth 设备对
图 3-14 Veth 设备对
:::

首先,创建一对 Veth 设备,它们的名称分别为 veth1 和 veth2。命令如下所示:
Expand Down
Loading

0 comments on commit 7bf38b5

Please sign in to comment.