跳到正文
复制成功
请遵守本站许可
报告
章节_文章 // 现场报告

文章编号: RL-LINUX网络命

2026.09.24

Linux 网络:命名空间、veth、网桥、ARP 与路由

Chavy
Chavy
#Kubernetes#Linux#网络#容器网络
档案

摘要:从 Network Namespace、veth pair 和 Linux Bridge 理解容器网络,梳理 ARP、邻居表、MAC 转发表与路由表的转发职责。

1. Network Namespace#

Linux Namespace 是 Linux 内核提供的一种资源隔离机制。

不同类型的 Namespace 可以隔离不同资源,例如:

Namespace隔离的主要资源
net网络设备、路由表、网络协议栈等
pid进程 ID 视图
mnt挂载点视图
uts主机名和域名信息
ipc进程间通信资源
user用户和组 ID 映射

本节重点关注 net,也就是 Network Namespace。

1. 没有网络隔离时#

假设 Linux 主机上运行两个普通进程:

flowchart TB
    subgraph G0["Linux 主机"]
        direction TB
        N0["进程 A"]
        N1["进程 B"]
    end
    subgraph G1["共享主机网络环境"]
        direction TB
        N2["网卡"]
        N3["IP 地址"]
        N4["路由表"]
        N5["网络协议栈"]
    end
    N0 -.->|"共享"| N2
    N0 -.->|"共享"| N3
    N0 -.->|"共享"| N4
    N0 -.->|"共享"| N5
    N1 -.->|"共享"| N2
    N1 -.->|"共享"| N3
    N1 -.->|"共享"| N4
    N1 -.->|"共享"| N5

它们通常共享主机的网络命名空间,因此使用同一套网络设备和路由环境。

2. 使用 Network Namespace 后#

可以为不同进程创建独立的网络环境:

宿主机 Network Namespace

eth0:192.168.1.10 独立路由表、网络设备与协议栈

Namespace A eth0:10.0.1.2 自己的路由表 自己的网络协议栈

Namespace B eth0:10.0.2.2 自己的路由表 自己的网络协议栈

示意:每个网络命名空间拥有独立的网络视图,命名空间之间需要通过网络连接或其他机制进行通信。

每个 Network Namespace 都可以拥有自己的:

  • 网络接口。
  • IP 地址。
  • 路由表。
  • 邻居表。
  • 网络协议栈状态。

因此,两个 Namespace 可以分别拥有一个叫作 eth0 的接口,却使用不同的 IP 地址。

关键理解:网络命名空间隔离的是网络环境,而不是自动创建一条网络连接。 要让两个 Namespace 通信,还需要 veth pair、Bridge、路由或其他网络机制。

2. veth pair:连接两个网络命名空间#

理解了 Network Namespace,接下来学习 Linux 容器网络中最重要的虚拟网络设备之一:veth pair。

veth pair 是一对互相连接的虚拟以太网接口。可以把它想象成一根虚拟网线:从一端发出的数据帧,会从另一端进入。

例如:

flowchart TB
    subgraph G0["veth pair"]
        direction TB
        N1["Pod 侧:eth0"]
        N2["主机侧:vethXXXX"]
    end
    N0["Pod 网络命名空间<br/>eth0 · 10.10.1.2/24"]
    N3["宿主机网络<br/>Linux Bridge / 路由 / 其他数据面"]
    N0 <--> N1
    N1 <--> N2
    N2 <--> N3

注意:veth pair 本身不负责分配 IP 地址,也不会自动完成跨节点通信。它只提供两个网络接口之间的虚拟连接。

在常见的 Bridge 型容器网络中:

  • 一端放进 Pod 的 Network Namespace,通常命名为 eth0。
  • 另一端留在宿主机,通常命名为 veth...。
  • 主机侧接口可以连接 Linux Bridge,也可以配合路由等机制工作。

并非所有 Kubernetes CNI 都采用完全相同的拓扑。例如,某些 CNI 采用路由或 eBPF 数据面,不一定通过传统 Linux Bridge 转发。

3. Linux Bridge 是什么?#

Linux Bridge 可以理解为 Linux 内核中的一个虚拟二层交换机。

真实网络中,多台电脑可以连接到一台以太网交换机,通过 MAC 地址进行二层转发。

Linux Bridge 做的事情类似,只不过它运行在 Linux 主机内部,可以连接虚拟网络接口。

flowchart TB
    N0["Pod A<br/>eth0 · 10.10.1.2"]
    N1["veth pair<br/>连接 Pod A 与宿主机"]
    N2["Linux Bridge:br0<br/>虚拟二层交换机"]
    N3["veth-b<br/>Pod B 的主机侧接口"]
    N4["veth-c<br/>Pod C 的主机侧接口"]
    N5["Pod B<br/>10.10.1.3"]
    N6["Pod C<br/>10.10.1.4"]
    N0 --> N1
    N1 --> N2
    N2 --> N3
    N2 --> N4
    N3 --> N5
    N4 --> N6

图中展示的是典型的 Bridge 型容器网络模型。实际 Kubernetes CNI 可能采用路由、Overlay 或 eBPF 等其他实现。

理解 Linux Bridge 时,要记住:Bridge 主要依据以太网帧的 MAC 地址进行二层转发,而路由器主要依据 IP 地址进行三层转发。

4. Bridge 如何转发数据?#

假设三个 Pod 位于同一个 IP 子网:

PodIP 地址MAC 地址(示例)
Pod A10.10.1.202:00:00:00:00:0a
Pod B10.10.1.302:00:00:00:00:0b
Pod C10.10.1.402:00:00:00:00:0c

Pod A 要向 Pod B 发送数据时,需要知道目标 MAC 地址。

如果 Pod A 不知道 10.10.1.3 对应的 MAC 地址,它会通过 ARP 请求进行解析。

拿到目标 MAC 地址后,Pod A 构造以太网帧,并通过自己的 eth0 发出。

数据帧经过 veth pair 进入宿主机,再由 Bridge 根据 MAC 地址转发给 Pod B 对应的接口。

完整路径如下:

flowchart TB
    N0["Pod A eth0"]
    N1["veth pair"]
    N2["Linux Bridge br0"]
    N3["Pod B 对应的 veth"]
    N4["Pod B eth0"]
    N0 --> N1
    N1 --> N2
    N2 -->|"根据目标 MAC 查找转发表"| N3
    N3 --> N4

如果 Bridge 尚未学习目标 MAC 对应的端口,或者目的 MAC 是广播地址,可能需要进行泛洪转发。具体行为取决于 Bridge 的转发表和配置。

Bridge 的 FDB(转发数据库)与 Namespace 的邻居表不是同一张表:

  • 邻居表:记录 IP 地址与 MAC 地址的映射。
  • Bridge FDB:记录 MAC 地址从哪个 Bridge 端口可以到达。

这是两个经常被混淆的概念。

5. ARP:知道 IP,为什么还需要 MAC?#

这是理解局域网通信的关键。

IP 地址用于三层寻址,而以太网帧需要目标 MAC 地址才能在二层网络中传输。

例如,Pod A 要访问 10.10.1.3:

  1. Pod A 检查自己的路由表。
  2. 判断目标 IP 位于直连子网。
  3. 查询邻居表,寻找 10.10.1.3 对应的 MAC 地址。
  4. 如果没有有效映射,通过 ARP 请求询问局域网中的设备。
  5. Pod B 收到 ARP 请求后,返回自己的 MAC 地址。
  6. Pod A 缓存这个映射,再发送实际的数据帧。
flowchart TB
    N0["Pod A<br/>想访问 10.10.1.3"]
    N1["ARP Request:广播询问<br/>谁拥有 10.10.1.3?"]
    N2["Pod B:ARP Reply<br/>10.10.1.3 对应我的 MAC 地址"]
    N3["Pod A 缓存映射并发送数据<br/>IP 数据包封装进以太网帧"]
    N0 --> N1
    N1 --> N2
    N2 --> N3

这里有一个非常重要的细节:

ARP 只负责解析同一链路上下一跳的 MAC 地址,并不是所有情况下都解析最终目标 IP 的 MAC。

如果目标 IP 不在本地子网,Pod 通常会把数据包发送给默认网关。此时,Pod 需要解析的是网关的 MAC 地址,而不是远端 Pod 的 MAC 地址。

这也解释了为什么跨节点网络中,即使源 Pod 知道目标 Pod 的 IP 地址,也不一定能直接获得目标 Pod 的 MAC 地址。

6. 邻居表:Linux 如何记住 IP 与 MAC 的对应关系?#

每次访问一个 IP 都重新发送 ARP 请求会产生不必要的网络开销。

因此,Linux 会缓存解析结果。

在 Linux 中,可以使用以下命令查看邻居表:

PRTCL // BASH
Terminal window
ip neigh show

如果想查看特定接口的记录:

PRTCL // BASH
Terminal window
ip neigh show dev eth0

输出可能类似:

PRTCL // TEXT
10.10.1.3 dev eth0 lladdr 02:00:00:00:00:0b REACHABLE
10.10.1.4 dev eth0 lladdr 02:00:00:00:00:0c STALE

字段解释:

字段含义
10.10.1.3目标 IP 地址
dev eth0使用的网络接口
lladdr对应的链路层地址,通常是 MAC 地址
REACHABLE映射被认为仍然可达
STALE缓存存在,但尚未确认其当前可达性

其他常见状态还有 DELAY、PROBE、INCOMPLETE 和 FAILED。这些状态可以帮助你判断邻居解析是否成功。

1. ARP 失败会出现什么现象?#

例如:

PRTCL // TEXT
10.10.1.3 dev eth0 INCOMPLETE

如果长时间无法完成邻居解析,可能意味着:

  • 目标设备没有响应。
  • 二层网络连接有问题。
  • 接口或 VLAN 配置不正确。
  • 广播请求没有到达目标。
  • 目标 IP 地址配置错误。

不过,看到 INCOMPLETE 并不能直接证明 Bridge 故障,还需要结合路由、接口状态和抓包结果判断。

7. 先理解:交换机和路由器有什么区别?#

我们先建立一个简单模型。

flowchart LR
    subgraph G0["网段 A:10.10.1.0/24"]
        direction LR
        N0["主机 A<br/>10.10.1.10"]
        N1["主机 B<br/>10.10.1.20"]
        N2["二层交换机 / Linux Bridge"]
    end
    subgraph G1["网段 B:10.10.2.0/24"]
        direction LR
        N4["主机 C<br/>10.10.2.10"]
    end
    N3["路由器 / Linux 路由节点<br/>连接两个 IP 网段"]
    N0 <--> N2
    N1 <--> N2
    N2 <--> N3
    N3 <--> N4

主机 A 访问主机 B 时,两者在同一个子网中,通常可以直接通过二层网络通信。

但是,当主机 A 访问主机 C 时,目标 IP 10.10.2.10 不属于本地 10.10.1.0/24 网段。此时主机 A 通常需要将数据包交给路由器,由路由器继续转发。

因此:

  • 二层交换:主要依据 MAC 地址转发以太网帧。
  • 三层路由:根据 IP 地址和路由表决定下一跳。

Linux Bridge 属于二层转发机制,而 Linux 本身也可以充当三层路由器。

8. 路由表:Linux 如何决定数据包往哪里走?#

Linux 通过路由表决定 IP 数据包应该从哪个接口发出,以及应该交给哪个下一跳。

查看路由表:

PRTCL // BASH
Terminal window
ip route

例如:

PRTCL // TEXT
default via 192.168.1.1 dev eth0
10.10.1.0/24 dev eth1 proto kernel scope link src 10.10.1.10
192.168.1.0/24 dev eth0 proto kernel scope link src 192.168.1.10

逐条解释:

路由含义
default via 192.168.1.1 dev eth0没有更具体路由时,经 eth0 交给网关
10.10.1.0/24 dev eth1目标属于这个网段时,从 eth1 直接发送
192.168.1.0/24 dev eth0目标属于这个网段时,从 eth0 直接发送

其中:

  • via 表示下一跳网关。
  • dev 表示发送接口。
  • src 表示该路由通常使用的首选源地址。
  • default 表示默认路由,等价于 0.0.0.0/0。

1. Linux 如何匹配路由?#

假设路由表是:

PRTCL // TEXT
10.0.0.0/8 via 192.168.1.1
10.10.0.0/16 via 192.168.1.2
10.10.1.0/24 via 192.168.1.3
default via 192.168.1.254

现在目标 IP 是 10.10.1.20。

它同时匹配前三条路由,但 Linux 通常选择最长前缀匹配,也就是最具体的路由:

PRTCL // TEXT
10.10.1.0/24 via 192.168.1.3

如果目标是 10.10.2.20,则 /24 路由不再匹配,会选择:

PRTCL // TEXT
10.10.0.0/16 via 192.168.1.2

如果目标是 172.16.1.10,上述路由都不匹配,才会考虑默认路由。

实际路由选择还可能受到策略路由、路由表优先级和其他内核配置影响。

可以使用以下命令查询 Linux 对具体目标的路由判断:

PRTCL // BASH
Terminal window
ip route get 10.10.1.20
ip route get 10.10.2.20
ip route get 172.16.1.10

这是排查 Linux 网络问题时非常实用的命令。

9. 默认网关:为什么访问外部网络需要它?#

假设一台 Linux 主机的配置如下:

PRTCL // TEXT
IP:192.168.1.10
掩码:255.255.255.0
网关:192.168.1.1

主机要访问 192.168.1.20 时,目标与本机处于同一子网,通常可以直接通信。

但是,如果访问 8.8.8.8,目标不在本地子网中,主机就需要查找路由表。

假设存在默认路由:

PRTCL // TEXT
default via 192.168.1.1 dev eth0

数据包就会被交给 192.168.1.1,由它继续转发。

flowchart TB
    N0["Linux 主机<br/>192.168.1.10"]
    N1["默认网关<br/>192.168.1.1"]
    N2["其他网络 / Internet<br/>继续逐跳转发"]
    N0 --> N1
    N1 --> N2

要注意,默认网关并不是互联网本身,也不保证目标一定可达。它只是主机在没有更具体路由时使用的下一跳。

10. 跨网段通信时,ARP 到底解析谁?#

这是本节最重要的知识点之一。

假设:

PRTCL // TEXT
主机 A:
IP:10.10.1.10/24
MAC:AA-AA-AA-AA-AA-AA
网关:
IP:10.10.1.1
MAC:BB-BB-BB-BB-BB-BB
主机 C:
IP:10.10.2.10/24

主机 A 想访问主机 C。

由于 10.10.2.10 不在 A 的本地子网中,A 会根据路由表决定把数据包发送给网关。

因此,A 需要解析的是:

网关 10.10.1.1 的 MAC 地址,而不是远端主机 10.10.2.10 的 MAC 地址。

数据包的变化可以这样理解:

flowchart TB
    subgraph G0["第一跳"]
        direction TB
        N0["主机 A"]
        N1["网关"]
    end
    subgraph G1["第二跳"]
        direction TB
        N2["网关"]
        N3["目标网络"]
    end
    subgraph G2["最后一跳"]
        direction TB
        N4["到达主机 C<br/>目标 IP 仍然是 10.10.2.10<br/>以太网目的 MAC 是 C 的 MAC"]
    end
    N0 -->|"IP 头部:源 10.10.1.10,目的 10.10.2.10<br/>以太网头部:源 MAC 为 A,目的 MAC 为网关"| N1
    G0 --> G1
    N2 -->|"网关查找路由表,决定下一跳<br/>重新封装新的以太网头部"| N3
    G1 --> G2

在没有 NAT 等额外处理的普通路由场景中:

  • 每一跳的以太网源 MAC 和目的 MAC 都可能变化。
  • IP 源地址和目的地址通常保持不变。
  • IP TTL 每经过一个三层转发节点通常减 1。

这就是为什么抓包时,同一个 IP 数据包在不同网络接口上可能具有不同的以太网头部。

11. 容器网络创建过程与 Kubernetes#

现在回到 Kubernetes。

当你在集群中创建一个普通 Pod 时,容器运行时与 CNI 插件会共同完成 Pod Sandbox 的网络配置。具体过程取决于运行时和插件实现。

在常见的 veth 型网络中,可以把它理解为:

flowchart TB
    N0["Kubernetes 创建 Pod"]
    N1["创建 Pod 网络命名空间"]
    N2["创建 veth pair"]
    N3["一端放入 Pod Namespace"]
    N4["另一端连接宿主机网络"]
    N5["配置 IP、路由和网络规则"]
    N6["Pod 获得网络连接能力"]
    N0 --> N1
    N1 --> N2
    N2 --> N3
    N2 --> N4
    N3 --> N5
    N4 --> N5
    N5 --> N6

但请注意,Kubernetes 并不规定所有 CNI 都必须采用 veth pair + Linux Bridge 的实现方式。这是理解容器网络的经典模型,而不是每个集群的固定结构。

12. 观察真实 Pod 的网络命名空间#

如果你有 Linux 节点的 root 权限,可以继续观察真实 Kubernetes Pod。

1. 找到 Pod 所在节点#

PRTCL // BASH
Terminal window
kubectl get pod <pod-name> -o wide

记录它所在的 Node。

2. 查看节点网络接口#

登录该节点:

PRTCL // BASH
Terminal window
ip -br addr
ip route

在传统 veth 网络中,可能会看到一些 veth... 接口;使用其他 CNI 时,也可能看到隧道设备、路由设备或其他网络接口。

3. 通过进程进入网络命名空间#

在节点上查找容器进程 PID。具体方法取决于使用的容器运行时。

拿到目标进程 PID 后,可以执行:

PRTCL // BASH
Terminal window
sudo nsenter -t <PID> -n ip addr
sudo nsenter -t <PID> -n ip route

其中:

  • -t <PID>:指定目标进程。
  • -n:进入目标进程所在的 Network Namespace。

这样就可以从宿主机直接查看该网络命名空间里的接口和路由,而不必依赖 Pod 镜像中是否安装了 ip 命令。

注意,容器进程 PID 必须来自目标 Pod 对应的容器或 Sandbox 网络命名空间,不能随意选择一个进程。

13. Bridge 与路由的排查命令#

实际排障时,可以先执行:

PRTCL // BASH
Terminal window
# 查看节点接口
ip -br addr
# 查看路由
ip route
ip route get < 目标 IP>
# 查看邻居表
ip neigh show
# 查看 Bridge
bridge link show
# 查看 Bridge 的 MAC 转发表
bridge fdb show

这些命令可以帮助你区分:

  • 路由是否正确。
  • 邻居解析是否成功。
  • Bridge 是否学习到 MAC 地址。
  • 网络接口是否处于正常状态。

如果使用 Cilium 或其他不依赖传统 Linux Bridge 的 CNI,bridge 命令没有相关输出并不代表网络故障。

ip route get < 目标 IP> 能帮助确认 Linux 当前如何选择下一跳与发送接口。

14. 跨节点网络中的路由、封装与返回路径#

假设集群中的两个 Pod 分别位于不同节点:

PRTCL // TEXT
Pod A:10.244.1.10
Node A:192.168.1.10
Pod B:10.244.2.20
Node B:192.168.1.20

当 Pod A 访问 Pod B 时,CNI 必须提供一条可达路径。

不同网络方案的实现方式不同:

  • 路由型网络:节点通过路由表知道目标 Pod 网段应该经哪个节点到达。
  • VXLAN Overlay:源节点将内部 Pod 数据包封装在外层节点 IP 数据包中,通过底层网络传送。
  • eBPF 数据面:可以通过 eBPF 程序、映射表和相关路由机制处理转发。

因此,Kubernetes 跨节点通信并不是简单地把 Pod IP 放进数据包就结束了。底层还必须存在正确的转发路径和返回路径。

15. 知识检查清单#

  1. Network Namespace:隔离网络接口、路由表和网络协议栈等网络资源。
  2. veth pair:提供一对互相连接的虚拟网络接口。
  3. Linux Bridge:Linux 内核提供的二层虚拟交换机。
  4. ARP:在 IPv4 网络中解析同一链路上的下一跳 MAC 地址,不一定是最终目的主机的 MAC。
  5. 邻居表:缓存 IP 与链路层地址映射。
  6. FDB:Bridge 根据 MAC 地址进行二层转发时使用的端口映射表。
  7. 路由表:决定下一跳和发送接口,通常采用最长前缀匹配;没有更具体路由时使用默认网关。
  8. 路由转发需要考虑返回路径、防火墙和内核转发设置。
归档于 2026.09.24
// 档案结束
Classified
章节_06
协议编号: CC-BY-NC-SA-4.0

Linux 网络:命名空间、veth、网桥、ARP 与路由

作者:Chavy发布日期:2026.09.24

基于 CC BY-NC-SA 4.0

© 2026 Chavy
Powered by Astro