6. 又一个大坑:SDN App Store
自从苹果的App Store深入人心以来,App Store成为了一个空前泛滥的概念。各个行业都在做平台做store。在这样的大背景下,一个自然而然的联想就是:既然SDN控制器是网络基础设施的操作系统,那么我们就把SDN控制器的北向API开放,做一个SDN的App Store吧!这样,工程师们可以在开放的平台上编写各种应用,共同打造开放的网络基础设施平台。
这确实是一个非常诱人的构想。不少企业都已经朝着这个方向付出了巨大的努力,比如HP。各大高校和研究机构也在积极的进行科研。甚至在世界各地都有和SDN应用相关的开发比赛。不过很遗憾,时至今日,我们连那个设想中SDN App Store的影子都没有看到。博主也曾经凭借一腔热血在这条路上狂奔了近一年,得到的只是一些血淋淋的教训。每次想到那些逝去的时光,都感慨不已。曾经一度,博主把问题的根源归结为不完善的系统设计导致开发和测试后期积重难返,但回味越久,就越觉得:SDN App Store根本就是一件极其艰难任务。在这片文章里,博主试图梳理一下那些血淋淋的教训,欢迎大拿们鄙视和嘲笑。
挑战1: 定义南向北向API
要了解定义南向接口的难度,大家只要看看OpenFlow几个版本之间的差异就够了,比较OpenFlow 1.0和1.4,那根本就是两个完全不同的协议嘛。即便如此,Cisco觉者OpenFlow抽象不够,于是有了ACI和OpFlex。微软和facebook觉着OpenFlow和现有的ASIC及协议栈不够兼容,于是有了Switch Abstraction Interface和BGP for Datacenter。虽然各个巨头之间存在利益博弈,但博主仍然对各个协议之间巨大的差异表示惊讶。照目前的情形看,南向接口标准化几乎是不可能的事情。与其旷日持久的争论那种接口更好,不如认定一种南向接口,发动一切可以发动的力量,一条道走到黑。毕竟我们的目的不是发明一种最好的协议,而是用集中控制的方式管理网络。
为各种应用定义干净,全面的北向API,在博主看来是一件同样艰难的事情。有人会把SDN控制器的北向API和linux的glibc做类比,但现实是这两件事情完全没有办法类比。计算机操作系统本质上并没有对计算机资源进行任何的抽象:CPU还是CPU(甚至有几个核都明明白白的告诉你,以便于编写并行程序),内存还是内存,硬盘还是硬盘。但是SDN控制器的北向接口却需要一定程度的抽象: 在不同的应用场景中,tenant,network,router,switch,port,interface的概念都有不小的差异。博主在Floodlight上参与开发过两款比较复杂的商业应用,最初的构想是由Floodlight提供统一的北向接口,由两款应用共享。但伴随着客户对几代产品的反馈,需求越来越清晰,我们发现两款应用需要的压根就是完全不同的北向API,需要非常不同的抽象。于是在某段时间内,我们为两款应用维持了两个完全不同的Floodlight stack。两个Floodlight的再次融合还是后来的事情,那是另外一个有趣的故事。
如果说定义南向API的困难在于巨头之间的博弈,定义北向API的困难在于对应用场景缺乏深入的理解,那么这第一个挑战也许随着行业的成熟还有解。下一个挑战却真的让博主无所适从,只想撞墙。
挑战2: 协调各个App的行为
在这里,我们首先看看如何协调一个App的行为:比如网络当中同时发生了两件事:一个link down事件,一个VM刚刚起来向外发送了第一个ARP,这个ARP引起了一个packet-in事件。如果这两个事件同时到达SDN控制器,SDN控制器需要如何处理呢?
最简单的办法是给这两个事件强加一个顺序。比如packet-in在先,link down在后。这样,控制器就会首先通过packet-in学习到那个新的VM,并且把和这个VM相关的表项都在交换机中编写好(参见Proactive vs. Reactive)。之后再处理link down这个事件,即将所有需要那条link的traffic都移走,这其中就可能包括那些在处理packet-in时刚刚编辑好的表项。
如果强加的顺序是link down在先,packet-in在后,控制器就会首先把经过那条link的traffic都移走,之后再处理packet-in。这里需要注意的是:在处理packet-in的时候,那条断掉的link已经不在网络拓扑当中了,于是所有与这个packet-in相关的表项都不会用到那条link。看来,只要给网络事件维持一个顺序,这个SDN控制器的行为还是正确的。
但是,网络事件那么多,并发性那么强,用单线程来串行的处理这些事件还了得?于是multi-threading/processing开始了,这是一个潘多拉魔盒。还是拿上面的例子说事儿:两个网络事件同时发生,分别由两个线程处理,如果两个线程没有信息交流,那么处理的结果很可能是:处理link down事件的线程把使用那条link的流都移走了,处理packet-in的线程却认为那条link还在,于是使用了那条link去编辑了流表。这显然是错大了。不少开源的控制器以及基于这些开源控制器的应用都使用了类似这个例子中的多线程模型,但线程之间的信息共享又处理的比较粗糙,导致一旦有并发的网络事件,系统便陷入瘫痪。
以上这个玩具一般的例子只想传达一个信息:正确处理并发的网络事件是SDN系统设计中最大的挑战之一。但是这其实只是一个老问题:Inter-Process Communication嘛,有好多相当成熟的方案可以借鉴。天才的网络工程狮们都是分布式系统的专家,不会被这种问题难倒。真正的问题不是来自于协调一个App的行为,而是协调多个并行App的行为。
我们来集体脑补一下一个场景:张三部署了高大上的多租户SDN数据中心,并且开放了SDN App Store和北向API。大家便开始纷纷贡献自己的App。李四的App在监听link down事件,相应的决策是移走traffic。王五的App也在监听link down事件,相应的决策是重启交换机。除非两个App没有共享任何资源,否则SDN控制器该听谁的呢?在这件事上,微软Azure走在了前面,他们的statesman系统在App和SDN控制器之间引入了一个仲裁系统,这个仲裁系统的主要作用就是“resolve conflicts and merge accepted modifications”。
但问题还远远没有解决。这个仲裁系统是Azure内部的解决方案,每一个新应用的出现,他们都需要对仲裁系统进行修改,比如为不同应用的不同决策配置优先级,甚至需要重写解决冲突的部分逻辑。这件事在Azure能够做到的原因有二:1) 所有的应用都是Azure自己部署的,2) Azure有强大的研发团队,每一个新应用的上线,他们都有能力对这个仲裁系统进行高度定制。但这两个前提在绝大多数机构是不存在。市场需要的是一个通用的解决方案。
现在所有的开源SDN控制器都会提供一些应用作为例子,每个应用单独跑起来也许没问题。但很少有人在讨论哪怕仅仅把两个需要共享资源的应用放在一起跑该如何协调。这件事才是SDN App Store的基础。博主在这件事情上努力过,没有任何有价值的经验值得分享,得到的教训反倒是:在目前这个阶段,与其去尝试解决这个问题,不如把所有需要共享资源的feature都放在一个App里面,设计一套干净的Inter-Process Communication机制处理并发的网络事件。
也就是因为以上的两个挑战,让博主认为SDN App Store是一个无比巨大的坑,慎跳,慎跳。