Network Namespace 到底是个啥,别人再问你告诉他

在 Linux 系统中,每个进程的命名空间信息都暴露在 /proc/<PID>/ns/ 目录下

核心底层技术是 Linux 的 Network Namespace(网络命名空间) 和 Pause 容器。

在 Kubernetes 中,一个 Pod 并不是一个单一的实体,而是由一组共享资源的容器组成的。具体实现过程如下:

  1. Pause 容器(基础设施容器):当你创建一个 Pod 时,K8s 会首先启动一个极其轻量的 pause 容器。这个容器的唯一作用就是占用并维持一个 Network Namespace。
  2. 共享网络栈:Pod 内的其他业务容器(比如 Nginx、Java 应用等)在启动时,会被加入到这个 pause 容器创建的同一个 Network Namespace 中。
  3. 效果:因为它们都在同一个网络命名空间里,所以它们看到的网卡(如 eth0)、IP 地址、路由表、端口号都是完全一样的。这就好比几台电脑插在了同一个交换机上,甚至更亲密------它们共用同一个虚拟网卡。

一个 namespace 下可以有多个虚拟网卡吗?

完全可以。

一个 net namespace 就像一台独立的"虚拟主机",拥有自己独立的:

  1. 网卡列表(lo、eth0、br0、veth 等)
  2. 路由表
  3. iptables 规则
  4. 端口空间

在 Linux 操作系统中,网络栈(Network Stack)指的是操作系统内核处理网络数据的一整套架构。它不仅包含 IP 地址,还包含了以下整套家当:

  1. 网络接口(网卡/Network Interfaces): 比如宿主机的物理网卡 eth0,或者虚拟网卡。
  2. 路由表(Routing Table): 决定数据包从哪个网卡发出去,下一步去哪里。
  3. 防火墙规则(iptables/netfilter): 决定哪些数据包可以放行,哪些要丢弃或转发。
  4. 协议实现: TCP/UDP 等协议的底层实现。
  5. 端口(Ports): 0 到 65535 的端口资源,用来区分不同的应用程序。

创建一个独立的网络命名空间 Linux Namespace(网络命名空间)

这是容器技术的基石。Linux 允许你把网络资源隔离开来。每个 Namespace 都有自己独立的网卡、路由表 ,也就是一个命名空间有自己的网络栈。

bash 复制代码
# 创建一个名为 pod_ns 的网络命名空间
sudo ip netns add pod_ns 
# 查看是否创建成功 
ip netns list

可以进入这个命名空间,查看网络

bash 复制代码
ip netns exec pod_ns ip addr

意思是"请让我钻进 pod_ns 这个独立空间里,去执行后面的命令",

你会发现屏幕上极其干净!之前的物理网卡、宿主机 IP 统统消失了。里面只有孤零零的一张 lo(本地环回虚拟网卡),而且状态还是 DOWN(关闭的)。

这就是"网络栈隔离"的铁证! 这个小房间现在是一片绝对的白纸,它不知道外面有 eth0,也没有任何 IP 地址。

bash 复制代码
ip netns exec pod_ns ip link set lo up

进入到pod_ns 空间,启动lo网卡

bash 复制代码
ip netns del pod_ns

删除pod_ns 网络命名空间

bash 复制代码
sudo ip link add br1 type bridge

内核创建了一个名为 br1 的虚拟网卡。但此时它并没有启动,也没有分配 IP,里面也没有插任何网线

bash 复制代码
ip link show br1

目前还是处于down的状态,还没有通电,还没有ip,暂时不能通信

bash 复制代码
# 1. 先删掉 br1 上的旧 IP ,可选 如果配置错了,然后重新添加
sudo ip addr del 192.168.100.1/24 dev br1 
# 2. 给 br1 添加新 IP(举例改成 192.168.200.1) 
sudo ip addr add 192.168.200.1/24 dev br1

查询目前状态

bash 复制代码
ip addr show br1

接下来启动这个br1

bash 复制代码
sudo ip link set br1 up

已经启动了 目前是21号设备 如上图编号。

现在网桥创建好了,接下来就是把虚拟网线(veth pair)插上去

创建veth pair

bash 复制代码
sudo ip link add veth_host type veth peer name veth_ns

如果已经存在,同一个名称会报错,

具体效果与原因: 系统会返回类似 RTNETLINK answers: File exists 的错误提示5。这是因为 veth_host 这个网络接口名称在你的系统中已经存在。在 Linux 网络命名空间中,网络接口(网卡)的名称必须是唯一的,系统不允许创建同名接口

我们可以先删除,在重建

bash 复制代码
sudo ip link delete veth_host 

p link show veth_host  确保不存在
[root@test64 _data]# ip link show veth_host
Device "veth_host" does not exist.

sudo ip link add veth_host type veth peer name veth_ns

执行 ip addr 会有一对吗?

perl 复制代码
22: veth_ns@veth_host: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN group default qlen 1000
    link/ether ca:0e:10:13:fe:37 brd ff:ff:ff:ff:ff:ff
23: veth_host@veth_ns: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN group default qlen 1000
    link/ether 5e:55:f9:5f:ab:10 brd ff:ff:ff:ff:ff:ff

@ 符号的关联:

veth_ns@veth_host 表示 veth_ns 的配对端是 veth_host。

veth_host@veth_ns 表示 veth_host 的配对端是 veth_ns。

这种相互指向正是 veth(Virtual Ethernet)设备对的典型特征,它们就像一根虚拟网线的两端

把网线一头插进命名空间,一头插上网桥

veth_ns 塞进 pod_ns 命名空间: veth_ns 移到一个网络命名空间里

bash 复制代码
sudo ip link set veth_ns netns pod_ns

执行完毕后 通过ip addr观察,成对的消失了:变成了 veth_host@if22

perl 复制代码
23: veth_host@if22: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000
    link/ether 5e:55:f9:5f:ab:10 brd ff:ff:ff:ff:ff:ff link-netnsid 0
  • if22:这里的 22 是 veth_ns 在目标命名空间里的接口索引号(Index)。因为 veth_host 还在宿主机,为了让你知道它的配对端在哪,内核加上了这个后缀。

  • link-netnsid 0:这表示配对端所在的命名空间在当前视角下的 ID。

插一段:

bash 复制代码
ip netns exec pod_ns bash   

这个命令可以进入对应的网络空间执行bash命令。

接下来 把 veth_host 这头插到我们的网桥 br1 上,将 veth_host 这个虚拟网卡接入(挂载)到名为 br1的虚拟网桥(Bridge)上

bash 复制代码
sudo ip link set veth_host master br1

如何解除绑定 如果你想把 veth_host 从网桥上拔下来,可以使用 nomaster 参数:

bash 复制代码
sudo ip link set veth_host nomaster

进入到 pod_ns网络空间,给veth_ns 分配 IP,注意要和网桥是同一个网段

bash 复制代码
# 给 veth_ns 分配 IP
sudo ip netns exec pod_ns ip addr add 192.168.200.2/24 dev veth_ns
sudo ip netns exec pod_ns ip link set veth_ns up

可以发现 ip netns exec pod_ns ip addr,veth_ns网卡状态已经是up

bash 复制代码
[root@test64 _data]# ip netns exec pod_ns ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default 
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
22: veth_ns@if23: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether ca:0e:10:13:fe:37 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 192.168.200.2/24 scope global veth_ns
       valid_lft forever preferred_lft forever
    inet6 fe80::c80e:10ff:fe13:fe37/64 scope link 
       valid_lft forever preferred_lft forever

路由表

当给网桥分配IP的时候,内核会自动内核自动生成直连路由

bash 复制代码
[root@test64 _data]# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         10.10.30.254    0.0.0.0         UG    100    0        0 eth0
10.10.30.0      0.0.0.0         255.255.255.0   U     100    0        0 eth0
172.17.0.0      0.0.0.0         255.255.0.0     U     0      0        0 docker0
192.168.100.0   0.0.0.0         255.255.255.0   U     0      0        0 br0
192.168.122.0   0.0.0.0         255.255.255.0   U     0      0        0 virbr0
192.168.200.0   0.0.0.0         255.255.255.0   U     0      0        0 br1

在 route -n 的输出中,0.0.0.0 代表"无网关"。这说明 192.168.200.0/24 这个网段是直接连接在 br1 上的。内核不需要把数据包交给任何外部路由器,直接通过 br1 这个接口就能送达

验证

宿主机网桥 (192.168.200.1) <--- veth pair ---> 命名空间容器 (192.168.200.2)

1.从宿主机 ping 容器:

bash 复制代码
ping 192.168.200.2

2.从容器 ping 宿主机网关:

bash 复制代码
sudo ip netns exec pod_ns  ping 192.168.200.1

3.在容器里启动一个 Web 服务,宿主机访问:

bash 复制代码
sudo ip netns exec pod_ns python2 -m SimpleHTTPServer 8080


# 终端2:在宿主机访问
curl http://192.168.200.2:8080

发现能正常访问服务。至此我们的网络已经通了。

相关推荐
程序员老赵1 小时前
Docker 部署 Rocky Linux:轻松搭建 RHEL 兼容企业级基础镜像平台
linux·后端·docker
彬冷的心3 小时前
K8s 部署若依项目 + Harbor 私有仓库(双节点版)
云原生·容器·kubernetes
convee_ai3 小时前
Agent 执行为什么需要独立 Sandbox:拆解 Hullwork 的 gVisor 隔离
架构·kubernetes
想要成为老金高手4 小时前
Kubernetes Service 深度实践:从 ClusterIP 到 Ingress 七层代理
云原生·容器·kubernetes
码力斜杠哥4 小时前
Docker Compose快速入门笔记
笔记·docker·eureka
IT大白鼠4 小时前
Kubernetes 持久化存储:PV、PVC、StorageClass 存储体系
云原生·容器·kubernetes
青禾8375 小时前
Docker 从入门到实践:镜像、容器、数据卷与 Docker Compose
运维·docker·容器
GGG7665 小时前
K8s1.28 全栈落地|Jenkins+GitLab+Harbor DevOps 流水线封神实战
kubernetes·gitlab·jenkins
xrlfreedom5 小时前
大厂 MCP 面试实录:桌面客户端 stdio MCP Server 调试与安全加固方案设计
docker·结构化输出·mcp·提示注入防护