Linux网络虚拟化基础:Network Namespace、Veth Pair、Bridge、TUN/TAP设备
聊到云原生网络,很多人一上来就扑到CNI插件、Service Mesh这些上层东西上。但我个人的习惯是,先把地基打牢。Linux网络虚拟化的四个核心组件——Network Namespace、Veth Pair、Bridge、TUN/TAP——就是整个容器网络的地基。你想想看,Kubernetes的Pod网络、Docker的bridge模式,底层全是这些东西在撑场面。
今天我们就把这四个家伙彻底聊透。我会结合自己踩过的坑,帮你把每个组件的原理、用法、以及它们之间的协作关系理清楚。
1. Network Namespace:网络隔离的起点
Network Namespace,说白了就是Linux内核提供的一个网络栈隔离机制。每个Namespace拥有自己独立的网络设备、IP地址、路由表、防火墙规则等等。进程在哪个Namespace里,就只能看到那个Namespace里的网络资源。
我记得刚接触容器时,一直有个困惑:为什么容器里看到的网卡和宿主机不一样?后来才明白,每个容器其实都活在自己的Network Namespace里。
核心要点:Network Namespace实现了网络资源的完全隔离。不同Namespace之间默认是互不可见的,必须通过Veth Pair等设备才能打通。
创建和操作Namespace很简单,用ip netns命令就行:
# 创建两个Namespace
ip netns add ns1
ip netns add ns2
# 查看所有Namespace
ip netns list
# 在ns1里执行命令
ip netns exec ns1 ip addr
# 删除Namespace
ip netns delete ns1
这里有个小细节:ip netns exec后面跟的是Namespace名字,然后才是要执行的命令。我刚开始时经常把顺序搞反,结果报错半天找不到原因。
我的经验:调试网络问题时,我习惯先确认进程在哪个Namespace里。用ls -l /proc/<PID>/ns/net可以查看进程的网络Namespace。曾经有一次排查容器DNS解析问题,折腾了两小时,最后发现是进程跑错了Namespace。
2. Veth Pair:打通Namespace的隧道
Namespace之间默认是隔离的,那怎么通信呢?Veth Pair就是干这个的。它是一对虚拟网卡,像一根网线的两头——一端发数据,另一端就能收到。
Veth Pair总是成对出现。创建时你会得到两个接口,比如veth0和veth1。把一端放进一个Namespace,另一端放进另一个Namespace,两个Namespace就能通信了。
# 创建一对Veth
ip link add veth0 type veth peer name veth1
# 把veth0放进ns1,veth1放进ns2
ip link set veth0 netns ns1
ip link set veth1 netns ns2
# 给两端配置IP并启用
ip netns exec ns1 ip addr add 10.0.0.1/24 dev veth0
ip netns exec ns1 ip link set veth0 up
ip netns exec ns2 ip addr add 10.0.0.2/24 dev veth1
ip netns exec ns2 ip link set veth1 up
# 测试连通性
ip netns exec ns1 ping 10.0.0.2
为什么会这样?因为Veth Pair本质上是一根虚拟的网线。数据从一端进入,内核直接把它转发到另一端,不经过任何物理硬件。所以延迟极低,性能很好。
注意:Veth Pair的两端必须分别属于不同的Namespace,否则没有意义。我曾经见过有人把两端都留在默认Namespace里,然后问我为什么ping不通——嗯,那相当于把网线两头插在同一台交换机上,当然能通,但毫无隔离效果。
3. Bridge:虚拟交换机
有了Veth Pair,两个Namespace能通信了。但如果有三个、四个、几十个Namespace呢?总不能两两之间都拉一根Veth吧?这时候就需要Bridge了。
Linux Bridge就是一个虚拟的交换机。它工作在二层,基于MAC地址转发数据帧。你可以把多个Veth Pair的一端都插到这个Bridge上,所有Namespace就能互相通信了。
# 创建Bridge
ip link add br0 type bridge
ip link set br0 up
# 创建Veth Pair,一端放Namespace,另一端接Bridge
ip link add veth0 type veth peer name veth0-br
ip link set veth0 netns ns1
ip link set veth0-br master br0
ip link set veth0-br up
ip link add veth1 type veth peer name veth1-br
ip link set veth1 netns ns2
ip link set veth1-br master br0
ip link set veth1-br up
# 配置Namespace的IP
ip netns exec ns1 ip addr add 10.0.0.1/24 dev veth0
ip netns exec ns1 ip link set veth0 up
ip netns exec ns2 ip addr add 10.0.0.2/24 dev veth1
ip netns exec ns2 ip link set veth1 up
# 测试
ip netns exec ns1 ping 10.0.0.2
你看,Docker的默认bridge网络模式,底层就是这么干的。Docker Daemon会创建一个docker0的Bridge,每个容器启动时,都会创建一对Veth,一端放进容器,另一端挂到docker0上。
性能提示:Bridge转发依赖MAC地址学习。如果Namespace数量很多(比如上百个),Bridge的MAC表会膨胀,可能影响转发性能。我在一个生产环境中遇到过这个问题,后来改用Macvlan或直接路由方案解决了。
4. TUN/TAP设备:用户态与内核态的桥梁
前面讲的Veth Pair和Bridge都是二层/三层的虚拟网络设备。但TUN/TAP不一样,它工作在更底层——它允许用户态程序直接读写网络数据包。
具体来说:
- TUN设备:工作在第三层(IP层),处理IP数据包。用户态程序从TUN设备读到的是IP包,写进去的也是IP包。
- TAP设备:工作在第二层(以太网层),处理以太网帧。用户态程序从TAP设备读到的是完整的以太网帧。
我最早接触TUN/TAP是在做VPN项目的时候。OpenVPN、WireGuard这些工具,底层都是靠TUN/TAP设备来实现的。用户态程序从TUN设备读取IP包,加密后通过物理网卡发出去;对端收到后解密,再写进TUN设备,就完成了虚拟网络的打通。
# 创建TUN设备(需要root权限)
ip tuntap add dev tun0 mode tun
ip link set tun0 up
ip addr add 10.0.1.1/24 dev tun0
# 创建TAP设备
ip tuntap add dev tap0 mode tap
ip link set tap0 up
# 查看创建的TUN/TAP设备
ip link show tun0
ip link show tap0
用户态程序怎么操作TUN/TAP设备?很简单,把它当成一个普通文件来读写:
# 用cat简单测试(实际场景会用专门的程序)
cat /dev/net/tun # 读取数据包
避坑指南:我曾经在调试一个自定义网络插件时,发现TUN设备读不到数据。排查了半天,最后发现是忘了设置persist标志。默认情况下,程序关闭TUN设备后,内核会自动删除它。加上ip tuntap add dev tun0 mode tun persist才能让它持久存在。
5. 四个组件如何协同工作?
现在我们把四个组件串起来,看看它们在实际场景中是怎么配合的。
以Kubernetes的Flannel VXLAN模式为例:
- 每个Node上有一个Bridge(比如
cni0),所有Pod的Veth一端都挂在这个Bridge上。 - Pod之间的通信,如果跨Node,数据包会从Bridge转发到TUN/TAP设备(或者VXLAN隧道端点)。
- TUN/TAP设备把二层帧封装成UDP包,通过物理网卡发出去。
- 对端Node收到后,解封装,再通过Bridge转发给目标Pod。
你看,Network Namespace负责隔离,Veth Pair负责连接Namespace和Bridge,Bridge负责二层交换,TUN/TAP负责打通用户态和内核态。四个组件各司其职,构成了容器网络的基础骨架。
总结一下:
| 组件 | 层级 | 主要用途 |
|---|---|---|
| Network Namespace | 网络栈 | 隔离网络资源 |
| Veth Pair | 二层/三层 | 连接Namespace |
| Bridge | 二层 | 虚拟交换机 |
| TUN/TAP | 三层/二层 | 用户态与内核态数据交换 |
嗯,这四个组件搞明白了,后面学CNI、Service Mesh、网络策略这些东西,你会觉得豁然开朗。下一章我们聊聊更高级的网络虚拟化技术——Macvlan和IPVLAN,到时候你会发现,它们本质上也是在Namespace、Veth、Bridge这些基础组件上做的扩展。