OpenStack 网络实现的底层细节-PORT/TAP
1. TAP 设备是谁创建的?
TAP 设备是由 Hypervisor(通过 libvirt)创建的。
具体流程如下:
- 当 Nova 决定在某个计算节点上启动虚拟机时,Nova-Compute 服务会调用 libvirt API 来创建和启动虚拟机
- libvirt 根据虚拟机的配置(包括网络接口信息)执行以下操作:
- 在宿主机的网络命名空间中创建一个 TAP 设备(如
tap12345678-ab
) - 将这个 TAP 设备的一端"连接"到虚拟机的虚拟网卡(通过 KVM/QEMU 的
-netdev tap
参数) - 将 TAP 设备的名字返回给 Nova-Compute
- 在宿主机的网络命名空间中创建一个 TAP 设备(如
关键点: TAP 设备是标准的 Linux 网络设备,由内核的 tun/tap
驱动提供支持。
2. 如何将 TAP 设备与对应的虚拟机关联起来?
这种关联是通过 libvirt 的域配置(Domain XML) 建立的:
<interface type='bridge'><mac address='fa:16:3e:ab:cd:ef'/><source bridge='br-int'/><target dev='tap12345678-ab'/><model type='virtio'/><address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
</interface>
在这个配置中:
<mac address>
对应 Neutron Port 的 MAC 地址<target dev>
指定了 TAP 设备的名称<model type>
指定了虚拟网卡的类型(如 virtio)
当虚拟机启动时:
- libvirt 创建 TAP 设备
tap12345678-ab
- QEMU/KVM 进程被启动,其虚拟网卡后端连接到这个 TAP 设备
- 虚拟机内部的操作系统看到一个网络接口(通常是
eth0
),其 MAC 地址为fa:16:3e:ab:cd:ef
关联的建立: 虚拟机的数据包从虚拟网卡发出 → 经过 QEMU 处理 → 到达宿主机的 TAP 设备。
3. 如何将 TAP 设备关联到对应的虚拟交换机接口上?
这是由 Neutron Agent 完成的,具体取决于使用的网络类型:
对于 Open vSwitch:
# Neutron OVS Agent 会执行类似这样的命令:
ovs-vsctl add-port br-int tap12345678-ab
ovs-vsctl set Interface tap12345678-ab external-ids:iface-id=ports12345678-ab-cd
br-int
是 OVS 集成桥tap12345678-ab
是 TAP 设备external-ids:iface-id
非常重要,它将该 OVS 端口与 Neutron 中的 Port ID 关联起来
对于 Linux Bridge:
# Neutron Linux Bridge Agent 会执行:
brctl addif brqXXXX tap12345678-ab
ip link set tap12345678-ab up
brqXXXX
是对应的 Linux Bridgetap12345678-ab
被添加到桥接端口中
4. 虚拟交换机是如何感知到要将 TAP 设备关联到接口上的?
这是整个流程中最关键的部分——协调机制。主要有两种方式:
方式 A:基于 RPC 的主动配置(主要方式)
-
Port Binding 请求:
- Nova-Compute 在启动虚拟机前,通过 Neutron API 创建一个 Port 或查询现有 Port
- Neutron Server 在数据库中记录该 Port 应该绑定到哪个计算节点
-
信息推送:
- 计算节点上的 Neutron Agent(OVS Agent 或 Linux Bridge Agent)通过 RPC 定期向 Neutron Server 汇报自己的状态
- Neutron Server 通过 RPC 回复,告知 Agent 该节点上有哪些 Port 需要处理
-
Port 创建和绑定:
- Neutron Agent 接收到需要创建的 Port 列表
- Agent 检查本地 OVS/Linux Bridge,发现对应的 TAP 设备已经存在(由 libvirt 创建)
- Agent 执行命令将 TAP 设备添加到虚拟交换机
方式 B:基于事件触发的被动配置
-
设备创建事件:
- 当 libvirt 创建 TAP 设备时,会触发 udev 事件
- Neutron Agent 可以监听这些事件
-
端口发现:
- Agent 检测到新的 TAP 设备后,检查其属性(如 MAC 地址)
- Agent 向 Neutron Server 查询,找到对应的 Port
- 然后执行端口绑定操作
完整流程示例
让我们看一个完整的时序:
-
用户:
nova boot --image cirros --flavor m1.tiny --nic port-id=ports12345678-ab-cd vm1
-
Nova-API:接收请求,调度到计算节点01
-
Nova-Compute(计算节点01):
- 调用 Neutron API 确认 Port
ports12345678-ab-cd
的状态 - 生成 libvirt XML 配置,包含 MAC 地址和网络信息
- 调用 libvirt 启动虚拟机
- 调用 Neutron API 确认 Port
-
libvirt:
- 创建 TAP 设备
tap12345678-ab
- 启动 QEMU 进程,将虚拟网卡连接到 TAP 设备
- 创建 TAP 设备
-
Neutron OVS Agent(计算节点01):
- 通过 RPC 从 Neutron Server 获取端口更新
- 发现需要处理 Port
ports12345678-ab-cd
- 执行:
ovs-vsctl add-port br-int tap12345678-ab
- 执行:
ovs-vsctl set Interface tap12345678-ab external-ids:iface-id=ports12345678-ab-cd
-
安全组配置:
- 如果使用
iptables_hybrid
,Agent 会为tap12345678-ab
配置 iptables 规则 - 如果使用
openvswitch
驱动,Agent 会在 OVS 流表中配置规则
- 如果使用
总结
- 创建者:TAP 设备由 libvirt(受 Nova-Compute 控制)创建
- 虚拟机关联:通过 libvirt 域配置将 TAP 设备与虚拟机的虚拟网卡绑定
- 交换机关联:由 Neutron Agent 通过 ovs-vsctl/brctl 命令将 TAP 设备添加到虚拟交换机
- 感知机制:通过 Neutron Server 与 Agent 之间的 RPC 通信来协调,Neutron Server 知道每个 Port 应该绑定到哪个节点的哪个虚拟交换机
这个精密的协调机制确保了逻辑上的 Neutron Port 能够准确地映射到物理计算节点上的网络连接。