首先,这片文章初衷是为了自我总结,我不会从感情上偏袒其中某个解决方案,但我确实有自己的Preference和对未来技术发展的看法。
从真正开始参与Neutron开发,已经有近2年的时间,起初的半年内(Icehouse周期里),无时无刻不在修复Neutron在生产环境中发现的各类Bug,其中有一些核心的问题处理比较费时,甚至至今也没有一个很好的解决方案。
众所周知,OpenStack所有的数据持久化(除了Ceilometer外),全部依赖官方推荐的MySQL(包括Percorna、MariaDB等),但是开源关系型数据库引擎的扩展性一直都是问题,从生产环境监控中可以很容易看到,Neutron对数据库的读写压力,在OpenStack所有组件中,仅次于Nova(Keystone可以通过内存数据库来缓解75%以上的压力)。其中主要是三个部分的原因,一方面数据库引擎单点或者HA都无能解决扩展性问题,当Neutron-server进程越来越多时,就会出现,虽然有Galera集群方案,但其事务处理性能一直都是瓶颈,而且乐观锁机制也会导致API失败(Nova有db-retry,Neutron在那个时候还没有)。第二个方面,是SQLAlchemy框架本身的限制,Python社区一直都是松耦合的纯开源社区,所以导致很多企业级应用所必须的框架,没有得到企业级的维护,其中首当其冲就是SQLAlchemy,这个Python世界里排行第一的ORM解决方案,并不是一个优秀的性能出众的ORM方案(至少和我在Java世界里使用的Hibernate,各方面都差了不止一截),记得其在0.90-0.99的每个版本都存在或多或少的Bug没有修复,而且它的ORM引擎对SQL本身的优化也不是特别到位。第三个方面是Neutron社区,一直以来都存在错用SQLAlchemy的情况,在事务处理过程中使用RPC引起不必要的事务内协程切换,间接增加无谓的数据库引擎长时间维护事务的压力,大规模环境下经常导致事务Timeout、Deadlock等情况。这些情况集中于ML2和L3RouterPlugin插件的DB模块,每个Release都有大量的Race Condition曝出,然后就是Case by Case去修复,虽然这种情况自从Icehouse曝出多达10-20个同样的问题后,慢慢随着Juno、Kilo已经修复了大多问题(本人也参与讨论和修复了其中的几个Bug),但是,由于初期设计失误导致的这种情况,在后期,却需要200%-300%的时间去分析和修复,让人汗颜。
Neutron的控制平面是基于RPC实现的,官方推荐基于AMQP0.9的RabbitMQ方案,但是大规模环境下,RabbitMQ集群的扩展性也成为了障碍,虽然存在Kernel调优和Ram Node-Disk Node的优化方案,但一方面RabbitMQ本身对于Devops是黑盒,其次官方的指南在当时并不清晰(后期官方也在不断完善Best Practice之类的文档)。为了处理当时的生产环境,切换到了基于ZeroMQ的分布式消息队列,在Neutron项目中替换了RabbitMQ的方案,确有奇效。
关于这个方案,在Vancouver峰会上我有一个演讲,详细描述了一个 新的分布式消息队列系统 。当前,社区除了官方推荐能在小规模Region稳定运行的RabbitMQ,oslo.messaging团队正在发展三个更有前途的希望能够稳定运行在大规模环境的RPC驱动,分别是ZeroMQ、Kafka、AMQP1.0(记得是基于Apache Qpid dispatch router实现的)。
Eventlet是OpenStack依赖的greenthread管理库,它的优点是开发模型简单,能有效重用iowait时的计算资源,缺点是缺少细粒度的调度控制。在OpenStack世界里,需要显式调度的时候,需要使用eventlet.sleep。
但是基于iowait的调度粒度太粗。某些情况下,我确实需要在iowait下禁止当前协程切换呢?还有些情况下,我需要基于优先级的调度呢?在某些特殊情况下,我需要抢占式调度呢?对于大型系统来说,开发模型简单易学,隐藏了大量细节,并不是好事。
在Neutron中,存在一个并不是特别起眼的模块,Scheduler,这个模块负责把Neutron core Resource和Agent进行绑定和解绑,也就是把资源调度到不同的Agent上去配置。这个Scheduler目前常用的是DHCP、L3、LB(负载均衡)。这个模块存在一个较大的缺陷,就是每个调度器都是独立运行,其中没有任何资源协调,导致在生产环境下,我即便是有针对性地实现了更细粒度调度算法,也无法使得不同的调度器间进行交互,实现更高层次的资源统一调度(比如,把一组资源统一调度到同一台Host,当前无法实现,在写DB时会出现Race Condition)。那个时候,我自己基于Redis开发了一个分布式锁管理器,在各个调度器之间实现了统一的调度控制。
Neutron目前还没有AgentGroup的概念,没有办法实现统一的集群管理和可靠的健康检查机制(RPC+DB,只能算Demo)。
基于以上两个问题,都是由于Neutron项目内不存在Cluster Coordination机制导致(虽然我实现了一个,但并不通用,当时还没有Tooz),这个机制目前已经有了一个BP(通过Tooz实现,但是只有我觉得可以+1,其他Reviewer并没有反馈),而且其实Nova社区也有了ServiceGroup的参考实现,但是Neutron社区方面却一直Delay,不知道是因为Core Team把握不准,还是觉得这个功能比较复杂,要放到M周期讨论。
Neutron中最常用的(User Survey调研占到75%的案例)是Openvswitch和Linuxbridge,其中的Agent框架都是基于Daemon-loop的轮询机制,这套机制在大规模生产环境下,基本不可用,因为一次轮询的时间太长,导致一些需要立即更新的端口配置延时到下一个轮询周期,对于任一端口配置错误都会导致full-sync,系统开销极大。另外,所有对于虚拟网络设备的配置都是通过Subprocess调用外部Command的方式,导致Host Kernel需要维护大量并发的Subprocess,带给Host Kernel很大的压力。幸好在Liberty周期里,已经有人在实现基于事件的Callback机制,并且我也联合另一个Neutron开发者向社区提出了使用Netlink Library Call代替Subprocess的技术方案,还在初期讨论过程中,但是从Icehouse到Liberty,确实够久的。
当然,除了处理Neutron的一系列事故外,我还在思考这么一个问题,就是Neutron的SDN方案,到底该如何发展?当前的情况是,不停地修Bug,平均一个BP的引入会同时带来10+的Bugs(话说回来,DVR的引入带来了30+的Bugs,给HP和Review BP的人狠狠点赞)?OpenStack提供了一个广阔的开放的平台,定义了业界认可的API集合,但是,就如同存储技术需要Domain Knowledge,网络技术同样需要,当前Neutron除了其Plugin框架之外的实现,更多是Reference Design,而不是大规模生产环境下的专用系统。
在这个时候,也有思考过SDN和OpenStack的关系。
这个问题不是我抛出的,而是去年就有很多云计算架构师和网络架构师,包括一些业界专家一起在QQ群里论战。其实这个问题,需要从两个角度去看。第一,从云计算技术的角度,Neutron实现了租户网络拓扑的自定义,确实是SDN思想的体现。第二,从网络技术的角度看,Neutron仅仅是实现了网络通路(保证网络是通的,汗),还没有针对流量的细粒度管控,职责也没有非常清晰地分离,与现实世界里大量专业的SDN系统所实现的网络功能相比,确实差了很远,所以要说Neutron是SDN的初级起步阶段也未尝不可,所有特别是很多业界的网络专家对Neutron的实现不屑一顾也情有可原。最新Neutron社区主导的项目,像Dragonflow、RouterVM、ML3,以及与外部SDN开源方案的互动更为频繁(OpenDayLight、OVN等),可以看出OpenStack也在朝好的方向努力。
有网络的地方,就可以有SDN发挥的余地,在我眼里,SDN技术所能应用的领域,囊括了整个CT领域,从范围上讲,包含卫星网、全球互联网、骨干网、城域网、园区网、最后100M接入网,局域网;从传输介质上讲,包含双绞线、光纤(单模、多模)、同轴电缆、无线通信(微波、Wifi、2/3/4/5G移动网)所形成的各类网络;当然还包括IT领域的DCN(数据中心网络)、DCI(数据中心互联),NFV领域,以及在未来DT领域会大力发展的物联网、传感器网络等等。
云计算网络(比如OpenStack Neutron)环境仅仅是SDN众多北向应用中的一个,不需要谈到SDN必谈云。离开了云,SDN技术还是可以在其它领域发亮发光,反倒离开了SDN,云就更加虚无缥缈了。
马力,海云捷迅(AWcloud)架构师,大规模云计算架构、数据中心架构、SDN、Opentack,Email: mali@awcloud.com