2. Linux 网络命名空间基础:理解 Network Namespace 概念,使用 ip netns 命令创建、删除、管理命名空间,实现基本的网络隔离。

2.1 什么是 Network Namespace?

Network Namespace(网络命名空间)是 Linux 内核提供的一项轻量级虚拟化技术,用于实现网络栈的隔离。每个 Network Namespace 拥有独立的网络设备、IP 地址、路由表、防火墙规则(iptables/ip6tables)、网络栈状态以及套接字(socket)实例。简单来说,一个 Network Namespace 就是一个独立的“网络沙箱”。

在默认情况下,Linux 系统启动后所有进程共享同一个网络命名空间(称为 root namespace 或 default namespace)。通过创建新的 Network Namespace,我们可以让进程“看到”完全不同的网络环境,从而实现多租户隔离、容器网络、测试环境模拟等高级功能。

核心概念: Network Namespace 是 Linux 容器(如 Docker、LXC)网络隔离的底层基石。理解它,你就掌握了容器网络的一半。

2.2 Network Namespace 隔离了什么?

下表列出了 Network Namespace 隔离的关键网络资源,以及它们在不同命名空间之间的独立性:

资源类型 隔离内容 是否独立 典型用途
网络设备 eth0, lo, veth, bridge, tun/tap 等 完全独立 每个命名空间拥有自己的网卡和回环接口
IP 地址 IPv4/IPv6 地址配置 完全独立 不同命名空间可使用相同 IP 段而不冲突
路由表 FIB (Forwarding Information Base) 完全独立 每个命名空间可定义独立的路由策略
防火墙规则 iptables, ip6tables, nftables 规则集 完全独立 隔离的网络安全策略
套接字 TCP/UDP/RAW socket 监听与连接 完全独立 同一端口可在不同命名空间被不同进程使用
/proc/net /proc/net/dev, /proc/net/tcp 等 完全独立 每个命名空间看到自己的网络统计
sysctl 网络参数 net.ipv4.ip_forward, net.core.somaxconn 等 部分独立 部分参数可独立配置,部分继承自 root namespace
关键洞察: 由于套接字是隔离的,在命名空间 A 中监听 0.0.0.0:8080 的进程,与命名空间 B 中监听 0.0.0.0:8080 的进程完全不会冲突。这是容器能够运行多个相同端口服务的基础。

2.3 Network Namespace 的层级关系与生命周期

Network Namespace 在 Linux 内核中通过 struct net 结构体表示,所有命名空间形成一个树形结构,但实际访问时通过文件系统路径 /var/run/netns/ 或 /proc/PID/ns/net 来引用。下图展示了命名空间之间的典型关系:

Network Namespace 层级与生命周期关系图 Network Namespace 层级与生命周期关系 Root Namespace (默认命名空间) ns1 (容器/进程组) ns2 (容器/进程组) eth0: 10.0.1.2 lo: 127.0.0.1 路由表 | iptables 规则 进程 PID: 1234 /proc/1234/ns/net eth0: 10.0.2.2 lo: 127.0.0.1 路由表 | iptables 规则 进程 PID: 5678 /proc/5678/ns/net 生命周期:命名空间随最后一个进程退出而销毁,除非通过 bind mount 持久化
重要生命周期规则: 当一个 Network Namespace 中没有任何进程运行时,该命名空间会被内核自动销毁。要持久化一个命名空间(即使没有进程),需要使用 ip netns exec 或通过 mount --bind /var/run/netns/<name> 方式保持引用。

2.4 使用 ip netns 命令管理命名空间

ip netns 是 iproute2 工具包中专门用于管理 Network Namespace 的命令行工具。它提供了创建、删除、列出、执行命令等完整操作。以下是核心命令及其功能:

命令 功能描述 示例
ip netns add <name> 创建一个新的 Network Namespace ip netns add red
ip netns delete <name> 删除指定的 Network Namespace ip netns delete red
ip netns list 列出系统中所有 Network Namespace ip netns list
ip netns exec <name> <cmd> 在指定命名空间中执行命令 ip netns exec red ip addr
ip netns identify <PID> 查看指定进程所属的命名空间名称 ip netns identify 1234
ip netns pids <name> 列出指定命名空间中的所有进程 PID ip netns pids red
ip netns monitor 监控命名空间的创建和删除事件 ip netns monitor

2.5 实战:创建与管理命名空间

下面通过一个完整的操作序列,演示如何创建、查看、进入和删除 Network Namespace。请以 root 权限执行以下命令:

步骤 1:创建两个命名空间

# 创建名为 red 和 blue 的两个网络命名空间
ip netns add red
ip netns add blue

# 验证创建结果
ip netns list

输出示例:

red
blue

步骤 2:查看命名空间中的网络设备

# 查看默认命名空间的网络设备(包含所有物理和虚拟设备)
ip link list

# 查看 red 命名空间的网络设备(只有 lo 设备)
ip netns exec red ip link list

# 查看 blue 命名空间的网络设备
ip netns exec blue ip link list
观察结果: 新创建的命名空间中默认只有一个 lo(回环)设备,且状态为 DOWN。这意味着该命名空间目前无法进行任何网络通信,包括本机回环通信。

步骤 3:启动回环接口

# 在 red 命名空间中启用 lo 接口
ip netns exec red ip link set lo up

# 验证 lo 接口状态
ip netns exec red ip link show lo

# 测试回环通信
ip netns exec red ping 127.0.0.1 -c 2

步骤 4:在命名空间中执行任意命令

# 在 red 命名空间中启动一个 bash shell
ip netns exec red bash

# 此时 shell 提示符可能不变,但网络环境已隔离
# 查看当前命名空间的网络栈
cat /proc/net/dev
ip route show
iptables -L -n

# 退出命名空间
exit
实用技巧: 使用 ip netns exec <name> bash 可以“进入”一个命名空间,后续所有命令都在该命名空间中执行。退出 bash 后,命名空间中的进程结束,但命名空间本身仍然存在(因为 ip netns 通过 bind mount 持久化了它)。

步骤 5:删除命名空间

# 删除 red 命名空间
ip netns delete red

# 验证删除
ip netns list

# 清理 blue 命名空间
ip netns delete blue

2.6 命名空间之间的通信:veth 对的基本原理

默认情况下,不同 Network Namespace 之间是完全隔离的,无法直接通信。要实现跨命名空间通信,最常用的方法是使用 veth(Virtual Ethernet)对。veth 是一对虚拟网卡,像一根“网线”的两端:一端放入一个命名空间,另一端放入另一个命名空间(或 root namespace),数据包从一端进入就会从另一端出来。

veth 对连接两个 Network Namespace veth 对:连接两个 Network Namespace Network Namespace A veth-A 10.0.1.1/24 Network Namespace B veth-B 10.0.1.2/24 虚拟网线(veth 对) 数据包流向 veth 对总是成对出现:一端发送的数据,另一端立即接收
veth 对的关键特性:
  • 成对出现: 创建 veth 对时,内核同时生成两个端点,分别称为 veth0 和 veth1(或自定义名称)。
  • 数据直通: 从一端发出的数据包,内核直接将其注入到另一端的接收队列,不经过物理网络。
  • 命名空间可迁移: 创建后,可以将 veth 的一端移动到另一个命名空间,实现跨命名空间连接。
  • 无广播域隔离: veth 对是点对点连接,不传递广播帧(除非通过 bridge 桥接)。

2.7 实战:使用 veth 对连接两个命名空间

以下命令序列演示如何创建 veth 对,并将其两端分别放入 red 和 blue 命名空间,实现两个隔离网络之间的通信:

# 1. 创建两个命名空间
ip netns add red
ip netns add blue

# 2. 创建 veth 对(两端默认在 root namespace 中)
ip link add veth-red type veth peer name veth-blue

# 3. 将 veth 两端分别移入命名空间
ip link set veth-red netns red
ip link set veth-blue netns blue

# 4. 为 veth 接口配置 IP 地址并启用
ip netns exec red ip addr add 10.0.1.1/24 dev veth-red
ip netns exec red ip link set veth-red up
ip netns exec red ip link set lo up

ip netns exec blue ip addr add 10.0.1.2/24 dev veth-blue
ip netns exec blue ip link set veth-blue up
ip netns exec blue ip link set lo up

# 5. 测试连通性
ip netns exec red ping 10.0.1.2 -c 3

# 6. 查看路由表确认
ip netns exec red ip route
ip netns exec blue ip route

# 7. 清理
ip netns delete red
ip netns delete blue

预期输出(ping 部分):

PING 10.0.1.2 (10.0.1.2) 56(84) bytes of data.
64 bytes from 10.0.1.2: icmp_seq=1 ttl=64 time=0.089 ms
64 bytes from 10.0.1.2: icmp_seq=2 ttl=64 time=0.072 ms
64 bytes from 10.0.1.2: icmp_seq=3 ttl=64 time=0.068 ms

--- 10.0.1.2 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2042ms
常见错误排查:
  • ping 不通: 检查 veth 接口是否已 up(ip netns exec <name> ip link show),以及 IP 地址是否配置正确。
  • RTNETLINK answers: File exists: 表示命名空间或 veth 对已存在,先删除再创建。
  • Cannot find device "veth-red": 确认 veth 对已创建且未被移入其他命名空间。
  • 操作权限: 所有 ip netns 和 ip link 操作需要 root 权限。

2.8 命名空间的持久化与文件系统视图

Network Namespace 在 Linux 中通过 /proc/PID/ns/net 文件表示。每个进程的 /proc/PID/ns/net 是一个符号链接,指向内核中该命名空间的唯一标识符。通过比较这些链接的 inode 号,可以判断两个进程是否在同一个命名空间中。

# 查看当前 shell 的命名空间标识
ls -l /proc/$$/ns/net

# 在 red 命名空间中查看标识
ip netns exec red ls -l /proc/$$/ns/net

# 比较两个命名空间的 inode 号
stat -L /proc/$$/ns/net
ip netns exec red stat -L /proc/$$/ns/net

ip netns 命令通过 /var/run/netns/ 目录下的 bind mount 来持久化命名空间。当你执行 ip netns add red 时,系统会:

  1. 创建一个新的 Network Namespace。
  2. 在 /var/run/netns/ 下创建一个名为 red 的文件。
  3. 通过 mount --bind /proc/PID/ns/net /var/run/netns/red 将命名空间绑定挂载到该文件。

这样,即使命名空间中的所有进程退出,由于 bind mount 的存在,内核不会销毁该命名空间。

2.9 本章小结与知识图谱

通过本章的学习,你已经掌握了 Network Namespace 的核心概念和基本操作。以下是本章的知识结构总结:

知识点 核心内容 掌握程度
Network Namespace 概念 独立的网络栈、设备、路由、防火墙、套接字 理解
隔离资源清单 网卡、IP、路由表、iptables、socket、/proc/net 记忆
ip netns 命令 add, delete, list, exec, identify, pids 熟练使用
veth 对原理 成对出现、数据直通、跨命名空间迁移 理解
跨命名空间通信 创建 veth 对、分配 IP、启用接口、ping 测试 熟练操作
命名空间生命周期 进程退出销毁、bind mount 持久化、/var/run/netns/ 理解