Neutron VLAN 网络模型 + Linux Bridge 驱动 + 集中式路由方案整理
By Opus 4.6
一、整体架构
外部网络 / Internet
│
│
┌─────────┴─────────┐
│ External Router │
│ (物理路由器) │
└─────────┬─────────┘
│
│ VLAN 100 (external)
│
┌─────────────────────────────┼─────────────────────────────────────┐
│ Network Node │
│ │
│ ┌─────────────────────────┴─────────────────────────┐ │
│ │ eth1 (外部网络物理网卡) │ │
│ │ 接入外部网络 │ │
│ └─────────────────────────┬─────────────────────────┘ │
│ │ │
│ ┌─────────────────────────┴─────────────────────────┐ │
│ │ brq-external (Linux Bridge) │ │
│ │ 外部网络桥 │ │
│ └──────┬──────────────────────────────┬─────────────┘ │
│ │ │ │
│ ┌──────┴──────┐ ┌──────┴──────┐ │
│ │ qg-xxx │ │ qg-yyy │ │
│ │ (router gw) │ │ (router gw) │ │
│ └──────┬──────┘ └──────┬──────┘ │
│ │ │ │
│ ┌──────┴──────────────────────────────┴──────┐ │
│ │ qrouter-xxx namespace │ │
│ │ (Neutron L3 Agent 管理) │ │
│ │ │ │
│ │ 路由表 / NAT / iptables │ │
│ │ │ │
│ │ qr-aaa ──┬── qr-bbb │ │
│ │ 10.0.1.1 │ 10.0.2.1 │ │
│ └──────┬─────┴────────┬───────────────────────┘ │
│ │ │ │
│ ┌──────┴──────┐ ┌─────┴──────┐ │
│ │ brq-net1 │ │ brq-net2 │ │
│ │ VLAN 201 │ │ VLAN 202 │ │
│ └──────┬──────┘ └─────┬──────┘ │
│ │ │ │
│ ┌──────┴──────────────┴──────┐ │
│ │ eth0 (内部网络物理网卡) │ │
│ │ trunk (承载 VLAN 201/202)│ │
│ └──────────────┬─────────────┘ │
│ │ │
└──────────────────┼─────────────────────────────────────────────────┘
│
物理交换机 (trunk)
承载 VLAN 201, 202
│
┌──────────────────┼─────────────────────────────────────────────────┐
│ Compute Node │
│ │ │
│ ┌──────────────┴─────────────┐ │
│ │ eth0 (内部网络物理网卡) │ │
│ │ trunk (承载 VLAN 201/202)│ │
│ └──────┬──────────────┬──────┘ │
│ │ │ │
│ ┌──────┴──────┐ ┌─────┴──────┐ │
│ │ brq-net1 │ │ brq-net2 │ │
│ │ VLAN 201 │ │ VLAN 202 │ │
│ └──────┬──────┘ └─────┬──────┘ │
│ │ │ │
│ ┌──────┴──┐ ┌─────┴───┐ │
│ │ tap-vm1 │ │ tap-vm3 │ │
│ │ │ │ │ │
│ └────┬────┘ └────┬────┘ │
│ │ │ │
│ ┌────┴────┐ ┌────┴────┐ │
│ │ VM-1 │ │ VM-3 │ │
│ │10.0.1.10│ │10.0.2.10│ │
│ │ net1 │ │ net2 │ │
│ └─────────┘ └─────────┘ │
│ │
└────────────────────────────────────────────────────────────────────┘
二、核心概念
三个角色
┌──────────────────────────────────────────────────────────────────┐
│ │
│ Controller Node │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ neutron-server │ │
│ │ - 接收 API 请求 │ │
│ │ - 管理网络/子网/端口/路由器 数据库 │ │
│ │ - 通过 RPC 通知各节点 Agent │ │
│ └──────────────────────────────────────────────────────────┘ │
│ │
│ Network Node │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ neutron-l3-agent (管理路由器 namespace) │ │
│ │ neutron-dhcp-agent (管理 DHCP namespace) │ │
│ │ neutron-linuxbridge-agent (管理 bridge + VLAN 子接口) │ │
│ │ neutron-metadata-agent (提供 metadata 服务) │ │
│ └──────────────────────────────────────────────────────────┘ │
│ │
│ Compute Node │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ neutron-linuxbridge-agent (管理 bridge + VLAN 子接口) │ │
│ │ nova-compute (管理 VM) │ │
│ └──────────────────────────────────────────────────────────┘ │
│ │
└──────────────────────────────────────────────────────────────────┘
集中式路由的含义
"集中式路由" 意味着:
┌─────────────────────────────────────────────────────────────┐
│ │
│ 所有跨子网的流量、所有访问外部网络的流量 │
│ 都必须经过 Network Node 上的 qrouter namespace │
│ │
│ VM-1 (net1, 10.0.1.10) │
│ │ │
│ │ 跨子网或访问外网 │
│ ▼ │
│ Compute Node eth0 │
│ │ │
│ │ VLAN 201 │
│ ▼ │
│ 物理交换机 │
│ │ │
│ │ VLAN 201 │
│ ▼ │
│ Network Node eth0 │
│ │ │
│ ▼ │
│ qrouter namespace ← 路由 + NAT 都在这里做 │
│ │ │
│ │ 如果目标是 net2: 路由到 VLAN 202 → 物理交换机 → 计算节点 │
│ │ 如果目标是外网: NAT → 外部网络 │
│ ▼ │
│ 目的地 │
│ │
└─────────────────────────────────────────────────────────────┘
优点: 简单,状态集中
缺点: Network Node 是瓶颈,是单点
三、Compute Node 详细结构
┌──────────────────── Compute Node ──────────────────────────────────┐
│ │
│ 物理网卡 eth0 │
│ ┌────────────────────────────────────────────────────────────┐ │
│ │ eth0: trunk port │ │
│ │ 承载 VLAN 201, 202 ... │ │
│ │ │ │
│ │ 内核自动创建 VLAN 子接口: │ │
│ │ eth0.201 ──── 标记/去标记 VLAN 201 的帧 │ │
│ │ eth0.202 ──── 标记/去标记 VLAN 202 的帧 │ │
│ └────┬───────────────────────────────┬──────────────────────┘ │
│ │ │ │
│ │ │ │
│ ┌────┴─────────────────┐ ┌────────┴─────────────────┐ │
│ │ brq-<net1-id> │ │ brq-<net2-id> │ │
│ │ Linux Bridge │ │ Linux Bridge │ │
│ │ │ │ │ │
│ │ 端口: │ │ 端口: │ │
│ │ - eth0.201 (上行) │ │ - eth0.202 (上行) │ │
│ │ - tap-vm1 (VM-1) │ │ - tap-vm3 (VM-3) │ │
│ │ - tap-vm2 (VM-2) │ │ - tap-vm4 (VM-4) │ │
│ │ │ │ │ │
│ │ 安全组: iptables │ │ 安全组: iptables │ │
│ │ 在 tap 端口上 │ │ 在 tap 端口上 │ │
│ │ │ │ │ │
│ └──────────────────────┘ └──────────────────────────┘ │
│ │ │ │ │ │
│ ┌────┴───┐ ┌────┴───┐ ┌────┴───┐ ┌────┴───┐ │
│ │tap-vm1 │ │tap-vm2 │ │tap-vm3 │ │tap-vm4 │ │
│ └────┬───┘ └────┬───┘ └────┬───┘ └────┬───┘ │
│ │ │ │ │ │
│ ┌────┴───┐ ┌────┴───┐ ┌────┴───┐ ┌────┴───┐ │
│ │ VM-1 │ │ VM-2 │ │ VM-3 │ │ VM-4 │ │
│ │ net1 │ │ net1 │ │ net2 │ │ net2 │ │
│ │10.0.1 │ │10.0.1 │ │10.0.2 │ │10.0.2 │ │
│ │ .10 │ │ .11 │ │ .10 │ │ .11 │ │
│ └────────┘ └────────┘ └────────┘ └────────┘ │
│ │
└────────────────────────────────────────────────────────────────────┘
VLAN 子接口的作用
eth0 收到一个带 VLAN tag 201 的帧:
┌─────────────────────────────────────────────────────────────┐
│ Dst MAC │ Src MAC │ 802.1Q: VLAN 201 │ EtherType │ Payload │
└─────────────────────────────────────────────────────────────┘
│
▼
eth0 收到帧
│
│ 内核 VLAN 处理
▼
eth0.201 剥离 VLAN tag
│
│ 帧变成普通以太网帧
▼
brq-net1 (bridge)
│
│ 二层转发
▼
tap-vm1 → VM-1
eth0.201 发送一个帧:
VM-1 → tap-vm1 → brq-net1 → eth0.201
│
│ 自动加上 VLAN 201 tag
▼
eth0 发出
│
┌───────────┴───────────────────┐
│ 带 VLAN 201 tag 的以太网帧 │
└───────────────────────────────┘
linuxbridge-agent 在计算节点做了什么
neutron-linuxbridge-agent 启动后:
当 neutron-server 通知 "节点上有 VM 要接入 net1 (VLAN 201)" 时:
① 创建 VLAN 子接口 (如果不存在)
ip link add link eth0 name eth0.201 type vlan id 201
ip link set eth0.201 up
② 创建 Linux Bridge (如果不存在)
brctl addbr brq-<net1-uuid-前11位>
ip link set brq-<net1-uuid> up
③ 将 VLAN 子接口加入 Bridge
brctl addif brq-<net1-uuid> eth0.201
④ VM 启动时,Nova 创建 tap 设备并加入 Bridge
(实际上 tap 设备由 libvirt/qemu 创建)
brctl addif brq-<net1-uuid> tap-<port-uuid-前11位>
⑤ 配置安全组
iptables 规则挂在 tap 设备上
四、Network Node 详细结构
┌────────────────────── Network Node ─────────────────────────────────────┐
│ │
│ ┌──────────── Host Network Namespace ──────────────────────────────┐ │
│ │ │ │
│ │ eth0 (内部网络) eth1 (外部网络) │ │
│ │ trunk: VLAN 201,202 flat 或 VLAN │ │
│ │ │ │ │ │
│ │ ├── eth0.201 │ │ │
│ │ │ │ │ │ │
│ │ │ ┌──┴──────────┐ ┌─┴──────────────┐ │ │
│ │ │ │ brq-net1 │ │ brq-external │ │ │
│ │ │ │ │ │ │ │ │
│ │ │ │ 端口: │ │ 端口: │ │ │
│ │ │ │ - eth0.201 │ │ - eth1 │ │ │
│ │ │ │ - qr-aaa ───┼──┼── qg-xxx ──┐ │ │ │
│ │ │ │ - tap-dhcp1 │ │ │ │ │ │
│ │ │ └─────────────┘ └─────────────┘ │ │ │
│ │ │ │ │ │
│ │ ├── eth0.202 │ │ │
│ │ │ │ │ │ │
│ │ │ ┌──┴──────────┐ │ │ │
│ │ │ │ brq-net2 │ │ │ │
│ │ │ │ │ │ │ │
│ │ │ │ 端口: │ │ │ │
│ │ │ │ - eth0.202 │ │ │ │
│ │ │ │ - qr-bbb ───┼───────────────┐ │ │ │
│ │ │ │ - tap-dhcp2 │ │ │ │ │
│ │ │ └─────────────┘ │ │ │ │
│ │ │ │ │ │ │
│ └─────┼────────────────────────────────┼──┼──────────────────────┘ │
│ │ │ │ │
│ │ ┌───────────────────────────┼──┼──────────────────┐ │
│ │ │ qrouter-<router-uuid> namespace │ │
│ │ │ │ │ │ │
│ │ │ ┌────────┐ ┌──────────┘ │ ┌────────┐ │ │
│ │ │ │ qr-aaa │ │ qg-xxx │ │ qr-bbb │ │ │
│ │ │ │10.0.1.1│ │172.16.1.100 │ │10.0.2.1│ │ │
│ │ │ └────┬───┘ └──────┬──────┘ └────┬───┘ │ │
│ │ │ │ │ │ │ │
│ │ │ │ 路由表: │ │ │
│ │ │ │ 10.0.1.0/24 dev qr-aaa │ │ │
│ │ │ │ 10.0.2.0/24 dev qr-bbb │ │ │
│ │ │ │ 0.0.0.0/0 via 172.16.1.1 │ │ │
│ │ │ │ dev qg-xxx │ │ │
│ │ │ │ │ │ │
│ │ │ │ iptables NAT: │ │ │
│ │ │ │ SNAT 10.0.x.x → 172.16.1.100│ │ │
│ │ │ │ DNAT floating_ip → fixed_ip │ │ │
│ │ │ │ │ │ │
│ │ └───────┼────────────────────────────────┼───────┘ │
│ │ │ │ │
│ │ ┌───────┼────────────────────────────────┼───────┐ │
│ │ │ qdhcp-<net1-uuid> namespace │ │ │
│ │ │ │ │ │ │
│ │ │ ┌────┴─────┐ │ │ │
│ │ │ │ tap-dhcp1│ │ │ │
│ │ │ │ 10.0.1.2 │ │ │ │
│ │ │ │ dnsmasq │ │ │ │
│ │ │ └──────────┘ │ │ │
│ │ └────────────────────────────────────────┘ │ │
│ │ │ │
│ │ ┌────────────────────────────────────────┐ │ │
│ │ │ qdhcp-<net2-uuid> namespace │ │ │
│ │ │ │ │ │ │
│ │ │ ┌────┴─────┐ │ │ │
│ │ │ │ tap-dhcp2│ │ │ │
│ │ │ │ 10.0.2.2 │ │ │ │
│ │ │ │ dnsmasq │ │ │ │
│ │ │ └──────────┘ │ │ │
│ │ └────────────────────────────────────────┘ │ │
│ │ │ │
└────────┼─────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────┘
qrouter namespace 内的配置
# 进入 router namespace
ip netns exec qrouter-<uuid> bash
# 查看接口
ip addr show
# qr-aaa: 10.0.1.1/24 (net1 的网关)
# qr-bbb: 10.0.2.1/24 (net2 的网关)
# qg-xxx: 172.16.1.100/24 (外部网络接口)
# 查看路由
ip route show
# 10.0.1.0/24 dev qr-aaa
# 10.0.2.0/24 dev qr-bbb
# default via 172.16.1.1 dev qg-xxx
# 查看 NAT 规则
iptables -t nat -S
# -A neutron-l3-agent-POSTROUTING -s 10.0.1.0/24 -j SNAT --to 172.16.1.100
# -A neutron-l3-agent-POSTROUTING -s 10.0.2.0/24 -j SNAT --to 172.16.1.100
# -A neutron-l3-agent-PREROUTING -d 172.16.1.200 -j DNAT --to 10.0.1.10 (floating ip)
五、四种典型流量路径
场景 1:同子网同节点(VM-1 → VM-2)
两个 VM 都在 Compute Node,都在 net1
VM-1 (10.0.1.10)
│
│ dst MAC = VM-2 MAC (ARP 学到的)
│ dst IP = 10.0.1.11
▼
tap-vm1
│
▼
brq-net1 (Linux Bridge)
│
│ FDB 查 dst MAC → 出端口 = tap-vm2
│ 💡 纯二层转发,不出节点
▼
tap-vm2
│
▼
VM-2 (10.0.1.11) ✅
流量路径:
VM-1 → tap-vm1 → brq-net1 → tap-vm2 → VM-2
不经过 Network Node ✅
不经过物理网络 ✅
不经过路由器 ✅
场景 2:同子网跨节点(VM-1 → VM-2')
VM-1 在 Compute-1,VM-2' 在 Compute-2,都在 net1
Compute-1 物理交换机 Compute-2
───────── ────────── ─────────
VM-1 (10.0.1.10) VM-2' (10.0.1.12)
│ ▲
│ dst MAC = VM-2' MAC │
▼ │
tap-vm1 tap-vm2'
│ ▲
▼ │
brq-net1 brq-net1
│ ▲
│ FDB 查 dst MAC → 未知 → 泛洪 │
│ 或已学到 → 出端口 = eth0.201 │
▼ │
eth0.201 eth0.201
│ 加 VLAN 201 tag 剥 VLAN tag │
▼ │
eth0 ──────────► 物理交换机 (VLAN 201) ──────────► eth0
trunk 转发
流量路径:
VM-1 → tap → brq-net1 → eth0.201 → eth0
→ 物理交换机 (VLAN 201 二层转发)
→ eth0 → eth0.201 → brq-net1 → tap → VM-2'
不经过 Network Node ✅
不经过路由器 ✅
纯二层 VLAN 转发 ✅
场景 3:跨子网(VM-1 net1 → VM-3 net2)⭐集中式路由
Compute Node 物理交换机 Network Node
──────────── ────────── ────────────
VM-1 (10.0.1.10, net1)
│
│ dst IP = 10.0.2.10
│ dst MAC = 网关 MAC (qr-aaa 的 MAC)
│ 💡 VM 发现目的 IP 不在同子网
│ 所以 dst MAC 填网关 MAC
▼
tap-vm1
│
▼
brq-net1
│
│ FDB 查 dst MAC = qr-aaa MAC → 出端口 = eth0.201
▼
eth0.201 → eth0
│
│ VLAN 201
▼
物理交换机 ──────────────────────────────────────────►
│
│ VLAN 201
▼
eth0 → eth0.201
│
▼
brq-net1
│
│ dst MAC = qr-aaa
▼
qr-aaa (在 brq-net1 上)
│
│ 进入 qrouter namespace
▼
┌──────────────────────┐
│ qrouter namespace │
│ │
│ 路由查找: │
│ 10.0.2.0/24 │
│ → dev qr-bbb │
│ │
│ 修改 MAC: │
│ src MAC = qr-bbb MAC │
│ dst MAC = VM-3 MAC │
│ (查 ARP 表) │
│ TTL - 1 │
│ │
└──────────┬───────────┘
│
▼
qr-bbb
│
▼
brq-net2
│
▼
eth0.202 → eth0
│
│ VLAN 202
▼
物理交换机 ◄────────────────────────────────────
│
│ VLAN 202
▼
Compute Node (可能是同一个也可能不同)
eth0 → eth0.202 → brq-net2 → tap-vm3 → VM-3 (10.0.2.10) ✅
完整路径:
VM-1 → tap → brq-net1 → eth0.201 → eth0
→ 物理网络 (VLAN 201)
→ Network Node eth0 → eth0.201 → brq-net1
→ qr-aaa → [qrouter: 路由] → qr-bbb
→ brq-net2 → eth0.202 → eth0
→ 物理网络 (VLAN 202)
→ Compute Node eth0 → eth0.202 → brq-net2
→ tap → VM-3
💡 关键: 流量必须绕到 Network Node 做路由
💡 即使 VM-1 和 VM-3 在同一个计算节点也要绕行!
场景 4:VM 访问外部网络(Floating IP / SNAT)
VM-1 (10.0.1.10) → Internet (8.8.8.8)
Floating IP: 172.16.1.200 → 10.0.1.10
VM-1 (10.0.1.10)
│
│ dst IP = 8.8.8.8
│ dst MAC = 网关 MAC (qr-aaa)
▼
tap → brq-net1 → eth0.201 → eth0
│
│ VLAN 201 → 物理网络
▼
Network Node: eth0 → eth0.201 → brq-net1 → qr-aaa
│
│ 进入 qrouter namespace
▼
┌──────────────────────────────────────────────────┐
│ qrouter namespace │
│ │
│ 路由查找: │
│ 8.8.8.8 → default via 172.16.1.1 dev qg-xxx │
│ │
│ iptables NAT: │
│ │
│ 情况A: VM-1 有 Floating IP │
│ SNAT: src 10.0.1.10 → 172.16.1.200 │
│ (1:1 NAT) │
│ │
│ 情况B: VM-1 没有 Floating IP │
│ SNAT: src 10.0.1.10 → 172.16.1.100 │
│ (router 的网关 IP,多对一 SNAT) │
│ │
└──────────────────────┬───────────────────────────┘
│
▼
qg-xxx (172.16.1.100)
│
▼
brq-external
│
▼
eth1 (外部网络物理网卡)
│
▼
外部物理路由器 → Internet
回包路径 (8.8.8.8 → VM-1):
Internet → 外部路由器 → eth1 → brq-external → qg-xxx
│
│ 进入 qrouter namespace
│ DNAT: dst 172.16.1.200 → 10.0.1.10
▼
qr-aaa → brq-net1 → eth0.201 → eth0
│
│ VLAN 201 → 物理网络
▼
Compute Node: eth0 → eth0.201 → brq-net1 → tap → VM-1 ✅
六、Neutron 配置文件
neutron.conf (Controller)
[DEFAULT]
core_plugin = ml2
[ml2]
type_drivers = vlan,flat
tenant_network_types = vlan
mechanism_drivers = linuxbridge
[ml2_type_vlan]
network_vlan_ranges = physnet1:201:300
# physnet1 是物理网络标签
# 201-300 是可分配的 VLAN ID 范围
linuxbridge_agent.ini (Compute + Network Node)
[linux_bridge]
physical_interface_mappings = physnet1:eth0
# physnet1 这个标签对应物理网卡 eth0
# Neutron 会在 eth0 上创建 VLAN 子接口
[vxlan]
enable_vxlan = false
# 我们用 VLAN,不用 VXLAN
[securitygroup]
enable_security_group = true
firewall_driver = iptables
l3_agent.ini (Network Node)
[DEFAULT]
interface_driver = linuxbridge
external_network_bridge =
# 集中式路由,L3 agent 只跑在 Network Node 上
七、逐步创建网络的命令
# ═══════════ 1. 创建 Provider 网络 (外部网络) ═══════════
openstack network create \
--provider-network-type flat \
--provider-physical-network extnet \
--external \
ext-net
openstack subnet create \
--network ext-net \
--subnet-range 172.16.1.0/24 \
--gateway 172.16.1.1 \
--allocation-pool start=172.16.1.100,end=172.16.1.200 \
--no-dhcp \
ext-subnet
# ═══════════ 2. 创建租户网络 ═══════════
# net1 (VLAN 201)
openstack network create net1
# Neutron 自动从 201-300 范围分配一个 VLAN ID,比如 201
openstack subnet create \
--network net1 \
--subnet-range 10.0.1.0/24 \
--gateway 10.0.1.1 \
--dns-nameserver 8.8.8.8 \
subnet1
# net2 (VLAN 202)
openstack network create net2
openstack subnet create \
--network net2 \
--subnet-range 10.0.2.0/24 \
--gateway 10.0.2.1 \
--dns-nameserver 8.8.8.8 \
subnet2
# ═══════════ 3. 创建路由器 ═══════════
openstack router create router1
# 设置外部网关
openstack router set --external-gateway ext-net router1
# 连接内部子网
openstack router add subnet router1 subnet1
openstack router add subnet router1 subnet2
# ═══════════ 4. 创建 VM ═══════════
openstack server create \
--image cirros \
--flavor m1.tiny \
--network net1 \
vm1
openstack server create \
--image cirros \
--flavor m1.tiny \
--network net2 \
vm3
# ═══════════ 5. 分配 Floating IP ═══════════
openstack floating ip create ext-net
# 返回: 172.16.1.150
openstack server add floating ip vm1 172.16.1.150
八、每一步 Neutron 在节点上干了什么
创建 net1 后(VLAN 201)
此时还没有 VM,节点上不会立即创建设备。
VM-1 启动后(Compute Node)
# linuxbridge-agent 自动执行:
# 1. 创建 VLAN 子接口
ip link add link eth0 name eth0.201 type vlan id 201
ip link set eth0.201 up
# 2. 创建 Linux Bridge
brctl addbr brq-aaaabbbb111
ip link set brq-aaaabbbb111 up
# 3. 上行口加入 Bridge
brctl addif brq-aaaabbbb111 eth0.201
# 4. Nova/libvirt 创建 tap 并加入 Bridge
# (由 qemu 自动创建 tap)
brctl addif brq-aaaabbbb111 tap-xxxxxxxx
# 5. 安全组 iptables 规则
iptables -I FORWARD -m physdev --physdev-in tap-xxxxxxxx \
-j neutron-linuxbridge-i-xxxxxxxx
# (实际规则更复杂)
路由器连接子网后(Network Node)
# l3-agent 自动执行:
# 1. 创建 router namespace
ip netns add qrouter-<router-uuid>
# 2. 创建 qr 接口并放入 namespace
# (实际上是创建 veth pair 或 tap,一端在 bridge,一端在 namespace)
ip link add qr-aaa type veth peer name ns-qr-aaa
brctl addif brq-net1 qr-aaa
ip link set ns-qr-aaa netns qrouter-<uuid>
# 3. 在 namespace 内配置 IP
ip netns exec qrouter-<uuid> ip addr add 10.0.1.1/24 dev ns-qr-aaa
ip netns exec qrouter-<uuid> ip link set ns-qr-aaa up
# 4. 同样处理 net2
ip netns exec qrouter-<uuid> ip addr add 10.0.2.1/24 dev ns-qr-bbb
ip netns exec qrouter-<uuid> ip link set ns-qr-bbb up
# 5. 设置外部网关
ip netns exec qrouter-<uuid> ip addr add 172.16.1.100/24 dev qg-xxx
ip netns exec qrouter-<uuid> ip route add default via 172.16.1.1
# 6. 配置 NAT
ip netns exec qrouter-<uuid> iptables -t nat -A POSTROUTING \
-s 10.0.1.0/24 -o qg-xxx -j SNAT --to 172.16.1.100
ip netns exec qrouter-<uuid> iptables -t nat -A POSTROUTING \
-s 10.0.2.0/24 -o qg-xxx -j SNAT --to 172.16.1.100
九、集中式路由的瓶颈分析
┌───────────────────────────────────────────────────────────────┐
│ │
│ 集中式路由的流量路径问题: │
│ │
│ Network Node │
│ ┌──────────┐ │
│ │ qrouter │ │
│ │ │ │
│ ┌──────►│ 路由 │◄──────┐ │
│ │ │ NAT │ │ │
│ │ └──────────┘ │ │
│ │ │ │
│ │ VLAN 201 │ VLAN 202 │
│ │ │ │
│ ┌─────┴─────┐ ┌──────┴────┐ │
│ │ Compute-1 │ │ Compute-2 │ │
│ │ │ │ │ │
│ │ VM-1 │ │ VM-3 │ │
│ │ net1 │ │ net2 │ │
│ └───────────┘ └───────────┘ │
│ │
│ VM-1 → VM-3 的流量: │
│ Compute-1 → 物理网络 → Network Node → 物理网络 → Compute-2 │
│ │
│ 即使 VM-1 和 VM-3 在同一台物理机上: │
│ Compute-1 → 物理网络 → Network Node → 物理网络 → Compute-1 │
│ 💥 流量走了两趟物理网络 + 一次 Network Node │
│ │
│ 问题: │
│ 1. Network Node 是性能瓶颈 │
│ 2. Network Node 是单点故障 (需要 HA) │
│ 3. 增加物理网络带宽消耗 │
│ 4. 增加延迟 │
│ │
│ 解决方案: │
│ → DVR (分布式虚拟路由) │
│ → 每个 Compute Node 有自己的 router namespace │
│ → 东西向流量本地路由 │
│ │
└───────────────────────────────────────────────────────────────┘
十、验证和调试命令
# ═══════════ Compute Node 上 ═══════════
# 查看所有 bridge
brctl show
# 查看某个 bridge 的端口
brctl showmacs brq-aaaabbbb111
# 查看 VLAN 子接口
cat /proc/net/vlan/config
# 查看 tap 设备
ip tuntap show
# 查看 iptables 安全组规则
iptables -S | grep tap
# ═══════════ Network Node 上 ═══════════
# 查看所有 namespace
ip netns list
# 进入 router namespace
ip netns exec qrouter-<uuid> bash
# 查看路由表
ip netns exec qrouter-<uuid> ip route
# 查看 NAT 规则
ip netns exec qrouter-<uuid> iptables -t nat -S
# 查看接口
ip netns exec qrouter-<uuid> ip addr
# 在 router namespace 内抓包
ip netns exec qrouter-<uuid> tcpdump -i qr-aaa -nn
# 进入 DHCP namespace
ip netns exec qdhcp-<uuid> bash
ip netns exec qdhcp-<uuid> ps aux | grep dnsmasq
一句话总结
Neutron VLAN + Linux Bridge + 集中式路由方案中:每个租户网络对应一个 VLAN ID + 一个 Linux Bridge,VLAN 子接口作为 Bridge 的上行口连接物理网络实现二层互通;所有跨子网和外部流量必须绕行 Network Node 上的 qrouter namespace 做三层路由和 NAT。简单可靠但 Network Node 是瓶颈和单点。