DPDK based Open vSwitch热升级设计与实现

 

 
系统级服务的无扰动升级(non distruptive upgrade , 下文简称为热升级)对服务的快速迭代开发有非常重要的意义 。虚拟交换机(vSwitch)作为虚拟网络的入口 , 需求多变 , 但频繁升级断网会影响虚机上运行的业务 。此外 , 一般每台宿主机上只有一个虚拟交换机 , 在架构上也不好做主备 。因此热升级技术对 vSwitch 的快速迭代至关重要 。
 
本文介绍了我们在 DPDK based Open vSwtich(下简称 ovs-dpdk)上的热更新技术的实践 , 希望和业界同行共同探讨 。
现状
  1. Open vSwitch(下简称 ovs)已有的“热升级”方案基本是为 ovs-kernel 而实现的 。在 ovs-kernel 中 , vswitchd 进程是慢路径 , kernel 模块是快速路径 。升级 vswitchd 进程时可不替换 kernel 模块 , 让大部分流量经过 kernel 中 flow cache 转发 , 减少网络扰动 。升级 kernel 模块则可能会有较长的断网风险 。这块的详细信息可以参考链接: http://docs.openvswitch.org/en/latest/intro/install/general/?highlight=hot%20upgrade#hot-upgrading
  2. ovs-dpdk 中 , 快速路径和慢速路径都集成在 vswitchd 进程中 , 如果简单的重启 vswtichd , 由于 DPDK 的初始化(主要是大页初始化 , 1G 大页耗时约 600ms)、网卡的初始化(实测 Mellanox CX5 驱动初始化耗时接近 1s)都比较耗时 , 因此会有秒级断网 。
  3. 为了实现快速的迭代开发 , 降低升级导致的断网带来的业务扰动 , 需要开发 ovs-dpdk 的热升级特性 。
方案与折衷实现热更新有很多实现方式:
  • 插件式升级(形象的说就是热补丁):将主要的包处理逻辑变成动态链接库 , 通过热加载插件的方式 , 避免耗时的 dpdk 初始化和网卡初始化 。(DPDK 主从模式也可被认为是这种方式的变体)
优点:常规升级断网时间非常小 , 可以做到纳秒级 。
缺点:框架升级和插件升级成为了两种升级 , 框架和插件之间必然有相互调用的 API 和共享 数据结构 , 开发人员需要保持框架和插件之间的 ABI(Application Binary Interface)一致 。一个简单的例子是流表的结构体可能会在框架和插件之间共享 , 如 果升级修改了流表的结构体 , 框架也需要升级 , 否则会因为不一致而导致内存错误 。
  • 双进程升级(形象的说就是热替换):通过硬件资源冗余 , 让新老 ovs 在升级中并存 , 老的 ovs 继续进行转发 , 使得流量不会断 , 新的 ovs 完成初始化之后 , 接管流量 。
优点:新旧 ovs 是两个进程 , 不需要做任何兼容 , 只需要遵守新旧进程之间的信息同步的通 信协议即可 。
缺点:需要资源冗余 , 需要网卡和内存冗余以同时满足新旧 ovs 的升级需求(2x 内存加 2x VF) , 断网时间也会更长一些 。
业界一般采用双进程实现热升级 , 这种方式的覆盖面更广 , 工程实现上相对来说也更容易一些 。下图描述了双进程热升级的一般流程 。
DPDK based Open vSwitch热升级设计与实现

文章插图
 
OVS 热更新的工作原理并不复杂 , 就是实现上需要考虑不少琐碎的工程细节 。主要通过代码上精细的控制使得升级断网时间较小 。
二段式设计我们把热升级的整个流程分成两个阶段(二段式) , 这里的设计有点借鉴虚拟机进行热迁移的过程 。在第一阶段 , 网络的转发服务不会停止 , 并且一旦升级出现故障 , 整个系统是可以自动回滚的 。只有到达第二阶段 , 网络会出现断网 。在第二阶段 , 如果出现问题 , 只能断网重启服务 , 系统不再具有回滚能力 。在实现上 , 我们给 ovs 开启了一个 JSON-RPC 服务用于热升级 。当 ovs 进程启动时 , 会自动检测是否有老进程的存在 。如果存在 , 则主动通过 JSON-RPC 发起热升级请求 。接收到热升级请求的 ovs 进程则开启两阶段升级:
  • 第一阶段:
  1. 老 ovs 进程释放各种独占资源:比如 ovsdb 的数据库锁 , pid 文件改名 , unixctl server path 等资源 。此时老 ovs 不能通过 ovsdb 获取最新配置 , 但是 PMD 线程依旧运行 , 转发并未停止 。


    推荐阅读