一个瞎掰掰的 OpenStack 调度算法

Written on July 19, 2014 View on GitHub

鉴于在团队中主要负责Nova相关二次开发工作,深受 OpenStack 调度器的折磨,主要以下吐槽。

1、flavor、instance_type 概念冗余。 2、extra_spec 设计,缺乏性能考虑。 3、weight 权重模型,看似容易扩展,实际像穿着盔甲跳舞。 4、状态同步依赖 compute 自助反馈,一是缺乏可靠性,甚至影响到了retry,二是难以升级。 5、看似通用可扩展的过滤器,获得的实际信息十分局限。

上面只是无责任吐槽,实际当然 OpenStack 这么做有其自己的原因,有的是为了跟EC2兼容,有的是为了降低复杂度,有的是历史原因。但不管怎么说,这东西影响了使用,于是我对 OpenStack 的调度器进行过几次改进。比如添加了hypervisor的识别,添加了虚拟机数量的限额,改进了baremetal的模式。这都是小改动,最近试了一个大改动,推翻了现有的weight机制。

Weight机制的核心观点,就是利用一个数值,来决定优先将虚拟机调度到哪台机器上。(既有可能是高到低排序,也有可能是低到高排序,分别实现了分散调度和集中调度) 目前实际的官方代码里,是使用剩余内存作为参数,说白了就是将内存排个序。 会有什么问题呢? 1、在实际部署环境里,难免出现compute故障,如果没有及时修复,故障的机器就一直在那。。。被调度,失败。。。一直。 2、如果有多种型号的机器做compute,那就回明显出现调度不均。实际情况机器是一批一批调度的,那么被部署的情况也是一批一批的。 3、每有个新客户出现,可能就会出现一批同类型机器。大客户的出现会导致不同COMPUTE上虚拟机数量差别甚远,数量多的,带来的网络压力和硬盘压力也会大。 当然你可以修改这个排序参考数值,如改成内存分配比,只要它有数值意义,但终归是个局限。

实验性改变一:压力控制

集中调度是防止碎片产生的不错办法,但是机器压力过高会影响性能,过低会资源浪费。 在整体思维结构不变的情况下,采用额外的阈值控制机制。 设定一个阈值,如75%,当某个机器压力达到75%的时候,则将其排序到队伍末尾。 如 70 60 80 70 90 60 ==> 90 80 70 70 60 60 ==> 70 70 60 60 90 80 当然这个百分比要控制合适,最好能塞下最大的实例,避免碎片。

实验性改变二:槽

于是我尝试做了一次改变,就是预先规划好虚拟机上能发出哪些类型的机器,多少个。然后再根据需要集中或分散调度。这种方式肯定有个专有名词,但是我读书少,不知道,所以我就管它叫槽。种种迹象表明,Amazon EC2使用的就是类似的调度方法。

存取槽信息

方案有很多种,可以是 compute_node 里添加一个字段用字符串记录槽配置和状态,也可以是单独一张表记录。也可以像floating_ip一样,预先吧所有数据生成一张表,每次只是表中取一行,分配一个instance。 第三种方式最理想,性能也最好,这里以第三种为例子,但是涉及到instance操作,我这边涉及到的更改并不全。 1、添加表 solt,字段包含id,instance_type,compute_node,instance. 并且将这个表填满。 2、compute_node 添加free_solts字段,记录剩余可用solt个数(用于调度器排序,可以不要)

调度过程(集中调度)

1、取出该类solt涉及的compute_nodes 2、compute_node 按照 free_solts 排序 3、按序调度compute_node

调度过程(随机调度)

1、取出该类所有空闲solt 2、利用随机值取一个solt 3、调度对应compute_node

注意

槽信息可以说与instance_type完全绑定了,那么filter的作用意义降低,没有特殊需求可以完全移除。如果发现必须用filter的地方,那就考虑有没有必要使用槽方式了。 solt表其实完全可以集成到instance表里,不过改动逻辑太多。