《Linux 网络虚拟化:namespace、veth、网桥与虚拟交换机》

深入 Linux 网络虚拟化:network namespace 协议栈隔离、veth pair 虚拟网线原理、Linux bridge 与 OVS 虚拟交换机、iptables/nftables 转发路径、Docker 的 bridge/host/overlay 网络模式、VRF 多租户路由,以及用 ip/netns/bridge 手动搭建与排错虚拟网络的实战。

引言

一台物理机要跑几百个「看似独立」的网络环境,靠的是网络虚拟化:network namespace 隔离各自的协议栈,veth pair 充当虚拟网线,Linux bridge / OVS 当虚拟交换机,iptables/nftables 负责转发与 NAT。Docker、Kubernetes 的容器网络正是这几样东西的组合。本文从最小单元讲起,用 ip netns/ip link/bridge 手动搭一个「两个命名空间互通」的实验,再拆解 Docker 网络模式与 VRF 多租户,最后给出排错命令集。

前置:/linux-network-commands/(网络命令与排错基础)。容器隔离原理见 /linux-containers-isolation/,虚拟化整体视图见 /linux-virtualization-guide/。


目录


1. network namespace:隔离的协议栈

network namespace 让一组进程拥有「自己的」网卡、路由表、iptables 规则——互不可见,如同各自插在同一台物理机上的独立主机:

# 创建/删除/查看命名空间
ip netns add red
ip netns add blue
ip netns list
# 在命名空间里执行命令
ip netns exec red ip addr

被隔离的网络资源:

资源是否隔离
网卡(lo、eth0…)是(各自独立)
路由表是
iptables/nftables 规则是(较新内核)
邻居表(ARP)是
端口号空间是(各自有自己的端口)
/proc/net 视图是
# 未特权创建自己的命名空间
unshare --net bash        # 新 bash 在隔离的网络栈里
# 命名空间里的进程
ip netns exec red sleep 1000 &

心智:namespace 是「容器网络的最小单位」——Docker 每个容器默认一个独立 netns。命名空间之间天生不通,要互通必须搭「桥」——这正是 veth + bridge 的用途。


2. veth pair:一根虚拟网线

veth 永远是成对出现的虚拟网线:一端发数据,另一端立刻收到——把两个 netns「物理」拉通:

# 创建一对 veth(veth0 ⇄ veth1)
ip link add veth0 type veth peer name veth1
# 把一端放进 red 命名空间
ip link set veth1 netns red
# 两端分别配 IP 并启用
ip addr add 10.0.0.1/24 dev veth0 && ip link set veth0 up
ip netns exec red ip addr add 10.0.0.2/24 dev veth1
ip netns exec red ip link set veth1 up
ip netns exec red ping 10.0.0.1
red netns         宿主            blue netns
   veth1 ⇄======= veth0 ⇄======= veth2

记忆:veth 是「线」,bridge 是「交换机」,组合起来就是一套可扩展的虚拟局域网。veth 本身只解决「两个点直连」,三五个命名空间就得靠 bridge 挂多根线。


3. Linux bridge:虚拟交换机

Linux bridge 是内核里的二层交换机:多个 veth 一端挂进来,数据按 MAC 地址转发:

# 建桥 + 挂接
ip link add br0 type bridge
ip link set veth0 master br0
ip link set veth2 master br0
ip link set br0 up
# 查看桥与端口
bridge link show
# 查看 MAC 地址表(谁在哪个口)
bridge fdb show
能力说明
MAC 学习自动记录 MAC 从哪个口来
泛洪未知单播/广播向所有端口转发
STP可选生成树,防环路
VLAN内核桥支持 802.1Q 过滤
# 老工具 brctl 的现代替代就是 ip/bridge 命令
# 桥本身也可配 IP,作为网关与外部通信
ip addr add 10.0.0.254/24 dev br0

心法:Docker 默认桥接网络 = veth + bridge + iptables NAT 的组合。排查容器互访问题时,bridge fdb show 能直接告诉你「这个 MAC 到底从哪个口进来」。


4. OVS:可编程虚拟交换机

Linux bridge 是「硬件交换机的软件版」,OVS 则是「可编程 SDN 交换机」——支持 OpenFlow,规则可由控制器下发:

# 安装并启动(Debian 系)
sudo apt install openvswitch-switch
sudo systemctl enable --now openvswitch-switch
# 建桥与端口
ovs-vsctl add-br ovs0
ovs-vsctl add-port ovs0 veth0
ovs-vsctl show
# 下发一条流规则(OpenFlow)
ovs-ofctl add-flow ovs0 'priority=10,in_port=1,actions=output:2'
对比Linux bridgeOVS
数据面内核 MAC 学习内核+用户态流表
控制面简单二层OpenFlow/控制器可编程
适用容器互通、小规模虚拟化集群、SDN、OpenStack

记忆:需要「下发规则控制走向」时选 OVS,只要「二层互通」Linux bridge 就够。生产上 OVS 常见于 OpenStack/K8s 的底层网络插件,复杂度换来的是集中管控能力。


5. iptables/nftables 与转发路径

虚拟网络通了二层,三层转发与 NAT 还要靠 netfilter 钩子——iptables/nftables 在其中扮演网关角色:

# 开启 IP 转发(容器/虚拟机网关的前提)
sysctl -w net.ipv4.ip_forward=1
echo 'net.ipv4.ip_forward=1' >> /etc/sysctl.conf
# 桥接流量的 NAT(容器访问外网)
iptables -t nat -A POSTROUTING -s 10.0.0.0/24 ! -o br0 -j MASQUERADE

netfilter 的五个钩子贯穿收发路径:PREROUTING → INPUT / FORWARD → POSTROUTING / OUTPUT。nftables 是新一代替代:

# nftables 等价规则
nft add table ip nat
nft add chain ip nat postrouting { type nat hook postrouting priority 100 \; }
nft add rule ip nat postrouting ip saddr 10.0.0.0/24 \
    oifname != "br0" masquerade

铁律:转发流量走 FORWARD 链,不是 INPUT 链。容器/虚拟机互访不通时先 iptables -L FORWARD 看默认策略,-P FORWARD DROP 的策略会把所有转发流量静默丢弃。


6. Docker 网络模式:bridge、host、overlay

Docker 把上面所有组件封装成几种开箱即用的网络模式:

模式原理场景
bridge(默认)veth + 自定义桥 + NAT单机容器互通、容器出外网
host直接用宿主网络栈性能敏感、端口直达
none无网络离线任务/手动配置
overlayVXLAN 跨主机隧道Swarm/K8s 跨节点
macvlan容器挂到物理网段容器直接拥有物理 IP
# 自定义桥接网络
docker network create -d bridge --subnet=172.20.0.0/24 mynet
docker run -d --network mynet nginx
# 查看网络细节
docker network inspect mynet
# host 模式
docker run --rm --network host alpine ip addr

心法:单机隔离用 bridge、跨主机要互通用 overlay、追求性能且不怕端口占用用 host。K8s 的 Pod 网络则是 CNI 插件(calico/flannel)在底层做同样的 namespace+veth+bridge 组合,只是更自动化。


7. VRF 与多租户网络

VRF(虚拟路由转发)在单台设备上维护多张独立路由表——让一台 Linux 同时充当多个「互不干扰的路由器」:

# 启用 VRF 支持后创建
ip link add vrf-red type vrf table 100
ip link set vrf-red up
ip link set eth1 master vrf-red
# 策略路由:按源/目的选表
ip rule add from 10.10.0.0/16 lookup 100
ip route show table 100
租户 A 的流量 → table 100(只含租户 A 的路由)
租户 B 的流量 → table 200(只含租户 B 的路由)
同一物理接口、同一设备,两套完全隔离的转发视图

记忆:VRF = 「一台设备拆成多台路由器」,比「每个租户一台虚拟机」省得多。排查多租户问题先确认 ip rule 的选表策略,再看对应表里有没有路由。


8. 实战:手动搭建 netns 互通

用一小时搭一个小实验:两个命名空间经 Linux 桥互通,并验证与外网的路径:

# 1. 两个命名空间
ip netns add red && ip netns add blue
# 2. 一对 veth,一端进 red
ip link add veth-r type veth peer name veth-r-br
ip link set veth-r netns red
# 3. 另一对 veth,一端进 blue
ip link add veth-b type veth peer name veth-b-br
ip link set veth-b netns blue
# 4. 建桥并挂接两个「桥端」
ip link add br0 type bridge
ip link set veth-r-br master br0
ip link set veth-b-br master br0
ip link set veth-r-br up && ip link set veth-b-br up && ip link set br0 up
# 5. 两端配 IP 并启用
ip netns exec red ip addr add 10.0.0.1/24 dev veth-r
ip netns exec red ip link set veth-r up
ip netns exec blue ip addr add 10.0.0.2/24 dev veth-b
ip netns exec blue ip link set veth-b up
# 6. 验证互通
ip netns exec red ping 10.0.0.2
# 7. 给桥配 IP,验证网关语义
ip addr add 10.0.0.254/24 dev br0
ip netns exec red ping 10.0.0.254

心法:这套手工流程就是 Docker 桥接网络的「裸版本」。亲手敲一遍,以后再遇到容器网络问题,心里就有完整的二层/三层画面。


9. 排错:ip、netns、bridge、tcpdump

虚拟网络排错有一套固定顺序:先看拓扑、再看状态、最后抓包:

ip netns list                 # 命名空间都在吗
ip addr                       # 宿主网卡/桥的地址与 up 状态
ip netns exec red ip addr     # 容器侧网卡有没有 up、IP 配没配
bridge link show              # 端口挂对没有
bridge fdb show               # MAC 从哪个口进来的
ip route                      # 路由表有没有默认路由
# 抓包定位「包到底到没到」
ip netns exec red tcpdump -n -i veth-r icmp
# 同时看宿主桥侧
tcpdump -n -i br0 icmp
# 常见坑位
#  网卡 DOWN(忘了 up)→ 报文丢在本地
#  FORWARD DROP → 跨桥转发被策略挡
#  没开 ip_forward → 三层转发直接失败

铁律:排错从「包在哪一层消失」入手:二层看 bridge fdb、三层看 ip route + ip_forward、策略看 iptables -L FORWARD、最后才是 tcpdump 抓包确认。


10. 速查表

需求命令
建命名空间ip netns add <name>
在命名空间执行ip netns exec <name> <cmd>
建 veth 对ip link add a type veth peer name b
把设备放进 nsip link set <dev> netns <name>
建桥ip link add br0 type bridge
挂端口进桥ip link set <dev> master br0
看桥端口bridge link show
看 MAC 表bridge fdb show
开启转发sysctl -w net.ipv4.ip_forward=1
NAT 出网iptables -t nat -A POSTROUTING ... -j MASQUERADE
建 OVS 桥ovs-vsctl add-br ovs0
建 VRFip link add vrf-red type vrf table 100
抓包tcpdump -n -i <if> icmp

一句话记忆:namespace 隔离协议栈、veth 拉虚拟网线、bridge/OVS 当虚拟交换机、iptables/nftables 管转发 NAT;Docker 桥接 = 这套组合的封装,排错按「二层 fdb → 三层路由 → 策略链 → 抓包」逐层推进。


延伸阅读

  • /linux-network-commands/ — 网络命令与基础排错
  • /linux-containers-isolation/ — 容器隔离技术全景
  • /linux-virtualization-guide/ — 虚拟化方案对比
  • /linux-security-hardening/ — 网络隔离与安全加固
  • /linux-kernel-tuning/ — 网络栈内核参数调优

继续阅读

探索更多技术文章

浏览归档,发现更多关于系统设计、工具链和工程实践的内容。

全部文章 返回首页

「linux」更多文章

  1. 《进程调度与 CPU:CFS、优先级与 cgroup CPU 控制》
  2. 《ELF 二进制与动态链接:从符号到加载》
  3. 《eBPF 与可观测性:bpftrace、追踪与动态插桩》