Skip to content

Commit

Permalink
fix typo
Browse files Browse the repository at this point in the history
  • Loading branch information
isno committed Feb 5, 2025
1 parent 34797b9 commit 2709c3e
Show file tree
Hide file tree
Showing 5 changed files with 26 additions and 25 deletions.
4 changes: 3 additions & 1 deletion application-centric/Controller.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# 10.2 声明式管理的本质

许多人容易将“声明式风格的 API”和“声明式管理”混为一谈,这实际上是对声明式管理缺乏正确认识。要真正理解声明式管理,首先需要弄清楚 Kubernetes 的控制器模式。

## 10.1.1 控制器模式

Expand All @@ -14,8 +15,9 @@

总结控制器模式就是,用户通过 YAML 文件表达资源的“预期状态”,“控制器”(Controller)监视资源状态,当资源的实际状态和“预期状态”不一致时,控制器执行相应的操作,以确保两者一致。在 Kubernetes 中,这个过程被称之为“调谐”(Reconcile),Reconcile 就是不断执行“检查 -> 差异分析 -> 执行”的循环。

Reconcile 过程的存在,确保了系统状态与终态保持一致的理论正确性。许多人将“声明式管理”和“声明式风格的 API”混为一谈,实际上是对 Reconcile 的必要性缺乏正确的认识。这个逻辑很容易理解,第一次提交描述时系统达成了你想要的期望状态,并不代表、也不保证一个小时后的情况也是如此
Reconcile 过程的存在,确保了系统状态始终向预期终态收敛。这个逻辑很好理解:系统在第一次提交描述时达到了期望状态,但这并不意味着一个小时后的情况也是如此

所以说,声明式管理的核心在于“调谐”,而声明式风格的 API 只是一种对外的交互形式。

## 10.1.2 基础设施即数据思想

Expand Down
4 changes: 1 addition & 3 deletions distributed-transaction/BASE.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,7 @@ BASE 是“Basically Available”、“Soft State”和“Eventually Consistent
- **最终一致性**(Eventually consistent):最终一致性强调,即使在网络分区或系统故障的情况下,在经过足够的时间和多次数据同步操作后,所有节点的数据一定会一致。


BASE 理论是对 CAP 定理中 AP(可用性和分区容错性)方案的进一步发展,强调即使无法实现强一致性,分布式系统也可以通过适当的机制最终达到一致性。这个适当的机制可概括为**基于可靠事件队列的事件驱动模式**

接下来,以一个具体的例子帮助你理解“可靠事件队列”的具体做法。
总结 BASE 理论是对 CAP 定理中 AP(可用性和分区容错性)方案的进一步发展,强调即使无法实现强一致性,分布式系统也可以通过适当的机制最终达到一致性。适当的机制可概括为**基于可靠事件队列的事件驱动模式**。接下来,以一个具体的例子帮助你理解“可靠事件队列”的具体做法。

假设有一个电商系统,下单操作依赖于三个服务:支付服务(进行银行扣款)、库存服务(扣减商品库存)和积分服务(为用户增加积分)。下单过程中,我们优先处理最核心、风险最高的服务,按照支付扣款、仓库出库以及为用户增加积分的顺序执行。下单的整个流程如图 5-2 所示。

Expand Down
2 changes: 1 addition & 1 deletion network/network-namespace.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,6 @@ target prot opt source destination

不难看出,不同的网络命名空间默认相互隔离,也无法直接通信。如果它们需要与外界(包括其他网络命名空间或宿主机)建立连接,该如何实现呢?

我们先看看物理机是怎么操作的,一台物理机如果要想与外界进行通信,那得插入一块网卡,通过网线连接到以太网交换机,加入一个局域网内。被隔离的网络命名空间如果想与外界进行通信,就需要利用到稍后介绍的各类虚拟网络设备。也就是在网络命名空间里面插入“虚拟网卡”,然后把“网线”的另一头桥接到“虚拟交换机”中。
我们先看看物理机是怎么操作的,一台物理机如果要想与外界进行通信,那得插入一块网卡,通过网线连接到以太网交换机,加入一个局域网内。被隔离的网络命名空间如果想与外界进行通信,就需要利用到稍后介绍的各类虚拟网络设备。也就是,在网络命名空间里面插入“虚拟网卡”,然后把“网线”的另一头桥接到“虚拟交换机”中。

没错,这些操作完全和物理环境中的配置局域网一样,只不过全部是虚拟的、用代码实现的而已。
21 changes: 12 additions & 9 deletions network/tuntap.md
Original file line number Diff line number Diff line change
@@ -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)<br/>
图 3-13 VPN 中数据流动示意图
:::

将一个数据包封装到另一个数据包是构建网络隧道,实现虚拟网络的典型方式。本书第七章介绍的容器网络插件 Flannel,早期曾使用 TUN 设备实现了容器间虚拟网络通信,但使用 TUN 设备传输数据需要经过两次协议栈,且有多次的封包/解包操作,导致产生了很大的性能损耗。这是后来 Flannel 弃用 TUN 设备的主要原因。
封装数据包以构建网络隧道,是实现虚拟网络的常见方式。例如,在本书第七章介绍的容器网络插件 Flannel 早期版本中,曾使用 TUN 设备来实现容器间的虚拟网络通信。但是,TUN 设备的数据传输需经过两次协议栈,并涉及多次封包与解包操作,导致了很大的性能损耗。这也是 Flannel 后来弃用 TUN 设备的主要原因。
20 changes: 9 additions & 11 deletions network/virtual-nic.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)<br/>
图 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 作为虚拟网络设备,具备与物理网卡相同的特性,因此可以配置 IPMAC 地址。接下来,我们为 Veth 设备分配 IP 地址,使其处于同一子网 172.16.0.0/24,并同时激活设备

```bash
# 配置命名空间1
Expand All @@ -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
Expand All @@ -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。

0 comments on commit 2709c3e

Please sign in to comment.