2、Linux网络命名空间基础:创建、删除、配置网络命名空间

网络命名空间(Network Namespace)是 Linux 内核提供的一项轻量级虚拟化技术,它允许在同一个物理主机上创建多个独立的网络栈实例。每个网络命名空间拥有自己独立的网络设备、IP 地址、路由表、防火墙规则(iptables/nftables)、套接字(socket)以及网络协议栈状态。容器技术的核心基石之一正是网络命名空间,它确保了容器之间网络环境的隔离性。

2.1 网络命名空间的核心隔离对象

当创建一个新的网络命名空间时,内核会为该空间复制一套完整的网络资源。下表列出了网络命名空间隔离的关键资源对象:

资源对象 隔离说明 默认初始状态
网络设备 物理网卡、虚拟网卡(veth/tun/tap)、网桥等设备只能属于一个命名空间 仅有 lo(回环)设备,且默认 DOWN
IP 地址 每个命名空间独立配置 IPv4/IPv6 地址,互不干扰 无 IP 地址
路由表 独立的路由选择策略,包括默认网关、静态路由 空路由表
防火墙规则 独立的 iptables/nftables 规则链 空规则集
套接字缓冲区 TCP/UDP 连接、Unix Domain Socket 完全隔离 无监听端口
/proc/net 与 /sys/class/net 进程看到的网络文件系统视图不同 仅包含 lo
关键理解:网络命名空间提供的是“网络栈的完全副本”,而非“共享”。这意味着在命名空间 A 中监听 80 端口,不会与命名空间 B 中的 80 端口冲突。这也是容器能够运行相同服务(如 Nginx)而不发生端口冲突的根本原因。

2.2 创建与删除网络命名空间

Linux 提供了 ip netns 命令集来管理网络命名空间。该命令集是 iproute2 工具包的一部分,也是目前最标准的管理方式。

2.2.1 创建命名空间

使用 ip netns add 命令创建一个新的网络命名空间:

# 创建一个名为 ns1 的网络命名空间
sudo ip netns add ns1

# 查看系统中已有的网络命名空间
sudo ip netns list

创建成功后,系统会在 /var/run/netns/ 目录下生成一个同名的挂载点文件,用于绑定该命名空间的生命周期。

2.2.2 删除命名空间

使用 ip netns delete 命令删除一个已存在的网络命名空间:

# 删除名为 ns1 的网络命名空间
sudo ip netns delete ns1
注意:删除命名空间前,请确保该空间内没有正在运行的进程或持有引用的网络设备。如果命名空间内有进程在运行,ip netns delete 命令会失败,并提示“无法删除”。此时需要先终止该空间内的所有进程,或使用 ip netns pids 查看并清理。

2.3 在命名空间中执行命令

创建命名空间后,需要进入该空间执行网络配置命令。ip netns exec 是进入指定命名空间执行命令的标准方式:

# 在 ns1 中查看网络设备
sudo ip netns exec ns1 ip link show

# 在 ns1 中查看路由表
sudo ip netns exec ns1 ip route show

# 在 ns1 中启动回环设备
sudo ip netns exec ns1 ip link set lo up

# 在 ns1 中启动一个交互式 Shell
sudo ip netns exec ns1 bash

当使用 bash 进入交互式 Shell 后,后续所有命令都默认在 ns1 命名空间中执行,直到输入 exit 退出。

2.4 配置网络命名空间的基本网络栈

一个刚创建的网络命名空间只有 lo(回环)设备,且处于 DOWN 状态。要让该命名空间具备基本的网络通信能力,需要完成以下配置步骤:

  1. 启动回环设备:确保本地进程间通信可用。
  2. 创建 veth 对:将一端放入命名空间,另一端留在根命名空间(默认命名空间)。
  3. 分配 IP 地址:为 veth 两端配置 IP 地址。
  4. 启用设备:将 veth 设备状态设置为 UP。
  5. 配置路由:添加默认网关或静态路由。

以下是一个完整的配置示例,将 ns1 连接到根命名空间:

# 1. 创建 veth 对,一端名为 veth0,另一端名为 veth1
sudo ip link add veth0 type veth peer name veth1

# 2. 将 veth1 移动到 ns1 命名空间
sudo ip link set veth1 netns ns1

# 3. 在根命名空间中配置 veth0
sudo ip addr add 192.168.100.1/24 dev veth0
sudo ip link set veth0 up

# 4. 在 ns1 中配置 veth1
sudo ip netns exec ns1 ip addr add 192.168.100.2/24 dev veth1
sudo ip netns exec ns1 ip link set veth1 up
sudo ip netns exec ns1 ip link set lo up

# 5. 验证连通性
sudo ip netns exec ns1 ping -c 3 192.168.100.1
验证结果:如果配置正确,ping 命令将成功收到来自 192.168.100.1 的回复。这表明 ns1 已经通过 veth 对与根命名空间建立了二层网络连接。

2.5 网络命名空间与 veth 对的结构关系

下图展示了根命名空间与子命名空间通过 veth 对进行连接的典型拓扑结构:

网络命名空间与 veth 对连接拓扑 根命名空间(默认) 子命名空间(ns1) eth0(物理网卡) veth0 192.168.100.1/24 veth1 192.168.100.2/24 lo(回环) 路由表 默认路由 独立路由表 veth 虚拟网线 进程 A 在 ns1 中监听 80 端口 根命名空间无法感知该端口

2.6 查看与调试网络命名空间

在实际运维和开发过程中,经常需要查看命名空间的状态信息。以下是一些常用的调试命令:

命令 功能说明 示例输出(部分)
ip netns list 列出所有网络命名空间 ns1 (id: 0)
ip netns identify <PID> 查看指定进程所属的网络命名空间 ns1
ip netns pids <NAME> 列出指定命名空间中的所有进程 PID 12345
nsenter -t <PID> -n ip addr 通过进程 PID 进入其命名空间查看网络 显示该命名空间的 IP 地址
lsns -t net 列出所有网络命名空间及其关联进程 显示命名空间号、进程数等
实用技巧:当使用 ip netns exec 进入命名空间后,可以通过 cat /proc/$$/net/dev 查看该空间内的网络设备统计信息。这与在根命名空间中查看 /proc/net/dev 是完全不同的视图。

2.7 网络命名空间的持久化与生命周期

网络命名空间的默认生命周期与 /var/run/netns/<NAME> 文件绑定。只要该文件存在,命名空间就不会被销毁。即使创建该命名空间的进程已经退出,命名空间依然存活。这一特性使得网络命名空间非常适合用于容器场景:

  • 持久化:通过 ip netns add 创建的命名空间会一直存在,直到显式执行 ip netns delete。
  • 临时命名空间:使用 unshare -n 创建的命名空间,在最后一个进程退出后自动销毁。
  • 容器集成:Docker/containerd 等容器运行时在创建容器时,会通过 unshare() 系统调用创建新的网络命名空间,并将其持久化到容器生命周期中。