微信公众号发布的技术分享文章更多、更及时和全面。也请大家关注本人微信公众号。谢谢!
我们介绍Orion,一个分布式软件定义的网络平台,部署在谷歌的数据中心(Jupiter)和广域(B4)网络中。Orion是围绕一个模块化的微服务体系结构设计的,该体系结构具有一个集中(central)发布-订阅数据库,以实现一个分布式的、紧耦合的、软件定义的网络控制系统。Orion支持基于意图的管理和控制,具有高度的可扩展性,并符合全局控制层次结构。
多年来,Orion在以下方面不断提高性能:融合(速度提高40倍)、吞吐量(每秒处理116万次网络更新)、系统可扩展性(支持16倍更大的网络)和数据平面可用性(Jupiter和B4的不可用时间分别减少50倍、100倍)同时保持高开发速度,每两周发布一次。如今,Orion支持谷歌的软件定义网络,抵御大规模生产网络的通用故障模式以及SDN系统特有的故障模式。
在过去的十年中,软件定义网络(SDN)取得了巨大的进展,其动机是提供新的网络功能,从根本上提高网络可靠性,并提高网络演进的速度。SDN从一个简单但影响深远的方法开始:将网络控制(如路由和配置管理)从单个硬件转发元素转移到集中管理实时和静态网络状态的服务器池。这种向逻辑集中的网络状态视图的转变,使我们能够从定义具有紧急行为的成对协议到保证活跃性、安全性、规模和性能的分布式算法的深刻转变。
例如,SDN对网络状态的全局视图为更强大的网络验证和基于意图的网络提供了机会。在较高的层次上,SDN提供了将网络从一种一致状态转换到另一种一致状态的机会,在这种状态下,一致性可以定义为符合策略且无黑洞。同样的全局视图和实时控制使流量工程能够响应拓扑、维护事件、故障甚至细粒度通信模式,从而使整个网络能够更高效、更可靠地运行。目前正在进行将终端主机和结构网络连接在一起的工作,以确保单个流、RPC和协同流满足更高级别的应用程序要求,这是传统协议难以实现或不可能实现的能力。SDN最大的长期好处之一可能是支持软件工程和鉴定实践,以实现每周安全的软件升级和增量功能交付,这可以在很大程度上加快网络演进。
虽然SDN的前景是巨大的,但实现这一前景需要一个满足或超过现有网络性能和可用性级别的生产级控制平面。此外,SDN必须与对等传统网络无缝互通,因为没有任何网络(SDN或其他网络)仅在其自己的技术岛(tech island)上运行。
在本文中,我们描述了谷歌SDN控制平面Orion的设计和实现。Orion是我们的第二代控制平面,负责所有数据中心(Jupiter)、园区和专用广域网(B4)的配置、管理和实时控制。Orion已经生产四年多了。SDN从协议到算法的转变,以及基于微服务的控制器体系结构,使得每两周发布一次的软件版本不仅提供了30多个新的重要功能,而且还将规模提高了16倍,在Jupiter和B4中的可用性分别提高了50倍和100倍。,如果没有基于SDN的软件速度,这种快速发展将是困难的或不可能的。
Orion围绕一组独立的微服务(从路由到配置管理再到网络管理)进行设计,通过可扩展网络信息库(NIB, Network Information Base)协调所有状态。NIB通过键值抽象/abstraction对更新进行排序和复制。我们描述了NIB的性能、语义和可用性需求以及开发模型,该模型允许数十名工程师通过定义良好、简单但长期有效的合同API独立、同时开发、测试和部署他们的服务。
虽然Orion在谷歌取得了成功,但我们的设计和SDN方法都不是万能的。我们描述了Orion面临的四个关键挑战,其中一些是SDN的基础,另一些是由我们自己的设计选择以及解决这些问题的方法造成的:
#1:逻辑集中控制要求更新的基本高性能、状态的内存表示以及松散协调的微服务SDN应用程序之间的适当一致性级别。
#2:控制与硬件元件的解耦打破了命运共享,使corner案例故障处理更加复杂。特别是,控制软件故障并不总是意味着相应的硬件元件出现故障。考虑控制软件在单独的物理故障域中运行的情况,该物理故障域通过独立的带外控制网络连接。无论是物理基础设施(控制服务器、其电源或冷却)还是控制网络故障,现在都至少会导致数据平面中突然出现大规模相关故障。
#3:必须小心平衡集中化和故障隔离之间的紧张关系。在极端情况下,可以想象一个单一的逻辑控制器用于谷歌的所有网络基础设施。在另一个极端,我们可以为我们的网络中的每个物理交换机考虑单个控制器。虽然两个极端都可以相对容易地抛弃,但找到合适的中间立场是很重要的。一方面,集中化更易于推理、实现和优化。另一方面,集中式设计更难垂直扩展,并暴露出更大的故障域。
#4:在全球网络环境中,我们必须将现有路由协议(主要是BGP)集成到Orion中,以允许与非SDN对等网络的互操作。这些协议的语义,包括控制和数据平面之间的流式更新和命运共享,与我们选择的SDN语义不匹配,需要在多个级别上进行调整。
本文介绍了Orion的概况。我们将概述如何在其体系结构、实现和发展中管理这些关注点。我们还讨论了运行Orion的生产经验,指出了SDN发展过程中仍然存在的一些问题。我们将在以后的工作中分享更多的细节和经验。
Orion的设计借鉴了Onix的经验。与Onix采用协作多线程的单片设计不同,Orion引入了分布式设计,每个应用程序都在一个单独的进程中。虽然Onix引入了一个NIB,该NIB只能由同一进程中的应用程序访问,但Orion的NIB可以由域内和域间的应用程序访问,从而提供了一种层次结构机制,而现有的控制器很少采用这种机制(Kandoo是一个例外)。支持层次结构的fabric级排空顺序和基于WCMP的最优(加权成本多路径)路由。
我们将Orion的逻辑分布在多个进程上,以实现可伸缩性和容错性,这是与其他面向生产的控制器(如ONOS和OpenDaylight)一样的功能,最初由Hyperflow提出。与我们以前的设计不同,Orion对所有进程使用单一配置,通过NIB原子化应用,排除了由于预期状态不一致而导致的错误。
Orion使用类似数据库的表来集中组织SDN程序生成和使用的状态,这一特性与其他一些OpenFlow控制器(如ONOS、Flowlog和Ravel)一样。所有这些技术的结合——层次结构、分布和类似数据库的抽象——使Orion能够满足Google在数据中心和广域网中的可用性和性能要求。
虽然Orion是OpenFlow控制器开发的一个演进,但其网络功能的模块化分解(如路由、流编程、交换机级协议等)是与诸如4D/Tesseract和RCP等OpenFlow之前的系统一样的设计目标。同样采用微服务和集中式数据库体系结构的单交换机操作系统包括Arista EOS和SONiC。
接下来我们将介绍Orion设计的原则。我们在构建Orion的早期阶段建立了许多这样的网络,而我们从运营Orion网络的经验中获得了其他的网络。我们将这些原则分为三类:环境原则——适用于生产网络的原则、体系结构原则——与SDN相关的原则和实施原则——指导我们的软件设计的原则。
基于意图的网络管理和控制。基于意图的网络通过描述网络终端状态的意图(“what”)而不是规定使网络达到该终端状态的修改顺序(“how”),来指定管理或设计变更。基于意图的网络往往在规模上是健壮的,因为高层意图通常随时间而稳定,即使在网络元素的低级状态快速波动时也是如此。
例如,考虑一种情况,当我们同时添加新的网络链接以增加集群的入口和出口容量时,我们希望暂时“耗尽”(转移流量远离)集群流量。当这些新的链接出现时,稳定的排空意图也将适用于它们,导致底层网络控制系统避免使用它们。
在Orion中,我们使用基于意图的方法来更新网络设计、调用操作更改以及向SDN控制器添加新功能。例如,我们在模型中捕获网络拓扑的预期更改,这反过来触发部署系统和操作人员对网络进行必要的物理和配置更改。正如我们将在后面描述的,Orion通过配置和动态状态更改将这种顶级意图传播到网络控制应用程序中,例如路由。应用程序通过改变其内部状态和生成中间意图对顶级意图更改作出反应,而中间意图又被其他应用程序使用。整个系统状态通过意图的分层传播演变,最终导致网络交换机中编程流(programmed flow)状态的变化。
对齐控制平面和物理故障域。将控制软件与物理元件解耦的一个潜在挑战是未对齐或过大的故障域。对于未对齐,考虑单个SDN控制器跨两个建筑物的部分管理网络硬件的情况。该控制器中的故障可能会导致两个建筑物之间的相关故障,从而使满足更高级别的服务SLO变得更加困难。类似地,负责园区中所有网络元素的单个SDN控制器的故障将构成过大的漏洞,即使它由于集中视图而提高了效率。
我们通过小心地将网络控制域与物理、存储和计算域对齐来解决这些挑战。举一个简单的例子,网络控制中的单个故障不应影响多个物理、存储或计算域。为了限制单个控制器故障的“爆炸半径”,我们利用分层、分区控制,软状态在层次结构上向上推进/progressing up。我们明确地设计和测试网络,以便在控制器出现故障时继续正确(尽管可能降级)操作。
SDN提供了处理故障的新方法,但也带来了需要仔细设计的新挑战。SDN控制器远离网络交换机,导致缺少命运共享,但也可能无法与交换机通信。
缺乏命运分享往往对我们有利。例如,当控制器发生故障时,网络根据其现有状态继续转发。相反,当单个交换机发生故障时,控制器可以通过在其周围重新布线,准确及时地修复路径。
对相关的不可达性做出乐观的反应。由于控制器必须处理不完整的信息,控制器和交换机之间的通信中断构成了一个困难的设计挑战。我们处理不完整信息的方法是,首先决定我们是在处理小故障还是大故障,然后对前者作出悲观反应,对后者作出乐观反应。
我们首先将三元健康状态与网络元素相关联:(i)健康,与最近的控制通信(交换机报告没有数据包丢失的健康链路和编程状态),(ii)不健康,当交换机声明自己不健康时,当相邻交换机报告不健康状况或间接信号暗示交换机不健康时,以及(iii)未知,最近没有与交换机进行控制通信,也没有间接信号暗示交换机不健康。
处于未知状态的交换机可能出现故障,或者根本无法与控制器通信(在大规模情况下,这种情况相当常见)。相比之下,不健康状态相当罕见,因为几乎没有机会实时诊断明确的故障状况。
控制器将单个交换机状态聚合为网络范围的健康状态,并使用该状态来决定悲观或乐观反应。我们分别称之为Fail-Closed/故障关闭和Fail-Static/故障静态。在故障关闭状态下,控制器重新编程流,以围绕(感知到的)故障交换机进行路由。在Fail Static(故障静态)中,控制器决定不对处于未知、潜在故障状态的交换机做出反应,保持流量流向交换机,直到交换机状态发生变化或网络运营商进行干预。图1显示了正常运行、故障关闭反应和故障静态条件的示例。
在Fail Static中,控制器会阻止做出反应,以避免在连接和拥塞方面恶化网络的整体状态。故障关闭和故障静态之间的权衡取决于对未知状态作出反应的成本/收益:如果可以避免处于未知状态的元件,而不会产生显著的性能成本,控制器保守地对此状态作出反应,并触发协调行动,以引导流量远离可能的故障。如果该反应将导致容量的显著损失或端到端连接的损失,则控制器将为该交换机进入故障静态模式。在实践中,我们使用一个简单的“容量退化阈值”从故障关闭转移到故障静态。实际阈值与以下因素直接相关:(1)网络的运行参数,特别是我们通常保留的容量余量(capacity headroom),例如,用于支持计划维护;(2) 我们在拓扑和控制域中设计的冗余级别。我们的目标是保留一定数量的冗余,即使在容量下降的情况下。
根据我们的经验,静态故障的发生是相当常见的,而且几乎总是适当的,因为它们与数据平面性能的损失无关。通常,静态故障由SDN控制器和网络元件之间的控制平面连接故障或控制器中的软件故障触发。这两者都不会直接影响数据平面的运行状况。
我们认为,与传统的分布式协议系统相比,SDN系统具有故障静态的能力优势。分布式系统也会发生一些故障,这些故障可能会从故障静态响应中获益。但是,它们不容易实现静态失败行为,因为它们只有局部视图。当集中式控制器可以在其整个域中观察到相关网络故障时,它更容易评估是否应该进入Fail Static。
利用带外和带内控制平面连接。在软件定义的网络中,一个关键考虑因素是“off box”控制器和数据平面交换机之间的连接。我们必须解决引导(bootstrap)问题,即需要一个正常运行的网络来建立基线控制。选项包括:i)正在控制的网络(“带内”)或ii)单独的“带外”网络(物理或逻辑)。虽然这是一个看似简单的问题,但有关纯开箱即用SDN控件、控件与数据平面网络之间的循环依赖关系、易调试性、可用性、可管理性和拥有成本的考虑因素使该主题异常复杂。
最简单的方法是拥有一个物理上独立的带外控制/管理平面网络(CPN),用于与数据平面网络正交的控制器和交换机之间的通信。这种方法干净地避免了循环依赖关系,保持了控制模型的简单性,并且能够轻松地从错误和错误配置中恢复。理想情况下,我们希望带外控制网络具有高可用性、易于管理和维护以及成本效益。最后,单独的CPN意味着安装和运行两个不同的网络,具有不同的运行模式和独立的故障特征。虽然故障独立性通常是一个理想的特性,但微妙或罕见的故障场景意味着,如果数据平面或控制平面出现故障,整个数据平面可能会崩溃。我们在第5节中描述了我们对Orion混合CPN的选择。
实现大规模软件开发环境是构建我们自己的SDN控制器的关键动机。SDN成功的关键是能够通过频繁的软件发布在网络上安全地增量部署新功能。这反过来意味着一个庞大的工程师团队必须能够同时开发多个独立的功能。扩展工程过程的需要导致了具有大量解耦组件的模块化系统。同时,这些组件必须相互交互,以实现紧密耦合的控制系统,反映网络控制的结构和动态。我们通过以下方式实现了这一目标:
• 具有独立进程的微服务体系结构,而不是我们在第一代SDN控制器中采用的单片模块,用于软件可进化性和故障隔离。
• 一个中央发布子系统(NIB),用于微服务之间的所有通信,负责跨流程的紧密耦合交互。
失效域控制对控制域的大小施加了上限。然而,我们关心的是单个NIB的性能、可伸缩性和故障模型,以协调控制域内的所有通信和状态。我们通过基准测试工作满足了我们的性能问题,并通过限制控制域范围和静态失效能力(包括控制域之间)满足了容错问题。
基于多年的经验,NIB已经成为我们最成功的设计元素之一。它管理所有组件间的通信,允许我们创建“单一时间箭头”,在进程间的其他并发事件之间建立顺序。这带来了非常有用的副效应,包括大大提高了整个系统的可调试性。它还允许我们在外部系统中存储事件序列(NIB跟踪),并将其用于离线故障排除和子系统的独立验证,我们在组件级回归测试中使用这些子系统。
接下来,我们将讨论第3.1节中介绍的基于意图的控制原则、状态协调以及基于SDN系统中各种故障模式的含义:
意图自上而下。作为一个整体,系统的顶层意图是操作者意图和静态配置。当意图通过NIB消息在系统中传播时,它会触发子系统中的局部反应,从而生成其他子系统可以使用的中间意图。更高级别的意图是权威性的,任何中间意图(也称为派生状态)都是从中重建的。编程交换机状态是与编程到数据平面设备中的意图相对应的基本事实(ground truth)。
权威意图必须始终反映在基本事实中。控制器确保通过以对现有数据平面通信中断最小的方式将基本事实真相迁移到预期状态来纠正任何不匹配。我们将这一进程称为“状态协调/state reconciliation”。
协调最好在具有全局视图的控制器中执行,因为最小的中断通常需要交换机之间的协调,以便以优雅且无循环的方式对更改进行排序。协调是一个强大的概念,它允许对复杂的故障模式进行推理,例如Orion进程重启以及数据和控制平面之间缺乏命运共享。
高级意图的可用性对于保持自上而下的基于意图的系统简单至关重要。为了实现这一目标,我们尽量减少意图暂时不可用的时间(例如,由于进程重启或组件之间的通信故障)。
图2描述了Orion的高级架构,以及它如何映射到ONF视图。为了实现可扩展性和故障隔离,我们将网络划分为多个域,其中每个域都是Orion SDN控制器的一个实例。
数据平面由底部的SDN交换机组成。Orion使用OpenFlow作为数据平面接口控件(CDPI,Control to Data Plane Interface)。每个交换机都运行一个OpenFlow代理(OFA),用于对转发表、统计数据收集和事件通知进行编程控制。控制平面由中心的Orion核心和顶部的SDN应用组成。控制平面在物理上与数据平面分离,在逻辑上集中,提供了域的全局视图。尽管在逻辑上是集中式的,Orion Core通过分布式控制器进程控制网络。NIB为这些应用程序提供统一的SDN北向接口,以共享状态和通信需求。Orion Core负责(i)将这些需求转换为OpenFlow原语,以协调交换机的编程状态与预期状态;(ii)向应用程序提供网络运行时状态的视图(转发规则、统计信息、数据平面事件)。
NIB存储所有Orion应用程序的意向。它被实现为一个集中的内存中(in-memory)数据存储,具有副本,可以在发生故障时从基本真相重建状态。NIB与发布-订阅机制相结合,在Orion应用程序之间共享状态。外部使用相同的基础结构来收集NIB中的所有更改,以便于进行debugging。NIB必须满足以下要求:
• 对外依存度低/Low External Dependency。由于Orion为支持所有高级计算和存储服务的网络编程,它本身不能依赖于高级服务。
• 事件排序的顺序一致性/Sequential Consistency of Event Ordering。为了简化应用程序之间的协调,所有应用程序必须以相同的顺序查看事件(时间箭头)——也即是说所有应用程序看到的事件的顺序应该相同。
值得注意的是,持续性/durability不是NIB的要求,因为在发生灾难性故障时,可以从网络交换机和其他来源重建NIB的状态。
NIB实体。NIB由一组NIB实体表组成,其中每个实体描述了域本地或外部的其他应用程序或观察者感兴趣的一些信息。某些实体类型包括:
• 配置的网络拓扑。它们捕获各种网络拓扑元素之间的配置标识和图形关系。示例包括端口、链接、接口和节点表。
• 网络运行时状态。这可能是拓扑状态、转发状态(例如ProgrammedFlow表)、协议状态(例如LLDPPeerPort表)、统计信息(例如PortStatistics表).
• Orion应用程序配置。每个应用程序的配置被捕获为一个或多个NIB表,例如LLDPConfig。
协议缓冲区模式。我们将每个NIB实体的模式表示为协议缓冲区消息。该NIB实体表中的每一行都是该模式的实例。每个实体模式的第一个字段必须是作为该实体的key的NIBHeader消息。NIB不强制key的引用完整性;但是,不一致性无法通过内部健康检查。
一个示例实体是NIB中表示的链接实体。链接分别被建模为对端口和节点实体的外部key引用。这表示两个交换机的两个端口之间的连接。此外,状态(up、down或unknown)作为链接实体的一部分进行建模。完整的协议缓冲区如附录所示。
协议缓冲区允许我们为模式迁移重用理解良好的模式。例如,尽管某些应用程序仍然使用以前的模式运行,但在升级过程中向表中添加新字段具有内置的向后和向前兼容性支持。
NIB API。NIB提供了一个简单的RPC API(读、写、订阅)来操作NIB表。写操作是原子操作,支持批处理。Subscribe操作支持基本筛选以表示感兴趣的实体。NIB通知模型提供事件顺序的连续一致性。出于规模和效率的考虑,它还支持将多个更新合并到单个通知中。
Config Manager提供一个外部管理API来配置Orion域中的所有组件。域配置是在该域中运行的应用程序配置集。为了统一和易于共享,应用程序配置由一个或多个NIB表组成。为了确保新配置有效,首先由正在运行的实例对其进行验证。推送配置的语义需要是原子的,即,如果整体配置的一个或多个部分未通过验证,则整体配置推送必须在没有任何副作用的情况下失败。由于验证配置的各个部分的Orion应用程序是解耦运行的,因此我们采用两阶段提交协议来更新NIB:配置首先在shadow NIB表中暂存,每个应用程序验证其配置。成功后,我们将shadow表原子化地提交给活动表。
拓扑管理器设置并报告网络数据平面拓扑(节点、端口、链路、接口等)的运行时状态。它从NIB中的配置中学习所需的拓扑。通过订阅来自交换机的事件,它将当前拓扑写入NIB中的表。拓扑管理器还定期从交换机查询端口统计信息。
Flow Manager执行流状态协调,确保交换机中的转发状态与Orion应用程序计算并反映在NIB中的预期状态匹配。当意图改变时或通过比较交换机状态每30秒进行一次调节。后者主要为Orion提供交换机统计信息,并在意图更改协调失败的罕见情况下纠正不同步状态。
OFE(Openflow前端)将连接多路复用到Orion域中的每个交换机。OpenFlow协议为(i)功能发布,(ii)转发操作,(iii)数据包IO,(iv)测量/统计,以及(v)数据平面事件通知(如链路断开)提供编程API。它们通过OFE的北向RPC接口暴露于拓扑和流管理器组件。
数据包I/O。Orion支持通过OpenFlow的Packet-I/O API向数据平面发送或从数据平面接收控制消息的应用程序:Packet Out消息通过交换机上的给定端口发送数据包,而Packet-In 通知将交换机发送的数据平面数据包发送到控制平面。通知包括元数据,如数据包的入口端口。Orion应用程序可以编程punt流,并指定过滤器来接收感兴趣的数据包。
Orion核心应用在设计上与网络类型无关。没有“policy”被灌输到他们身上;它属于更高级别的SDN应用程序。核心应用程序以通用方式编程并忠实地反映NIB中数据平面的状态。
路由引擎(RE)是Orion的域内路由控制器应用程序,提供常见的路由机制,如L3多路径转发、负载平衡、封装等。
RE向客户端路由应用程序(例如域间路由应用程序或BGP Speaker应用程序)提供抽象拓扑和可达性信息。它将Orion域内配置的交换机集合建模为一个抽象路由节点,称为超级节点或中间块。客户端路由应用程序以超节点粒度提供路由通告,以聚合或单个外部端口的形式为每个路由指定nexthop。
将来自其客户端的路由通告重新分解为各个外部端口上的单个节点级可达性,并为每个前缀计算SPF(最短路径优先)路径。RE避免了通过耗尽的、向下的或可能出错的链路的路径。当当前前缀的下一个路径集变得不可访问时,它还通过计算下一个可用的最短路径来应对本地故障。为了提高容量,根据客户端应用程序的请求,通过跨多条可行路径分配流量,并通过非最短路径转发,在域内重新执行负载平衡。在其客户端路由应用程序中重新管理相关的交换机硬件资源(例如:3层路由表)。
Orion路由引擎的一个关键亮点是能够从当前编程的路径解决方案到新的路径解决方案进行无损失排序(loss-free sequencing)。这可能是对网络状态变化的反应(例如,避免连接)。在传统网络中,来自分布式路由协议(如BGP)的更新的最终一致性可能会导致数据平面中出现瞬态循环和黑洞。相反,RE利用其全局视图进行顺序流编程(sequence flow programming):在编程将流量导向一组交换机的流之前,RE确保已在这些nexthop交换机上编程了相应的前缀。在移除流之前进行类似检查。
图3展示了一个端到端路由编程示例。从操作顺序可以明显看出,NIB语义适用于异步基于意图的编程模型(与严格的请求-响应交互相反)。一种常见的设计模式是使用一对NIB表,其中一个表表示生产者的意图,而另一个表捕获消费者的结果。意向表和结果表都有版本控制。应用程序可以在不等待结果的情况下多次更改意图,并且结果表会异步更新。
Orion应用程序框架是每个Orion应用程序的基础。该框架确保开发人员使用相同的模式来编写应用程序,从而了解一个SDN应用程序的控制流程转换为所有应用程序。此外,该框架还提供了所有部署中所有应用程序所需的基本功能(例如,领导人选举/leader-election、NIB连接、运行状况监视)。
高可用性。可用性是网络和SDN控制器的一项基本功能。Orion应用程序作为独立的二进制文件运行,分布在网络控制服务器机器上。这确保应用程序与其他应用程序中的错误(例如,导致崩溃的内存损坏)隔离。
除了隔离之外,在三台不同的物理机器上复制每个应用程序可确保计划内(如维护)和计划外(如停电)停机的容错能力。应用程序框架通过在领导人选举以及生命周期回调的基础上提供抽象/abstraction来促进复制。
应用程序经历一个生命周期,即被激活、从NIB接收意图/状态更新,然后被停用。识别/仲裁副本之间的领导地位及其转换(称为故障转移)是抽象的,因此对应用程序作者来说是隐藏的,从而减少了bug的数量和复杂性。
功能准备协议。我们之前面临的挑战之一是在控制器故障切换后有序恢复操作。特别是,当控制器的NIB出现故障时,新NIB的状态需要与网络的运行时状态以及所有应用程序和远程控制器的功能状态保持一致。在极端情况下,Orion要求能够在不损失流量的情况下,从控制平面的完全丢包/重启中恢复。为了支持这一点,Orion体系结构提供了一个能力准备协议。使用此协议,应用程序可以统一指定恢复操作所需的数据,以及为其他应用程序提供的数据。
功能是NIB状态的抽象,每个功能都可以由多个应用程序提供和使用。基于功能的协调可以防止Orion应用程序变得“耦合/coupled”,其中一个应用程序的特定实现依赖于另一个应用程序的实现细节或部署配置。这种依赖关系是迭代和发布速度的问题。例如,多个应用程序可以提供“向程序生成流”的功能,流管理器可以不知道域中存在哪些应用程序。
功能准备协议要求,在NIB故障切换后,所有应用程序在Flow Manager开始协调NIB状态与物理交换机之前报告其流的就绪情况。这可防止交换机无意中擦除流状态,从而导致流量丢失。如图4所示,每个应用程序指定的所需和提供的数据创建了所依赖和提供的功能的有向无环图,因此,在任何重新启动后,完整的NIB状态都会保持一致。应用程序可以相互依赖于不同的功能,只要它们不形成循环。一个健康的Orion域在协调时快速完成完整功能图,这是我们在测试中检查并在生产中发出警报的条件。因为这个图是静态的,所以这样的测试可以防止引入依赖的循环。
如果状态完全丢失,Config Manager将从Chubby检索静态拓扑,Chubby是一种用于加锁(locking)和小文件存储的外部高可用服务。然后,它提供了一个CONFIG_SYNC(配置同步)功能来解锁拓扑管理器和流管理器。这两个连接到配置和读取交换机状态和编程流中指定的交换机。然后,ARP和路由引擎可以被解锁,以生成需要编程的预期流;它们还向Flow Manager提供自己的 FLOWS_DESIRED功能,Flow Manager继续对交换机进行编程。
从远程服务检索其状态的应用程序必须明确管理和支持服务不可用或断开连接的情况,以防止延长域协调延迟。通常使用缓存数据,直到可以访问输入的权威源。
在实现Orion以控制特定网络的众多设计选择中,有三个突出的选择,包括将网络元素映射到控制器、控制器切换通信的方法以及与运行标准路由协议的外部网络的连接。我们首先回顾了两个Google网络架构(Jupiter和B4)中的这些常见选择,然后描述了每个架构的具体细节。在网络环境中不太相关,NIB实现的详细信息见文章附录。
控制域。在Orion域中选择要控制的元素涉及多种权衡。更大的域可以产生最佳的流量分布和无损失的路由排序,以实现更多的意图变化,但代价是任何故障都会增加爆炸半径。在Jupiter中,我们使用分区Orion域的层次结构;在B4中,与非Orion全局服务通信的Orion域的平面分区。每一个都带来了生产上的挑战。
控制通道。如第3.1节所述,在设计将Orion控制器连接到数据平面的控制平面网络(CPN)时,我们面临着权衡。第二个网络的成本和复杂性使我们采用了混合设计,其中只有机架顶部(ToR)交换机在带内(in-band)进行控制。
• 控制面和数据面分离:当我们着手建造B4和Jupiter时,我们以最纯粹的形式接受了SDN理念:基于转发设备外部网络状态的逻辑集中视图的软件定义的网络控制。为此,我们没有在交换机上运行任何路由协议。对于控制平面,我们运行一个单独的物理网络,连接到交换机的管理端口。我们在CPN上运行传统的onbox分布式路由协议。与数据平面网络相比,CPN的带宽要求更小,尽管它需要N+1冗余。
•CPN规模和成本:典型的基于Clos的数据中心网络在汇聚层中没有超额订阅,ToR上行链路的超额订阅基于机架中计算和存储的带宽要求。在其N个阶段中的每个阶段使用相同交换机构建的Clos网络,除两个阶段外,所有阶段中的交换机数量(例如,K)都相同。由于所有端口都连接到前一级,因此最顶层级将有K/2交换机。ToR阶段将有S*K交换机,其中S是上行链路与下行链路相比的平均超额预订。因此,ToR交换机的数量占总交换机数量的比例为2S/(2S+2N-3). 在N=5个阶段的Clos网络中,平均ToR超额订阅率为2~4,ToR交换机占总数的36%至53%。因此,不需要连接到它们的CPN大大降低了CPN的规模和成本。
•CPN电缆管理:管理TOR带内电缆可以减轻将单个CPN电缆部署到数据中心每个机架点的负担。
•带内TOR的软件复杂性:由于TOR是Clos拓扑中的leaf交换机,因此其带内管理不需要机箱内路由协议。我们在交换机堆栈中设计了简单的带内管理逻辑,以通过ToR上行链路设置到控制器的返回路径,ToR的CPU最后一次从该上行链路听到控制器的信息。
•可用性和可调试性考虑:多年来,我们强化了CPN和带内控制的ToR,以提高可用性。“Fail static/故障静态”是减少CPN失效漏洞的关键设计。此外,我们还引入了连接到CPN的设备的带内备份控制,以增强鲁棒性。
外部连接。我们在数据中心网络的边界使用BGP与谷歌的广域网交换路由:B2(也连接到互联网)和B4。这些路由包括计算机地址以及谷歌服务的单播和任播IP(anycast IP)。BGP属性,如团体(community)、度量(metrics)和AS路径,在整个谷歌网络中传播状态。除了可达性之外,还可以包括WCMP的排空状态(drain state)、IPv6就绪状态和带宽。
BGP的使用是最终向互联网传播路由的必要条件,但在内部是一种设计选择。这种选择是为了简化与传统的非SDN路由器以及以前的SDN软件的互连。在定义策略以指定拓扑更改期间的路径首选项时,BGP还使操作员更加熟悉。
Orion应用程序Raven将BGP和IS-IS集成到Orion中。Raven通过Orion的数据包I/O与对等方交换消息。Raven将这些与来自NIB的本地路更新由合并到标准BGP RIB(路由信息库)中。然后,根据策略,通过传统最佳路径选择选择的路由将作为BGP消息以及本地NIB以RouteAdvert更新的形式发送给对等Speaker。为了降低复杂性,Raven的相关BGP“路由器”是RE提供的抽象超级节点(第4.2节)。
不幸的是,BGP与我们的设计原则有些不匹配:它使用流式更新而不是完全意图更新,它的局部视图排除了基于阈值的故障静态策略和局部故障期间的全局重新平衡,并且它将控制平面活动性与数据平面活动性联系起来。在我们的生产经验中,我们遇到了两种不相关的故障,与非SDN网络中一样,这两种故障变得相互关联,并且仅由于BGP而导致重大停机。相比之下,ORION的故障静态策略明确地认为控制平面和数据平面故障是独立的。向这些邻接添加故障静态行为是一个正在开发的领域。
我们最初开发了Jupiter,谷歌的数据中心网络,以及第一代基于SDN的控制系统Onix。这里介绍的基于Orion的解决方案是基于Onix部署经验教训的第二次迭代。
Jupiter数据中心网络由三种构建块组成,每个构建块内部由形成Clos网络拓扑的交换机组成:(i)连接到一组主机的聚合块(aggregation blocks),(ii)连接到WAN/园区网的FBR(fabric边界路由器,也称为集群边界路由器),和(iii)连接聚合块和FBR的spien块。
如图5所示,我们为Jupiter分层组织Orion域。首先,我们将Orion物理域映射到Jupiter构建块。每个物理域程序在该域内切换。聚合块域在连接到它的主机之间建立连接。FBR域使用Raven与结构外部对等方保持BGP会话。多个spine块可以映射到单个Orion域,但每个域必须包含少于25%的所有spine块,以限制域失败的爆炸半径。
第二级Orion域承载一个分区集中路由控制器IBR-C(块间路由中心)。IBR-C在路由引擎的抽象拓扑上运行,跨物理域聚合网络状态,计算结构范围内的路由,并对物理域编程以建立结构范围内的可达性。虽然这些虚拟域的基础相同,但它们不包含一些用于直接控制设备的Orion核心应用程序。
为了避免单点故障,我们将IBR-C划分(或分割)为四个称为“颜色”的平面,每个平面控制25%的spine块,从而控制每对spine块和聚合块/FBR之间四分之一的路径。因此,单个控制器的爆炸半径不超过结构容量的25%。切分集中式控制器可避免单个配置或软件升级影响整个结构的故障。在阶段配置更改和升级中添加了额外的保护,以避免跨颜色同步更新。虽然分片提供了更高的故障恢复能力,但折衷的办法是在聚合块和FBR域中跨颜色合并路由更新的复杂性增加,以及在跨颜色不对称故障的情况下路由优化的损失。我们考虑了通过将聚合块拆分为单独的域来进行更深入的分片,每个域控制一部分交换机。由于更高的复杂性,此选项被拒绝,同时略微提高了可用性。
图6显示了一种IBR-C颜色的fabric级别控制流程。IBR-C订阅所有聚合块/FBR域和相同颜色的spine域中的NIB以进行状态更新。在Change Manager进行聚合后,解算器/Solver计算块间路由,Operation Sequencer将下一个预期路由状态写入相应域的NIB表中。IBR-D(块间路由域)是一个域级组件,它将来自不同IBR-C颜色的路由合并到RouteAdvert更新中。最后,路由引擎和Orion核心程序流程如图3所示。
收敛性。我们关心Jupiter上的两种收敛:数据平面收敛和控制平面收敛。数据平面收敛确保所有源/目标对之间存在有效路径(无黑洞),而控制平面收敛恢复fabric中(near)最优路径和权重。需要更改网络的工作流使用控制平面会聚作为可以安全进行的信号。收敛时间是触发事件与数据/控制平面中完成的所有工作之间的持续时间。
Jupiter对链路/节点故障的反应有三方面。首先,在检测到链路层中断时,与故障实体相邻的交换机对输出组执行本地端口修剪。但是,如果不存在替代端口或无法检测到对等故障(例如,交换机内存损坏),则这是不可能的。其次,重新编程域以避免此实体。这类似于交换机端口修剪,但可能发生在域内的非相邻交换机上。对于不影响块间路由的故障,反应链到此结束。否则,在第三步中,重新通知IBR-C故障,如图6所示。当fabric范围的编程完成时,IBR-C发出控制平面已收敛的信号。这种多层反应有利于操作,因为它最大限度地减少了数据平面收敛时间,从而减少了流量损失。
由于单个实体故障可能导致不同域中的连续事件(例如,spine交换机故障导致聚合块链路故障),因此可能触发多个IBR-C和域编程迭代以达到最终收敛。许多独立事件也同时发生,并被Orion一起处理,这会进一步延迟收敛。
实施方面的挑战。最初的Jupiter实现面临的一个挑战是在多条路径上优化流量分配。由于链路故障和拓扑不对称(例如,spine聚合块对之间的链路计数不同),路径间的容量可能不同。为了优化流量分配,Jupiter/Orion采用WCMP来改变每条路径和下一条路径的权重。由于每个转发条目都有精确的权重计算,因此需要在整个fabric中调整权重以完全平衡流量。另一个挑战是路线变化期间的瞬时环路或黑洞。这是由于传统路由协议和我们以前的SDN控制器中的异步流编程。使用基于Orion的Jupiter,我们在IBR-C和RE中实现了端到端流程排序。
在Jupiter的尺度上,网络事件到达IBR-C的频率很高,有时超过其处理速度。为了避免队列累积,IBR-C将处理某些导致丢包的事件(例如,链路断开)优先于非关键事件(例如,排空)。在发生大量事件时,IBR-C仅在发生丢包诱发事件时抢占管道。在完成更高优先级的处理后,它会对其他事件重新排序/排队以进行批处理。这是一个折衷方案,可以最大限度地减少流量损失,同时避免低优先级事件的匮乏。
Onix,B4的第一代SDN控制器,使用协作多线程运行控制应用程序。Onix有一个紧密耦合的体系结构,其中控制应用程序共享命运和一个公共线程池。有了Onix的架构,满足B4的可用性和规模需求变得越来越具有挑战性;在五年的时间里,两者都增长了100倍。Orion通过分布式体系结构解决了B4的可用性和规模问题,在该体系结构中,B4的控制逻辑通过单独的流程解耦为微服务。
图7显示了B4控制体系结构的概述。每个Orion域管理一个B4超级节点,这是一个2级折叠Clos网络,其中较低级别的交换机面向外部。在B4中,路由引擎使用链路聚合组(LAG)将入口流量发送到上一级中的所有可行交换机,并使用两层WCMP对下一个超级节点的流量进行负载平衡。
TE App是B4的流量工程代理。它与全局TE服务器实例建立会话以同步隧道转发状态。它从主TE服务器学习TE隧道操作,并通过RouteAvert表对操作进行编程。此外,TE App还支持快速重路由(FRR),通过临时将流量重新引导到备份隧道集或BGP/ISIS路由,恢复断开隧道的连接。
路径导出器(Path Exporter)订阅多个NIB表,并将观察到的数据平面状态导出到全局服务。它报告超节点级别的数据平面状态,包括抽象拓扑(例如,超节点-超节点链路容量)、抽象转发表(TE隧道和BGP路由)和抽象端口统计信息。
中央TE服务器(Central TE Server)是一个全局流量工程服务,它使用TE应用程序在每个域中提供的TE协议优化的B4路径。带宽执行器(Bandwidth Enforcer)是谷歌的全球带宽分配服务,通过主机速率限制在竞争服务之间提供带宽隔离。对于可伸缩性,中央TE服务器和带宽实施器都使用路径导出器提供的抽象网络状态。
本文介绍了Orion,谷歌Jupiter数据中心和B4广域网的SDN控制平面。Orion将控制与单个硬件元素解耦,从而实现从通过缓慢演进的协议进行的成对协调到具有全局结构状态逻辑集中视图的高性能分布式系统的过渡。我们强调Orion在可用性、功能速度和规模方面的优势,同时解决SDN的挑战,包括调整故障域、与现有网络的互操作以及控制与数据平面中的解耦故障。
虽然Orion在生产上已经经历了4年的考验,但我们仍然有一些有待解决的问题作为未来的工作。
其中包括(i)评估机箱内和机箱外控制之间的划分,(ii)使用P4Runtime API标准化控制到数据平面接口,(iii)探索使NIB持久化,(iv)调查BGP中的故障静态特性,以及(v)试验细粒度应用程序发布。
更多精彩内容,请关注微信公众号"网络技术风云汇"。
相关标签: