第271篇:云计算网络基础:虚拟交换机(OVS)
关键词:OVS、Open vSwitch、虚拟交换机、虚拟化网络、VLAN、VXLAN、流表
一、引言
在云计算环境中,虚拟机(VM)和容器需要通过网络进行通信。传统物理交换机无法直接连接运行在同一台物理服务器上的虚拟机,因此需要虚拟交换机(Virtual Switch)来实现虚拟机之间的二层连接以及虚拟机到外部网络的连接。
Open vSwitch(OVS)是目前最流行的开源虚拟交换机,被OpenStack、Kubernetes、VMware等主流云平台广泛采用。OVS不仅提供了传统交换机的基本功能,还通过OpenFlow协议实现了可编程的数据转发能力。
二、核心概念
2.1 虚拟交换机的角色
虚拟交换机与物理交换机的对比:
| 特性 | 物理交换机 | 虚拟交换机(OVS) |
|---|---|---|
| 运行环境 | 专用硬件 | 宿主机操作系统内核/用户空间 |
| 端口 | 物理端口 | 虚拟端口(vNIC/Tap) |
| 转发方式 | ASIC硬件转发 | 软件转发/DPDK硬件卸载 |
| 可编程性 | 有限 | 高(OpenFlow流表) |
| 管理方式 | CLI/SNMP | CLI/REST API/SDN控制器 |
| 扩展性 | 固定端口数 | 动态端口 |
2.2 OVS 架构

OVS核心组件:
| 组件 | 说明 |
|---|---|
| ovs-vswitchd | 核心转发守护进程,维护流表,处理数据转发 |
| ovsdb-server | 配置数据库服务,存储交换机配置 |
| ovs-vsctl | 命令行管理工具 |
| ovs-ofctl | OpenFlow流表管理工具 |
| datapath | 数据转发路径(内核模式或DPDK模式) |
2.3 OVS 网桥类型
| 网桥类型 | 说明 | 适用场景 |
|---|---|---|
| Internal Bridge | 内部网桥,端口在同一宿主机 | VM间通信 |
| Integrated Bridge | 集成网桥,连接物理网卡 | VM到外部网络 |
| Patch Port | 补丁端口,连接两个网桥 | 网桥间互联 |
| VLAN Bridge | VLAN标记网桥 | VLAN隔离 |
三、技术细节
2.4 OVS 流表转发
OVS基于OpenFlow流表实现数据包转发,流表由多个表项(Flow Entry)组成:
流表结构:
| 字段 | 说明 |
|---|---|
| Priority | 优先级,高优先级表项优先匹配 |
| Match | 匹配条件(源MAC、目的MAC、VLAN、IP、端口等) |
| Actions | 动作(转发、丢弃、修改、输出等) |
| Duration | 表项存活时间 |
| Packet/Byte Count | 匹配的数据包和字节统计 |
常用流表动作:
| 动作 | 说明 | 示例 |
|---|---|---|
| OUTPUT | 从指定端口输出 | OUTPUT:2 |
| DROP | 丢弃报文 | DROP |
| SET_FIELD | 修改报文字段 | SET_FIELD:0x0800->eth_type |
| PUSH_VLAN | 推送VLAN标签 | PUSH_VLAN;SET_FIELD:100->vlan_vid |
| POP_VLAN | 弹出VLAN标签 | POP_VLAN |
| NORMAL | 传统交换机行为 | NORMAL |
3.2 OVS 与物理网络对接
OVS通过集成网桥(Integrated Bridge)与物理网络对接:

2.6 OVS 的 DPDK 加速
DPDK(Data Plane Development Kit)是OVS的软件加速方案:
| 模式 | 转发方式 | 性能 | CPU占用 |
|---|---|---|---|
| Kernel Mode | 内核网络栈 | 10-50万pps | 高 |
| DPDK Mode | 用户空间轮询 | 1000万+pps | 中(绑核) |
| HW Offload | 网卡硬件卸载 | 线速 | 极低 |
2.6 OVS 高级功能:QoS 与 镜像
端口级限速(QoS):
OVS支持在端口级别实施流量限速,适用于多租户环境中的带宽保障:
# 1. 创建QoS策略
ovs-vsctl -- --id=@qos create qos type=linux-htb other-config:max-rate=1000000000 \
-- --id=@port get port tap-vm1 \
-- set port tap-vm1 qos=@qos
# 2. 创建带权重的子带宽限制
ovs-vsctl -- --id=@qos create qos type=linux-htb other-config:max-rate=5000000000 \
-- --id=@band1 create band type=htb-direct-max other-config:max-rate=1000000000 other-config:priority=1 \
-- --id=@band2 create band type=htb-direct-max other-config:max-rate=2000000000 other-config:priority=2 \
-- set qos @qos bands=@band1,@band2
| QoS类型 | 说明 | 适用场景 |
|---|---|---|
| linux-htb | 基于HTB令牌桶的分级限速 | 多级带宽保障 |
| linux-hfsc | 基于HFSC的层次化调度 | 复杂调度策略 |
| simple | 简单限速 | 单速率限制 |
端口镜像(SPAN):
# 创建镜像端口
ovs-vsctl add-br br-mirror
ovs-vsctl add-port br-mirror mirror-port
# 配置镜像规则
ovs-vsctl -- --id=@m create mirror name=mirror1 \
select-all=true \
output-port=mirror-port \
-- set bridge br-int mirrors=@m
2.7 OVS 流表编程:高级匹配与动作
多字段组合匹配示例:
# 1. 基于VLAN+IP+端口的精确匹配
ovs-ofctl add-flow br-int \
"priority=100,vlan_tci=0x0100,nw_src=192.168.1.0/24,nw_dst=10.0.0.0/8,tp_dst=443,\
actions=output:3"
# 2. 并发洪泛动作(发送到多个端口)
ovs-ofctl add-flow br-int \
"priority=50,dl_type=0x0806,\
actions:flood"
# 3. 修改MAC地址后转发
ovs-ofctl add-flow br-int \
"priority=80,in_port=1,dl_src=aa:bb:cc:dd:ee:01,\
actions:set_field:11:22:33:44:55:66->dl_src,output:2"
# 4. 基于计数器的流表(用于流量统计)
ovs-ofctl add-flow br-int \
"priority=90,in_port=2,nw_proto=6,tp_dst=80,\
actions=counter,output:3"
| 高级动作 | 说明 | 典型应用 |
|---|---|---|
| RESUBMIT | 将报文重新提交到指定表 | 多级流表联动 |
| GOTO | 跳转到指定表继续匹配 | 模块化流表设计 |
| GROUP | 调用Group Table | 负载均衡/广播 |
| METER | 通过Meter Table限速 | 端口级限速 |
| SET_QUEUE | 设置输出队列 | QoS队列映射 |
2.8 OVS Group Table 实现负载均衡
Group Table是OVS实现高级转发的关键机制:
# 创建轮询(Group Type=select)
ovs-ofctl add-group br-int group_id=1,type=select, \
bucket=watch_port=2,output:2; \
bucket=watch_port=3,output:3
# 创建故障转移(Group Type=failover)
ovs-ofctl add-group br-int group_id=2,type=failover, \
bucket=watch_port=4,output:4; \
bucket=watch_port=5,output:5
# 流表引用Group
ovs-ofctl add-flow br-int "priority=100,nw_dst=10.0.0.1,\
actions group:1"
| Group类型 | 说明 | 应用场景 |
|---|---|---|
| Select | 从bucket中选择(支持权重/轮询) | 负载均衡 |
| Failover | 按优先级选择首个存活bucket | 主备切换 |
| Indirect | 所有bucket执行相同动作 | 广播/组播 |
| All | 发送到所有bucket | 泛洪 |
2.9 OVS 流表管理最佳实践
| 最佳实践 | 说明 | 原因 |
|---|---|---|
| 流表分层设计 | 使用多表(multiple tables)分工 | 避免单表过大,提升匹配效率 |
| 优先级规划 | 精确匹配高优先级,泛洪低优先级 | 确保关键流量优先处理 |
| 表ID规划 | 表0:ACL过滤→表10:VLAN→表20:路由→表30:输出 | 清晰的流水线模型 |
| 流表版本管理 | 使用ovs-ofctl dump-flows定期备份 | 故障恢复和审计 |
| 避免流表膨胀 | 限制流表数量(<10000条) | 防止内存溢出和匹配性能下降 |
| 使用Group替代重复规则 | 通过Group Table复用bucket | 减少流表项数量 |
四、实战配置/案例分析
4.1 OVS 基础配置
# 1. 安装OVS
yum install openvswitch
# 2. 创建网桥
ovs-vsctl add-br br-int
# 3. 添加VM的虚拟端口
ovs-vsctl add-port br-int tap-vm1
ovs-vsctl add-port br-int tap-vm2
# 4. 添加物理端口(集成网桥)
ovs-vsctl add-port br-int eth0
# 5. 查看网桥配置
ovs-vsctl show
# 6. 查看流表
ovs-ofctl dump-flows br-int
4.2 OVS VLAN 配置
# 1. 创建VLAN网桥
ovs-vsctl add-br br-vlan
# 2. 添加带VLAN标签的端口
ovs-vsctl add-port br-vlan tap-vm1 tag=100
ovs-vsctl add-port br-vlan tap-vm2 tag=100
ovs-vsctl add-port br-vlan tap-vm3 tag=200
# 3. 添加Trunk端口(连接物理网络)
ovs-vsctl add-port br-vlan eth0 tag=none
# tag=none表示Trunk模式, 允许所有VLAN通过
# 4. 验证VLAN隔离
ovs-ofctl dump-flows br-vlan
4.3 OVS VXLAN 配置
# 1. 创建VXLAN端口
ovs-vsctl add-br br-vxlan
ovs-vsctl add-port br-vxlan vxlan1 \
-- set interface vxlan1 type=vxlan \
options:remote_ip=10.255.2.1 \
options:key=10001
# 2. 创建内部网桥并添加VM端口
ovs-vsctl add-br br-int
ovs-vsctl add-port br-int tap-vm1
# 3. 使用Patch Port连接两个网桥
ovs-vsctl add-port br-int patch-vxlan \
-- set interface patch-vxlan type=patch options:peer=patch-int
ovs-vsctl add-port br-vxlan patch-int \
-- set interface patch-int type=patch options:peer=patch-vxlan
# 4. 在VXLAN网桥上配置流表(将VLAN映射到VNI)
ovs-ofctl add-flow br-vxlan \
"priority=1,in_port=patch-int,vlan_tci=0x0100,\
actions=set_field:10001->tun_id,output=vxlan1"
4.4 故障案例:OVS流表冲突导致VM通信中断
现象:某OpenStack环境中,两台VM无法通信,但同一网桥上的其他VM通信正常。
排查过程:
# 1. 检查OVS网桥状态
ovs-vsctl show
# 网桥和端口状态正常
# 2. 检查流表
ovs-ofctl dump-flows br-int
# 发现两条冲突的流表项:
# 表项1: priority=1, in_port=1, actions=output:2
# 表项2: priority=2, in_port=1, dl_src=aa:bb:cc:dd:ee:01, actions=drop
# 表项2优先级更高, 将VM1的流量全部丢弃
# 3. 检查流表来源
# 表项2是由安全组规则自动生成的, 但由于规则配置错误,
# 匹配条件过于宽泛, 拦截了所有VM1的出方向流量
根因:Neutron安全组规则翻译为OVS流表时,优先级配置错误。一条drop规则的优先级(2)高于正常的forward规则(1),导致VM的流量被错误丢弃。
解决:
1. 修正安全组规则,确保drop规则的优先级低于forward规则
2. 检查Neutron的OVS流表生成逻辑
3. 使用ovs-ofctl del-flows手动删除冲突流表项作为紧急恢复措施
五、总结
| OVS特性 | 说明 | 应用 |
|---|---|---|
| 软件转发 | 基于内核/用户空间 | 通用场景 |
| DPDK加速 | 用户空间轮询转发 | 高性能场景 |
| OpenFlow | 可编程流表 | SDN/网络虚拟化 |
| VLAN支持 | 802.1Q VLAN | 多租户隔离 |
| VXLAN支持 | Overlay隧道 | 跨主机二层扩展 |
| Patch Port | 网桥间互联 | 复杂网络拓扑 |
| Group Table | 高级转发(负载均衡/故障转移) | 服务高可用 |
| QoS | 端口级限速 | 带宽保障 |
| 端口镜像 | SPAN流量复制 | 故障排查/安全审计 |
| 运维命令 | 说明 |
|---|---|
| ovs-vsctl show | 查看网桥拓扑 |
| ovs-ofctl dump-flows | 查看流表 |
| ovs-appctl dpif/dump-flows | 查看datapath流表 |
| ovs-vsctl add-br | 创建网桥 |
| ovs-vsctl add-port | 添加端口 |
| ovs-ofctl add-group | 添加Group条目 |
| ovs-ofctl dump-groups | 查看Group表 |
思考
- OVS的软件转发性能远低于物理交换机(ASIC),什么场景下使用OVS仍然合理?
- OVS的DPDK模式需要将CPU核心绑定到DPDK线程,这会带来什么管理和调度上的挑战?
- OVS流表的优先级机制如何影响转发行为?如果两条流表的匹配条件有重叠但优先级不同,会发生什么?
- OVS的Group Table如何实现负载均衡?与ECMP在网络设备中的负载均衡有何异同?
- OVS的多表流水线模型(multi-table pipeline)相比单表设计有什么优势?
下篇预告:第272篇:OpenStack Neutron 网络:Provider 与 Self-Service