2、OVS架构解析:OVS的组件与数据平面控制平面分离

好,咱们进入第二章。这一章我打算聊聊OVS的内部架构。说白了,就是看看OVS这个“黑盒子”里到底装了些什么东西,它们各自干什么活。

很多初学者一上来就敲命令,结果出了问题根本不知道从哪查起。我个人习惯是,先搞懂架构,再动手操作。这样遇到问题,你心里就有谱了。

2.1 OVS的核心组件

OVS不是一个大一统的二进制文件。它由好几个独立的守护进程和工具组成。我画个简单的图给你看:

+-------------------+      +-------------------+
|   ovs-vswitchd    |      |   ovsdb-server    |
|   (核心转发引擎)   |      |   (配置数据库)     |
+--------+----------+      +--------+----------+
         |                          |
         |   +------------------+   |
         +---|   ovs-vsctl      |---+
             |   (命令行配置)    |
             +------------------+
         +------------------+
         |   ovs-ofctl      |
         |   (OpenFlow控制)  |
         +------------------+
         +------------------+
         |   ovs-appctl     |
         |   (运行时调试)    |
         +------------------+

嗯,这里要注意,这些组件之间通过Unix Socket或者网络通信。它们各司其职,互不干扰。

2.1.1 ovs-vswitchd —— 真正的“交换机”

这是OVS的灵魂。它负责实际的数据包转发。你配置的流表、端口、隧道,最终都由它来执行。

它的核心职责:

  • 数据包处理:从物理网卡或虚拟端口收包,查流表,执行动作(转发、丢弃、修改等)。
  • 流表管理:维护OpenFlow流表,处理流表匹配和动作执行。
  • 端口管理:管理所有连接到交换机的端口(物理端口、虚拟端口、隧道端口)。
  • 状态监控:监控端口状态、链路状态,并上报给ovsdb-server。
我的经验: 有一次线上环境丢包严重,我排查了半天,最后发现是ovs-vswitchd进程的CPU占用率过高。原因是流表太大,匹配效率下降。从那以后,我养成了定期检查ovs-vswitchd性能的习惯。

2.1.2 ovsdb-server —— 配置的“数据库”

这个组件负责存储OVS的所有配置信息。比如你创建了多少个Bridge、每个Bridge有哪些Port、Port的配置参数等等。它使用OVSDB协议,本质上是一个轻量级的数据库。

它的核心职责:

  • 配置持久化:所有配置都保存在一个文件中(默认是/etc/openvswitch/conf.db)。重启后配置不丢失。
  • 配置同步:当ovs-vswitchd启动时,它会从ovsdb-server读取配置。当配置变更时,ovsdb-server会通知ovs-vswitchd。
  • 多客户端支持:多个ovs-vsctl实例可以同时连接,它负责处理并发。
注意: 千万不要手动修改conf.db文件!我曾经见过有人直接编辑数据库文件,结果导致OVS启动失败。所有配置变更都应该通过ovs-vsctl或ovsdb-client来完成。

2.1.3 ovs-vsctl —— 你的“遥控器”

这是你日常使用最多的工具。它负责与ovsdb-server通信,执行配置操作。比如创建Bridge、添加Port、设置VLAN等。

常用命令示例:

# 创建一个名为br0的Bridge
ovs-vsctl add-br br0

# 添加一个物理端口eth0到br0
ovs-vsctl add-port br0 eth0

# 查看所有Bridge
ovs-vsctl list-br

# 查看br0的详细信息
ovs-vsctl show

说白了,ovs-vsctl就是OVS的“配置入口”。你敲的每一条命令,最终都会变成对ovsdb-server的数据库操作。

2.1.4 ovs-ofctl —— OpenFlow的“控制器”

这个工具直接与ovs-vswitchd通信,用来管理OpenFlow流表。它不经过ovsdb-server,所以它操作的是运行时状态,不是持久化配置。

常用命令示例:

# 查看br0上的所有流表
ovs-ofctl dump-flows br0

# 添加一条流表:匹配源MAC,转发到端口1
ovs-ofctl add-flow br0 "dl_src=00:11:22:33:44:55,actions=output:1"

# 查看端口统计信息
ovs-ofctl dump-ports br0
关键区别: ovs-vsctl管理的是“配置”,ovs-ofctl管理的是“转发规则”。配置是持久的,转发规则是运行时的。重启ovs-vswitchd后,通过ovs-ofctl添加的流表会丢失,但通过ovs-vsctl配置的Bridge和Port还在。

2.1.5 ovs-appctl —— 调试的“瑞士军刀”

这个工具用于与ovs-vswitchd进程进行运行时交互。它可以查看内部状态、触发调试动作、修改运行时参数等。我个人觉得,这是排查疑难杂症时最强大的工具。

常用命令示例:

# 查看ovs-vswitchd的版本和运行时间
ovs-appctl version

# 查看所有连接的控制器
ovs-appctl list-conn

# 查看内存使用情况
ovs-appctl memory/show

# 触发一次流表重新计算(调试用)
ovs-appctl revalidator/purge
避坑指南: 我曾经在排查一个诡异的丢包问题时,用ovs-appctl ofproto/trace命令模拟了一个数据包在流表中的处理路径。结果发现是一条优先级错误的流表把包给丢了。没有这个工具,我可能得花一整天去翻日志。

2.2 数据平面与控制平面分离

这是OVS架构的核心思想。你想想看,传统的硬件交换机,控制平面和数据平面是集成在一起的。但OVS把它们分开了。

数据平面:负责实际的数据包转发。在OVS中,这就是ovs-vswitchd干的事。它只关心“收到一个包,该怎么做”。

控制平面:负责决策和配置。比如“这个端口应该属于哪个Bridge”、“这个流表应该怎么配”。在OVS中,控制平面由ovsdb-server和外部控制器(如OpenFlow控制器)共同完成。

为什么要分离?原因很简单:

  • 灵活性:你可以用不同的控制器来控制同一个交换机。比如用Ryu做SDN实验,用OVN做生产环境。
  • 可扩展性:数据平面可以专注于转发性能,控制平面可以专注于策略管理。两者互不干扰。
  • 故障隔离:如果控制平面挂了,数据平面还能继续转发(基于已有的流表)。这在生产环境中至关重要。
举个例子: 假设你有一个OVS Bridge,上面跑了100条流表。这时候你重启了ovsdb-server。你会发现,数据转发完全不受影响!因为ovs-vswitchd已经加载了流表,它不需要实时依赖ovsdb-server。这就是分离的好处。

嗯,这里要注意,分离不是绝对的。ovs-vswitchd和ovsdb-server之间还是有通信的。比如端口状态变化时,ovs-vswitchd会通知ovsdb-server更新数据库。但核心的转发逻辑,是完全独立的。

2.3 组件之间的协作流程

咱们用一个实际场景来串一下这些组件是怎么配合的:

  1. 配置阶段:你敲ovs-vsctl add-br br0。ovs-vsctl连接ovsdb-server,在数据库中创建一条记录。
  2. 通知阶段:ovsdb-server检测到配置变更,通知ovs-vswitchd:“嘿,有个新的Bridge要创建”。
  3. 执行阶段:ovs-vswitchd收到通知,在内核中创建对应的Bridge设备,并开始监听端口。
  4. 转发阶段:数据包到达,ovs-vswitchd查流表(如果有OpenFlow控制器,还会向控制器请求流表),执行转发。
  5. 调试阶段:如果出问题了,你用ovs-appctl查看内部状态,或者用ovs-ofctl查看流表。

整个过程,数据平面(ovs-vswitchd)只负责转发,控制平面(ovsdb-server + ovs-vsctl)只负责配置。各干各的,互不越界。

一个常见的误解: 很多人以为ovs-vsctl和ovs-ofctl是等价的。其实不是。ovs-vsctl改的是“配置”,重启后还在。ovs-ofctl改的是“运行时流表”,重启后丢失。我见过有人用ovs-ofctl配端口,结果重启后端口没了,一脸懵。

好了,这一章就到这里。下一章咱们会深入Bridge的创建和管理,到时候会用到今天讲的这些组件知识。你先把这些概念理清楚,后面操作起来就顺手多了。