摘要:
弹性伸缩是NFV的核心承诺,但在实际应用中却很难实现。出现这种困难的原因是大多数网络函数(NFS)是有状态的,并且这种状态需要在NF实例之间共享。在满足NFS上的吞吐量和延迟要求的同时实现状态共享是有挑战性的,并且迄今为止,还没有解决NFV对于全频谱NFS的性能目标的解决方案。
S6是一个新框架,可以在不影响性能的情况下支持NF的弹性缩放。 它的设计基于这样的见解:分布式共享状态抽象非常适合NFV背景。 我们将状态组织为分布式共享对象(DSO)空间,并使用旨在满足NFV工作负载的弹性和高性能需求的技术扩展DSO概念。
S6简化了开发过程:NF编写器程序不了解状态的分布和共享方式。 相反,S6透明地迁移状态并处理对共享状态的访问。 在我们的评估中,与最新的NFs动态缩放解决方案相比,S6在缩放事件期间可将性能提高100倍,在正常操作下可将性能提高2-5倍。
背景/问题:
网络功能虚拟化(Network Function Virtualization,NFV)主张将称为网络功能的中间盒功能从专用硬件设备转移到在VM或共享服务器硬件上的容器中运行的软件应用程序,NFV愿景的一个重要好处是提供弹性伸缩——能够根据所提供的负载的变化,增加或减少当前专用于特定NF的虚拟机/容器的数量。然而,实现这种弹性伸缩已经被证明是具有挑战性的,而且迄今为止的解决方案在性能、功能和/或开发的易用性方面都付出了巨大的代价。
困难在于大多数NFS是有状态的,其状态可以非常频繁地被读取或更新(例如,每个包或每个流)。因此,弹性伸缩需要的不仅仅是简单地更新一个负载平衡器,将部分通信量发送给另一个VM/容器。扩展可能涉及跨NF实例迁移状态,迁移对于高性能很重要(因为它避免了远程状态访问),但是它的实现必须是快速的,并且不应该给NF开发人员带来负担。此外,弹性伸缩必须确保数据包与其状态之间的关联,并且即使在状态迁移时,也必须正确地实施这种关联。最后一个复杂的情况是,某些类型的状态是不可分割的,而是跨实例共享的,在这种情况下,弹性缩放必须以确保满足该状态的一致性要求的方式支持对共享状态的访问,并且对NF吞吐量和延迟的影响最小。
任何弹性伸缩解决方案的核心是如何组织状态并将其抽象为NF应用程序。最近的工作探讨了这方面的不同选择:一些假设所有的状态都是本地的,但既不是共享的,也不是迁移的,我们称之为仅本地的方法。其他则支持更丰富的模型,在这种模型中,NF开发人员可以将状态公开为本地或远程,开发人员可以将状态从远程迁移到本地存储,或者显式地访问远程状态——我们称之为本地+远程方法。还有一些假设所有状态都是远程的,存储在一个集中的存储中,我们称之为仅远程的方法。
以上是探索NF状态管理设计空间的开拓性努力,但是它们仍然没有一个理想的解决方案:
-
仅本地方法实现了高性能,但是它所支持的NF功能有限
-
本地+远程方法支持任意NF功能,但会使NF开发复杂化,并且在缩放事件期间会因整体重新分区状态而导致长时间的停机
-
仅远程方法很优雅,但即使在正常操作下也会带来高性能开销。
解决方法:
本文提出了一种将状态组织为分布式共享对象(DSO)空间的弹性伸缩方法:对象封装NF状态,并生活在全局命名空间中,所有NF实例都可以读/写任何对象。虽然DSO是一个古老的概念,但它还没有应用到NFV背景中。特别是,DSO还没有被证明满足NFV强加的弹性和性能要求。
我们提出了S6,一个针对NFV的开发和运行框架。
为了满足NFV工作负载的需要,S6扩展了DSO的概念:
-
对于空间弹性,我们引入了DSO密钥空间的动态重组
-
为了最小化与缩放事件相关的停机时间,我们引入了“聪明但懒惰”的状态重组
-
减少远程访问开销,我们引入了每包微线程
-
为了在不增加开发人员负担的情况下优化性能,我们公开了每对象提示,开发人员可以通过这些提示向DSO框架通知适当的迁移或缓存策略。
S6隐藏了分布式状态管理在引擎盖下的所有内部复杂性,简化了NF开发。
我们提出了在S6之上实现的三个弹性NFS:NAT、PRADS(网络监控系统)和SNORT ID的子集。
我们展示了s6上的NFS以最小的性能开销进行弹性扩展,并将它们与使用先前方法构建的NFS进行了比较:像E2这样的本地系统不能支持我们的两个用例(NAT和PRADS),因为它不支持共享状态。与基于本地+远程方法的最新框架OpenNF相比,S6在扩展事件期间实现了10x-100x的低延迟,同时保持了10x的高吞吐量。与无状态NF相比,S6是一个基于仅远程方法的最新框架,在正常操作下可以获得2-5倍的高吞吐量。
具体实现细节:
状态管理涉及到许多设计选项,例如在哪里放置状态和何时启动迁移,它们都会影响NF的整体性能,例如吞吐量和延迟。
下图显示了先前行业研究所假定的NFV体系结构的典型组成部分。
无论是仅本地状态模型、仅远程状态模型还是本地+远程模型都有其缺陷,无法达到一个比较好的效果。
于是我们提出了一种新的模型——分布式共享状态模型,这是分布式计算所熟悉的。在该模型中,状态在NF之间分布,并且可以由任何NF访问,但是本地状态与远程状态对NF开发人员而言没有区别,所有状态变量都位于共享的地址空间中,并且状态管理框架透明地解析所有状态访问。该框架还负责确定状态的放置位置,并在适当的情况下跨NF实例迁移状态。正确完成后,通过将状态迁移到与访问它的NF实例位于同一位置,该模型可以实现与仅本地模型相当的吞吐量和延迟,避免本地+远程方法所导致的长时间停顿。由于本地状态和远程状态之间没有区别,因此在扩展事件期间不需要主动迁移,数据包到达时,迁移的开销将逐步摊销。
例如,对于上述相同的PRADS方案,暂停时间可以降至1毫秒以下。出于同样的原因,状态迁移不再需要与流量负载平衡进行紧密协调,从而降低了与本地+远程模型关联的系统复杂性。最后,分布式共享状态模型简化了NF的开发,开发人员可以在用于状态访问(本地或远程)的统一界面之上编写NF,将状态查找,远程访问和向状态管理框架的迁移的基本细节外包。
S6与现有的NF状态管理解决方案不同,所有解决方案都需要在NFV控制器,SDN控制器和NF实例之间进行复杂的运行时协调,而S6与负载均衡器和SDN控制器的分离降低了系统的复杂性。
我们总结了主要的设计思想:
-
S6提供了所有NF实例共享的全局DSO,我们选择“对象”作为状态的基本单位,对象封装了一组数据及其关联的操作,从而允许访问控制和状态的完整性保护。无论对象实际位于何处,都可以使用统一的API访问该空间中的所有对象。
-
我们的对象抽象为NF开发人员提供了指定对象访问模式的旋钮, S6框架使用此信息通过减少远程状态访问的次数来提高性能。
-
当不可避免要进行远程状态访问时,S6通过隐藏微线程的延迟来降低其成本, NF工作器实例只有在不依赖于对远程对象的出色访问的数据依赖下,才能继续处理其他流。
- 在发生缩放事件时,S6重新组织空间,同时让工作人员处理流量,S6通过智能但延迟的对象及其元数据迁移来最大程度地减少服务中断。
S6编程模型表(下表)总结了S6的API。从用户的角度来看,S6的核心组件是共享对象空间和任务,根据对象是否允许从多个编写器(NF实例)进行更新。我们提供两种类型的对象—— SingleWriter允许从单个实例进行独占写入, MultiWriter允许同时从多个实例进行并发写入。可以对对象上的方法进行适当注释,以允许进行更多优化,例如缓存读取,更新后遗忘或定期将合并的本地更新推入对象所有者。然后,S6支持基于对象类型在后面进行适当的优化。
下图显示了PRADS 中使用的对象类的示例实现。
S6提供两种类型的任务:数据平面和控制平面。数据平面任务对输入网络流量执行数据包处理,控制平面任务执行带外操作,例如更新配置或处理用户查询,两种类型的任务都可以使用统一的接口访问共享对象空间。
S6实现包含三个主要组件:S6运行器,S6编译器和NFV控制器。
S6运行器:运行时,S6运行器扮演三个角色:首先,它管理跨节点分布的DSO空间,它跟踪对象的位置并控制来自多个实例的对象访问,以支持每种对象类型的互斥或并发访问。其次,它管理与S6兼容的对象引用以提供S6编程接口,S6运行时介导对对象的每次访问,并在需要时执行远程操作或启动对象迁移。第三,它为数据平面和控制平面任务调度微线程,每当微线程由于远程访问而将要阻塞时,运行时都会调度另一个未决的微线程,并继续处理数据包而不会阻塞。
S6编译器:我们使用BOOST协同例程库来实现非抢先的用户级多线程。 S6编译器虽然S6在源代码中需要自定义编程接口,但是没有方便的方法来扩展C ++语法,我们实现了一个源代码到源代码的编译器,该编译器将S6扩展的C ++代码转换为纯C ++,生成的代码抽象化了DSO实施的实现细节。例如,当调用方法时,生成的代码将检查状态对象是本地对象还是远程对象,以调用适当的函数。我们在Clang-3.6库的顶部实现了编译器,以对开发人员的代码进行语法分析。
NFV控制器:NFV控制器我们构建了一个简单的NFV控制器来管理S6实例,它通过启动S6实例来运行NF群集,并根据网络工作负载启动横向扩展事件。控制器还从操作员到NF实例中继带外任务,例如查询或更新配置。
讨论与思考:
超越对象的其他状态:
集合:许多NF应用程序都包含集合数据结构(例如,链表,树或哈希表),在S6中,可以构建诸如C ++ STL之类的对象引用的非侵入式容器之类的集合。
多对象事务:S6本机支持线性化-对单个对象的写入之间的排序,但不支持串行化——对多个对象的排序。为了支持多对象事务,NF开发人员可以使用可完全更新的对象来实现自定义锁,只允许单个实例引用该锁对象,其他实例需要等待,直到从先前的实例中释放引用。密钥所有者序列化对锁对象的访问。
容错:
Pico 和FTMB等现有系统已经解决了中间盒和网络功能的容错问题。这些系统保证,当NF在非横向扩展环境中发生故障时,新的NF会迅速恢复联机-并显示发生故障的NF的所有状态-并继续处理数据。最直接的补救措施是在每个节点基础上采用Pico(基于检查点的按状态快照)或FTMB(基于检查点和重播的VM快照)算法,两种系统都在数据包处理过程中介入对中间盒状态的访问。
容错的另一种方法是通过基于DHT的经典故障转移恢复功能来扩展S6的状态管理。密钥所有权(甚至数据本身)可以在多个DHT节点之间复制三次。因此,如果任何单个节点发生故障,集群的其余部分可以立即继续处理传入流,从而访问其余的复制状态。