OpenStack nova私有代码维护–一种外挂方案思路




修改OpenStack开源代码的套路

小bug或者简单功能

直接在launchpad上提bug或改进任务,之后提交代码关联到launchpad即可。

针对比较大的功能特性的正常套路:

1. 邮件或IRC提出需求,并与项目TL或相关核心开发人员讨论需求的合理性、必要性、普适性等问题
2. 初步确认后,提出正式blueprint,等待相关开发review
3. bp合入后,即可开始代码编写、提交等待review
4. 反复修改后,代码合入上游分支,开发完成

上述流程是完美状态,很多时候需求不等人,走完开源社区的这套流程,估计半年一年都过去了,甚至你的代码都很少有人关注,最终不了了之,没了下文。。。

私有代码产生背景

还有一些公司,保留私有代码的想法看起来挺有道理,是为了保持竞争力,把一些功能做好之后不贡献社区,自己的产品就比别人多了这个功能,这种情况不予置评,个人感觉是这些公司的领导太看得起自己的产品经理或者开发人员了。如果是因为这个理由,个人建议还是全部自研比较合适,不要采用开源了。

时间紧迫是一个比较常见的困难,另外常见的就是需求的普适性问题,具体到某个使用OpenStack的公司很多需求都是针对内部场景的(其实不止OpenStack,其他开源项目也有相同困境),或者针对某个外部客户的具体项目的,很难推到OpenStack社区。

乱改代码的问题非常多,除非你不打算继续跟进开源社区的新版本,否则后患无穷。

开源项目定制代码的可维护性是个普遍问题,目前我还没听说哪家公司有完美的解决方案,可能是我眼界不够宽吧。

有些需求场景是可以通过组合OpenStack已有功能来达到相同或类似目的,需求的差异性很大,能找到替代方案的毕竟是少数,而且很多时候产品经理或者领导层是不懂(或者不能忍受)OpenStack或者其他开源项目的设计思想的,就想按自己或者所在公司的意愿进行强行纠正,但又没有开源社区话语权(话语权通常掌握在少数超大公司手中,具体来说就是项目TL、core reviewer或者core developer),只能把这种需求强加给内部开发人员,因为大家(不光产品,开发自己或多或少都有)都有一种在我看来比较诡异的想法,你们OpenStack或其他开源项目的开发,如果只是简单的拿开源项目代码来用,公司给你们开这么些工资,你们连一行代码都不想写,公司又不指望你们给开源社区做贡献,那养你们有何用?开发的想法是,我只看代码有卵用?等哪天在这家公司干不下去了出去找工作,简历都没得写,必须得干点啥才行,于是乱改一通,美其名曰二次定制开发,实则给公司带来了很大的麻烦。当然公司的一些领导是不关心这种问题的,反正需求搞定了就行,产品有·亮点·就行,管他之后怎么玩,代码怎么维护,这些问题都是开发考虑的,搞的不好肯定是那帮开发没能力或者偷懒,不是我决策失误,我又不懂开发,之前改不改都是你们开发自己决定的,我只是提了个需求而已,又不知道你们乱改代码才能实现,现在搞成这个局面也不是我想要的啊!你们自己看着办吧,烂摊子你们开发自己收拾去,反正我还要继续提需求,你们还得按时保质保量的完成,至于改不改代码怎么改代码怎么维护怎么升级都是你们的事,反正我又不懂代码,出了问题别找我就行。

上述场景多见于中大型公司,小型公司没钱没人搞这些定制化开发,超大型公司要么有开源话语权,要么不跟开源玩,自己搞一套系统出来,想怎么改怎么改。

有些开发比较diao(或者定制开发搞多了就变diao了,毕竟踩的坑多了,知道深浅了),看到公司这么瞎折腾就跑路了,去超大公司搞私有项目或者去专门刷社区贡献的公司了,反正有实力,不受这种气(当然主要还是超大公司有钱赚,还能跟着里面的大牛学经验,增加见识扩展眼界)。开发拍拍屁股走人,留下的烂摊子还得有人收拾,有些公司估计也是为了变相撵人,走的人都是工资高(有没有实力不好说),养不起了,你自己走了正合适(这是我瞎猜的,不惮以最坏的打算来推测)。

大部分采用开源项目的公司,维护私有代码都是作茧自缚的下场(注意:这里单指长期跟进开源情况,维护独立分支不跟进上游不算),加法做到最后,发现加不下去了,或者加法变成了乘法,积累了几年的私有代码,每次升级要花几倍几十倍的人力去merge上游,但上游代码已经物是人非,99%的代码不能直接merge,工作量不亚于再次二次开发,甚至比重新开发还累(当初的需求、某些实现细节,当初提出需求的人、开发代码的人都可能已经走人了)想要还原当时的想法和功能,更是难上加难。

不过还好,很多公司的项目都具有时效性,今天改了,明天可能就不用了,丢了就丢了,只要当初的项目到手就行,公司本质还是赚钱。另外一些持久使用的,就比较麻烦,演变一定时间之后,就会考虑重构或自研,这也是一种应对方案,招人重写就好了,反正有钱任性,自研是解决开源项目私有代码问题的终极方案,可惜不是一般公司玩得起的。

nova外挂方案

言归正传,我们作为小公司,没时间没人力专门搞社区贡献,私有代码多多少少又都有一点,我们本身是极力避免的,一般的bug修好肯定推到社区,但一些项目定制化需求,不得不做,毕竟赚钱生存是第一要务。

比如nova中,我们开发了云主机在线升配功能,可以不停机增加CPU数量、内存大小、磁盘空间,方便用户做垂直扩容操作,由于在线扩容kvm还属于不十分稳定的操作,使用限制比较大,另外受制于物理机资源,不一定每台云主机都能执行,因此社区没有做这类功能,但我们的产品为了增加亮点功能,做了这个功能,就需要维护私有代码。

我们本来也是直接改nova代码的,涉及到两部分,一个是正常的升配功能操作,从api到compute,中间涉及到配额使用量检查、修改,云主机规格修改,调用libvirt接口进行升配操作等;另一部分是在创建云主机时,要在xml中预先配置好maxCPU、maxMemory,预留好CPU和内存插槽,并在镜像中配置好udev规则,在升配后可以自动online相关硬件设备。

其中操作部分可以考虑开发外挂程序来替代直接修改nova代码,但有很多细节问题需要考虑,这里主要是提供一种思路,具体到自己的代码是否具备可操作性,需要自行斟酌。配置maxCPU、maxMemory那部分,目前还没想到合适的外挂方案。

外挂方案描述:

首先写一个agent,跑在计算节点上负责跟libvirt打交道(其实也可以利用libvirt的tcp远程调用功能把agent和WSGI api服务放在一起),通过MQ(建议)或者直接监听端口提供WSGI服务(不建议),然后写一个WSGI服务跑在控制节点上负责提供api接口,通过MQ跟agent交互,参考nova那一套流程,agent直接访问nova库,在需要执行数据库操作时,不通过nova直接进行修改(其实也可以考虑通过MQ调用nova-conductor进行DB操作,但是不能确定nova-conductor有没有实现私有代码需要的数据库修改接口,如果有的话,是可以考虑的,没有的话就又涉及到增加私有代码问题了,所以还是直接操作数据库比较简单粗暴有效果)。

具体到在线升配功能,其他操作都无所谓,检查配额使用量、检查计算节点资源剩余量(并发资源占用问题也需要考虑,但本身在线升配就不能保证100%成功,所以也就暂时无视了),需要写入db的操作就是增加用户配额使用量,修改云主机规格,配额使用量可能不准,可以通过定期同步的配置来优化,利用nova的两个配置项,until_refresh和max_age。

这个外挂的想法很简单粗暴,目的也很直接,省的以后升级nova需要merge代码(如果数据库表结构改了,可能需要修改外挂执行的sql语句)。存在的漏洞也很多,最难处理的就是并发物理资源申请问题,在不修改nova代码的情况下,很难解决,修改了nova代码又违背了我们开发外挂的初衷,只能根据实际情况折中处理。

这里仅仅是提供一种思路,能不能用还得自己考虑确定。