第一百二十三章:隔离之海
问道期涉及内核源码:
一
林小源在网络之海的边缘看到了一幕奇景——同一片海域被分割成了无数个独立的小海,每个小海都有自己的港口、自己的航线、自己的灯塔。
"这是什么?"
"网络命名空间。"一个低沉的声音从身后传来。
林小源转身,看到一个穿着灰色斗篷的老人。斗篷上绣着无数层叠的网状图案,每一层都是一个独立的网络世界。老人的面容模糊,仿佛同时存在于多个空间。
"我是 net_namespace。"老人说,"网络隔离的守护者。你看到的每个小海——都是一个独立的网络命名空间。每个命名空间有自己的网络设备、IP 地址、路由表、iptables 规则、端口空间。"
"完全独立?"
"完全独立。"老人说,"命名空间 A 里的 eth0 和命名空间 B 里的 eth0 是不同的设备——可以有不同的 IP 地址,不同的 MTU,甚至不同的驱动。它们互不可见,互不干扰。"
林小源看着那些独立的小海:"这有什么用?"
"容器。"老人说,"Docker、Kubernetes、LXC——它们都用网络命名空间。每个容器有自己的网络栈,就像一台独立的机器。容器 A 监听端口 80,容器 B 也可以监听端口 80——因为它们在不同的命名空间里。"
二
"但这些小海之间怎么通信?"林小源问。
老人从斗篷下抽出一根细细的线——一端连着一个小海,另一端连着另一个小海。
"veth pair。"老人说,"虚拟以太网对。一端在命名空间 A,另一端在命名空间 B。数据从一端进入,从另一端出来——就像一根虚拟的网线。"
林小源接过那根线,感到里面有数据在流动:"那多个命名空间呢?"
"用 bridge。"老人指向那些小海的交汇处——那里有一个巨大的平台,所有 veth pair 的另一端都连接在上面。"bridge 是虚拟交换机——它连接多个网络设备,根据 MAC 地址转发数据包。"
"就像一个中心交换机。"
"对。"老人说,"容器的 veth 一端在容器里,另一端在 bridge 上。容器发的数据包通过 veth 到达 bridge,bridge 再转发到目标容器的 veth。"
林小源看着那个平台上的数据流——无数光点在 veth pair 之间穿梭,bridge 根据 MAC 地址表把它们送到正确的目的地。
三
"网络命名空间是谁创建的?"林小源问。
"通常是容器运行时。"老人说,"但你也可以手动创建——ip netns add ns1。然后在命名空间里执行命令:ip netns exec ns1 ip addr。"
"那容器的网络是怎么配置的?"
老人走到一块石板前,上面刻着容器网络的拓扑图:
"容器启动时,运行时创建网络命名空间,创建 veth pair,一端放入容器,另一端连接到 bridge。然后配置 IP 地址、路由、iptables 规则。容器里的进程看到的是一块网卡————但实际上是 veth 的一端。"
"那跨主机的容器通信呢?"
"那是更复杂的问题。"老人说,"overlay network、VXLAN、BGP——都是解决方案。但基础是一样的:网络命名空间提供隔离,veth pair 提供连接,bridge 提供交换。"
林小源看着那些独立的小海,忽然明白了——容器的"独立网络"不是魔法,而是网络命名空间的隔离能力。每个容器以为自己有一块独立的网卡,实际上是 veth pair 的一端。
/*
* 网络命名空间:
*
* 命名空间 A 命名空间 B
* ┌──────────┐ ┌──────────┐
* │ eth0 │ │ eth0 │
* │ 10.0.1.2 │ │ 10.0.2.2 │
* │ │ │ │
* │ 路由表 │ │ 路由表 │
* │ iptables │ │ iptables │
* └──────────┘ └──────────┘
* ↑ ↑
* └─────────┬─────────────┘
* veth pair
*
* 网络命名空间的隔离:
* - 独立的网络设备
* - 独立的 IP 地址
* - 独立的路由表
* - 独立的 iptables 规则
* - 独立的端口空间
*
* 创建网络命名空间:
* ip netns add ns1
* ip netns exec ns1 ip addr
*/
printf("=== 网络命名空间 — 隔离的网络 ===\n\n");
printf("网络命名空间:\n\n");
printf(" 命名空间 A 命名空间 B\n");
printf(" ┌──────────┐ ┌──────────┐\n");
printf(" │ eth0 │ │ eth0 │\n");
printf(" │ 10.0.1.2 │ │ 10.0.2.2 │\n");
printf(" │ │ │ │\n");
printf(" │ 路由表 │ │ 路由表 │\n");
printf(" │ iptables │ │ iptables │\n");
printf(" └──────────┘ └──────────┘\n\n");
printf("--- 隔离的内容 ---\n");
printf("独立的网络设备\n");
printf("独立的 IP 地址\n");
printf("独立的路由表\n");
printf("独立的 iptables 规则\n");
printf("独立的端口空间\n\n");
printf("--- 创建和使用 ---\n");
printf("创建:\n");
printf(" ip netns add ns1\n\n");
printf("查看:\n");
printf(" ip netns list\n\n");
printf("在命名空间中执行:\n");
printf(" ip netns exec ns1 ip addr\n\n");
printf("--- 连接命名空间 ---\n");
printf("veth pair:\n");
printf(" 虚拟以太网对\n");
printf(" 一端在命名空间 A\n");
printf(" 另一端在命名空间 B\n\n");
printf("创建 veth:\n");
printf(" ip link add veth0 type veth peer name veth1\n");
printf(" ip link set veth1 netns ns1\n\n");
printf("--- 容器网络 ---\n");
printf("每个容器有自己的网络命名空间:\n");
printf(" 容器 1: 10.0.1.2\n");
printf(" 容器 2: 10.0.2.2\n");
printf(" 互相隔离\n");#include <stdio.h>
/*
* 网络命名空间:
*
* 命名空间 A 命名空间 B
* ┌──────────┐ ┌──────────┐
* │ eth0 │ │ eth0 │
* │ 10.0.1.2 │ │ 10.0.2.2 │
* │ │ │ │
* │ 路由表 │ │ 路由表 │
* │ iptables │ │ iptables │
* └──────────┘ └──────────┘
* ↑ ↑
* └─────────┬─────────────┘
* veth pair
*
* 网络命名空间的隔离:
* - 独立的网络设备
* - 独立的 IP 地址
* - 独立的路由表
* - 独立的 iptables 规则
* - 独立的端口空间
*
* 创建网络命名空间:
* ip netns add ns1
* ip netns exec ns1 ip addr
*/
int main() {
printf("=== 网络命名空间 — 隔离的网络 ===\n\n");
printf("网络命名空间:\n\n");
printf(" 命名空间 A 命名空间 B\n");
printf(" ┌──────────┐ ┌──────────┐\n");
printf(" │ eth0 │ │ eth0 │\n");
printf(" │ 10.0.1.2 │ │ 10.0.2.2 │\n");
printf(" │ │ │ │\n");
printf(" │ 路由表 │ │ 路由表 │\n");
printf(" │ iptables │ │ iptables │\n");
printf(" └──────────┘ └──────────┘\n\n");
printf("--- 隔离的内容 ---\n");
printf("独立的网络设备\n");
printf("独立的 IP 地址\n");
printf("独立的路由表\n");
printf("独立的 iptables 规则\n");
printf("独立的端口空间\n\n");
printf("--- 创建和使用 ---\n");
printf("创建:\n");
printf(" ip netns add ns1\n\n");
printf("查看:\n");
printf(" ip netns list\n\n");
printf("在命名空间中执行:\n");
printf(" ip netns exec ns1 ip addr\n\n");
printf("--- 连接命名空间 ---\n");
printf("veth pair:\n");
printf(" 虚拟以太网对\n");
printf(" 一端在命名空间 A\n");
printf(" 另一端在命名空间 B\n\n");
printf("创建 veth:\n");
printf(" ip link add veth0 type veth peer name veth1\n");
printf(" ip link set veth1 netns ns1\n\n");
printf("--- 容器网络 ---\n");
printf("每个容器有自己的网络命名空间:\n");
printf(" 容器 1: 10.0.1.2\n");
printf(" 容器 2: 10.0.2.2\n");
printf(" 互相隔离\n");
return 0;
}道藏笔记
内核启示
网络命名空间隔离网络资源。
网络命名空间的隔离:
- 独立的网络设备
- 独立的 IP 地址
- 独立的路由表
- 独立的 iptables 规则
连接命名空间:
- veth pair — 虚拟以太网对
- 网桥 — 连接多个命名空间
容器网络:
- 每个容器有自己的命名空间
- 通过 veth pair 和网桥通信
网络命名空间是"隔离之海"——让容器拥有独立的网络世界。
网络命名空间之试
容器能拥有独立 IP、路由表、防火墙和端口空间,本章依靠的隔离机制是什么?