From 2709c3ed76f05883d6c3870630b945c70c04e933 Mon Sep 17 00:00:00 2001 From: isno Date: Wed, 5 Feb 2025 10:34:05 +0800 Subject: [PATCH] fix typo --- application-centric/Controller.md | 4 +++- distributed-transaction/BASE.md | 4 +--- network/network-namespace.md | 2 +- network/tuntap.md | 21 ++++++++++++--------- network/virtual-nic.md | 20 +++++++++----------- 5 files changed, 26 insertions(+), 25 deletions(-) diff --git a/application-centric/Controller.md b/application-centric/Controller.md index 97f17ce6..cbd2df10 100644 --- a/application-centric/Controller.md +++ b/application-centric/Controller.md @@ -1,5 +1,6 @@ # 10.2 声明式管理的本质 +许多人容易将“声明式风格的 API”和“声明式管理”混为一谈,这实际上是对声明式管理缺乏正确认识。要真正理解声明式管理,首先需要弄清楚 Kubernetes 的控制器模式。 ## 10.1.1 控制器模式 @@ -14,8 +15,9 @@ 总结控制器模式就是,用户通过 YAML 文件表达资源的“预期状态”,“控制器”(Controller)监视资源状态,当资源的实际状态和“预期状态”不一致时,控制器执行相应的操作,以确保两者一致。在 Kubernetes 中,这个过程被称之为“调谐”(Reconcile),Reconcile 就是不断执行“检查 -> 差异分析 -> 执行”的循环。 -Reconcile 过程的存在,确保了系统状态与终态保持一致的理论正确性。许多人将“声明式管理”和“声明式风格的 API”混为一谈,实际上是对 Reconcile 的必要性缺乏正确的认识。这个逻辑很容易理解,第一次提交描述时系统达成了你想要的期望状态,并不代表、也不保证一个小时后的情况也是如此。 +Reconcile 过程的存在,确保了系统状态始终向预期终态收敛。这个逻辑很好理解:系统在第一次提交描述时达到了期望状态,但这并不意味着一个小时后的情况也是如此。 +所以说,声明式管理的核心在于“调谐”,而声明式风格的 API 只是一种对外的交互形式。 ## 10.1.2 基础设施即数据思想 diff --git a/distributed-transaction/BASE.md b/distributed-transaction/BASE.md index 70d1fb85..9f4db404 100644 --- a/distributed-transaction/BASE.md +++ b/distributed-transaction/BASE.md @@ -11,9 +11,7 @@ BASE 是“Basically Available”、“Soft State”和“Eventually Consistent - **最终一致性**(Eventually consistent):最终一致性强调,即使在网络分区或系统故障的情况下,在经过足够的时间和多次数据同步操作后,所有节点的数据一定会一致。 -BASE 理论是对 CAP 定理中 AP(可用性和分区容错性)方案的进一步发展,强调即使无法实现强一致性,分布式系统也可以通过适当的机制最终达到一致性。这个适当的机制可概括为**基于可靠事件队列的事件驱动模式**。 - -接下来,以一个具体的例子帮助你理解“可靠事件队列”的具体做法。 +总结 BASE 理论是对 CAP 定理中 AP(可用性和分区容错性)方案的进一步发展,强调即使无法实现强一致性,分布式系统也可以通过适当的机制最终达到一致性。适当的机制可概括为**基于可靠事件队列的事件驱动模式**。接下来,以一个具体的例子帮助你理解“可靠事件队列”的具体做法。 假设有一个电商系统,下单操作依赖于三个服务:支付服务(进行银行扣款)、库存服务(扣减商品库存)和积分服务(为用户增加积分)。下单过程中,我们优先处理最核心、风险最高的服务,按照支付扣款、仓库出库以及为用户增加积分的顺序执行。下单的整个流程如图 5-2 所示。 diff --git a/network/network-namespace.md b/network/network-namespace.md index a2053775..e3479553 100644 --- a/network/network-namespace.md +++ b/network/network-namespace.md @@ -41,6 +41,6 @@ target prot opt source destination 不难看出,不同的网络命名空间默认相互隔离,也无法直接通信。如果它们需要与外界(包括其他网络命名空间或宿主机)建立连接,该如何实现呢? -我们先看看物理机是怎么操作的,一台物理机如果要想与外界进行通信,那得插入一块网卡,通过网线连接到以太网交换机,加入一个局域网内。被隔离的网络命名空间如果想与外界进行通信,就需要利用到稍后介绍的各类虚拟网络设备。也就是在网络命名空间里面插入“虚拟网卡”,然后把“网线”的另一头桥接到“虚拟交换机”中。 +我们先看看物理机是怎么操作的,一台物理机如果要想与外界进行通信,那得插入一块网卡,通过网线连接到以太网交换机,加入一个局域网内。被隔离的网络命名空间如果想与外界进行通信,就需要利用到稍后介绍的各类虚拟网络设备。也就是,在网络命名空间里面插入“虚拟网卡”,然后把“网线”的另一头桥接到“虚拟交换机”中。 没错,这些操作完全和物理环境中的配置局域网一样,只不过全部是虚拟的、用代码实现的而已。 \ No newline at end of file diff --git a/network/tuntap.md b/network/tuntap.md index 8e85d766..8ada9a9b 100644 --- a/network/tuntap.md +++ b/network/tuntap.md @@ -1,26 +1,29 @@ # 3.5.2 虚拟网络设备 TUN 和 TAP -TUN 和 TAP 是 Linux 内核 2.4.x 版本之后引入的虚拟网卡设备,主要用于用户空间(user space)和内核空间(kernel space)双向传输数据。这两种设备的区别与含义为: -- TUN 设备是虚拟网络接口设备,工作在网络层(Layer 3),主要处理 IP 数据包。它模拟了一个网络层接口,可以让用户空间程序处理 IP 数据包; -- TAP 设备也是虚拟网络接口,但它工作在数据链路层(Layer 2),主要处理以太网帧。与 TUN 设备不同,TAP 设备传递的是完整的以太网帧,包括数据链路层头部,可以让用户空间程序处理以太网帧。 +TUN 和 TAP 是 Linux 内核自 2.4.x 版本引入的虚拟网卡设备,专为用户空间(user space)与内核空间(kernel space)之间的数据传输而设计。两者的主要区别如下: +- **TUN 设备**:工作在网络层(Layer 3),用于处理 IP 数据包。它模拟一个网络层接口,使用户空间程序能够直接收发 IP 数据包; +- **TAP 设备**:工作在数据链路层(Layer 2),用于处理以太网帧。与 TUN 设备不同,TAP 设备传输完整的以太网帧(包括数据链路层头部),使用户空间程序可以处理原始以太网帧。 +Linux 系统中,内核空间和用户空间之间数据传输有多种方式,字符设备文件是其中一种。 -Linux 系统中,内核空间和用户空间之间数据传输有多种方式,字符设备文件是其中一种。TUN/TAP 对应的字符设备文件为 /dev/net/tun。当用户空间的程序 open() 字符设备文件时,返回一个 fd 句柄,同时字符设备驱动创建并注册相应的虚拟网卡网络接口,并以 tunX 或 tapX 命名。当用户空间的程序向 fd 执行 read()/write() 时,就可以和内核网络互通了。 +TUN/TAP 设备对应的字符设备文件为 /dev/net/tun。当用户空间的程序打开(open)字符设备文件时,同时,TUN/TAP 的字符设备驱动会创建并注册相应的虚拟网卡,默认命名为 tunX 或 tapX。随后,用户空间程序读写(read/write)该文件描述符,就可以和内核网络栈进行数据交互了。 + +如图 3-13 所示,下面以 TUN 设备构建 VPN 隧道为例,说明其工作原理。 -TUN 和 TAP 两者工作原理基本相同,只是工作的网络层面不一样。如图 3-13 所示,笔者以 TUN 设备构建 VPN 隧道为例,说明其工作原理: 1. 首先,一个普通的用户程序发起一个网络请求; -2. 接着,数据包进入内核协议栈被路由至 tun0 设备。路由规则如下: +2. 接着,数据包进入内核协议栈,并路由至 tun0 设备。路由规则如下: ```bash $ ip route show default via 172.12.0.1 dev tun0 // 默认流量经过 tun0 设备 192.168.0.0/24 dev eth0 proto kernel scope link src 192.168.0.3 ``` -3. tun0 设备字符文件 /dev/net/tun 由 VPN 程序打开。所以,第一步用户程序发送的数据包被 VPN 程序接管。 -4. VPN 程序对数据包进行封装操作,“封装”是指将一个数据包包装在另一个数据包中,就像将一个盒子放在另一个盒子中一样。封装后的数据再次被发送到内核,最后通过 eth0 接口(也就是图中的物理网卡)发出。 +3. tun0 设备的字符设备文件 /dev/net/tun 由 VPN 程序打开。所以,用户程序发送的数据包不会直接进入网络,而是被 VPN 程序读取并处理。 +4. VPN 程序对数据包进行封装操作,封装(Encapsulation)是指在原始数据包外部包裹新的数据头部,就像将一个盒子放在另一个盒子中一样。 +5. 最后,处理后的数据包再次写入内核网络栈,并通过 eth0(即物理网卡)发送到目标网络。 :::center ![](../assets/tun.svg)
图 3-13 VPN 中数据流动示意图 ::: -将一个数据包封装到另一个数据包是构建网络隧道,实现虚拟网络的典型方式。本书第七章介绍的容器网络插件 Flannel,早期曾使用 TUN 设备实现了容器间虚拟网络通信,但使用 TUN 设备传输数据需要经过两次协议栈,且有多次的封包/解包操作,导致产生了很大的性能损耗。这是后来 Flannel 弃用 TUN 设备的主要原因。 +封装数据包以构建网络隧道,是实现虚拟网络的常见方式。例如,在本书第七章介绍的容器网络插件 Flannel 早期版本中,曾使用 TUN 设备来实现容器间的虚拟网络通信。但是,TUN 设备的数据传输需经过两次协议栈,并涉及多次封包与解包操作,导致了很大的性能损耗。这也是 Flannel 后来弃用 TUN 设备的主要原因。 diff --git a/network/virtual-nic.md b/network/virtual-nic.md index 3beb6cb6..4bb5a499 100644 --- a/network/virtual-nic.md +++ b/network/virtual-nic.md @@ -2,29 +2,29 @@ Linux 内核 2.6 版本支持网络命名空间的同时,也提供了专门的虚拟网卡 Veth(Virtual Ethernet,虚拟以太网网卡)。 -Veth 实现原理的本质是一种“反转数据传输方向”的实现,即:在内核中将需要被发送的数据包“反转"为新接收到的数据包,重新进入内核网络协议栈中处理。通俗的解释,Veth 就是一根带着两个“水晶头”的“网线”,从网线的一头发送数据,另一头就会收到数据。因此,Veth 也被说成是“一对设备”(Veth-Pair)。 +Veth 的核心原理是“反转数据传输方向”,即在内核中,将发送端的数据包转换为接收端的新数据包,并重新交由内核网络协议栈处理。通俗的解释,Veth 就是一根带着两个“水晶头”的“网线”,从网线的一头发送数据,另一头就会收到数据。因此,Veth 也被说成是“一对设备”(Veth-Pair)。 -Veth 的典型应用是连接隔离的网络命名空间,让它们可以互相通信。假设有两个网络命名空间 ns1 和 ns2,它们的网络拓扑结构如图 3-14。接下来,笔者将通过操作演示,帮助你理解 Veth 设备如何实现网络命名空间之间的互通。 +Veth 设备的典型应用场景是连接相互隔离的网络命名空间,使它们能够进行通信。假设存在两个网络命名空间 ns1 和 ns2,其网络拓扑结构如图 3-14 所示。接下来,笔者将通过实际操作演示 Veth 设备如何在网络命名空间之间建立通信,帮助你加深理解。 :::center ![](../assets/linux-veth.svg)
图 3-14 Veth 设备对 ::: -首先,创建一对 Veth 设备,它们的名称分别为 veth1 和 veth2。命令如下所示: +首先,使用以下命令创建一对 Veth 设备,命名为 veth1 和 veth2。该命令会生成一对虚拟以太网设备,它们之间形成点对点连接,即数据从 veth1 发送后,会直接出现在 veth2 上,反之亦然。 ```bash $ ip link add veth1 type veth peer name veth2 ``` -接下来,要做的是把这对设备分别放到 ns1 和 ns2 中。命令如下所示: +接下来,我们将分别将它们分配到不同的网络命名空间。 ```bash $ ip link set veth1 netns ns1 $ ip link set veth2 netns ns2 ``` -Veth 是虚拟的网络设备,因此具备虚拟网卡的特征。即可配置 IP/MAC 地址。接下来,给 Veth 设备配置上 ip 地址,它们的 IP 地址处于同一个子网 172.16.0.1/24 中,同时激活 Veth 设备。 +Veth 作为虚拟网络设备,具备与物理网卡相同的特性,因此可以配置 IP 和 MAC 地址。接下来,我们为 Veth 设备分配 IP 地址,使其处于同一子网 172.16.0.0/24,并同时激活设备。 ```bash # 配置命名空间1 @@ -34,13 +34,14 @@ $ ip netns exec ns1 ip addr add 172.16.0.1/24 dev veth1 $ ip netns exec ns2 ip link set veth2 up $ ip netns exec ns2 ip addr add 172.16.0.2/24 dev veth2 ``` -Veth 设备配置完 ip 之后,每个网络命名空间中会自动生成对应的路由信息。 +Veth 设备配置 IP 后,每个网络命名空间都会自动生成相应的路由信息。如下所示: ```bash $ ip netns exec ns1 ip route 172.16.0.0/24 dev veth1 proto kernel scope link src 172.16.0.1 ``` -上面的路由配置表明,凡是属于 172.16.0.0/24 网段的数据包都会通过 veth1 发送。自然地,通过 veth1 接口发送的数据包会被 veth2 接收到。在 ns1 中进行 ping 测试,可以看到两个命名空间已经连通了。 + +上述路由配置表明,所有属于 172.16.0.0/24 网段的数据包都会经由 veth1 发送,并在另一端由 veth2 接收。在 ns1 中执行 ping 测试,可以验证两个网络命名空间已经成功互通了。 ```bash $ ip netns exec ns1 ping -c10 172.16.0.2 @@ -49,8 +50,5 @@ PING 172.16.0.2 (172.16.0.2) 56(84) bytes of data. 64 bytes from 172.16.0.2: icmp_seq=2 ttl=64 time=0.063 ms ``` -虽然 Veth 设备模拟网卡直连的方式解决了两个容器之间的通信问题,但面对多个容器间通信需求,如果只用 Veth 设备的话,事情就会变得非常麻烦。让每个容器都为与它通信的其他容器建立一对专用的 Veth 设备,根本不切实际。 - - -此时,就迫切需要一台虚拟化交换机来解决多容器之间的通信问题,这正是笔者前面多次提到的 Linux bridge。 +最后,虽然 Veth 设备模拟网卡直连的方式解决了两个容器之间的通信问题,但面对多个容器间通信需求,如果只用 Veth 设备的话,事情就会变得非常麻烦。让每个容器都为与它通信的其他容器建立一对专用的 Veth 设备,根本不切实际。此时,就迫切需要一台虚拟化交换机来解决多容器之间的通信问题,这正是笔者前面多次提到的 Linux bridge。