原文链接 http://www.51gocloud.com/?p=1885
原生openstack环境下创建虚拟机耗时较长,相比AWS发放时间(20s左右)还是有很大差距;本文围绕这一问题进行展开,针对各瓶颈点给出优化思路。
整体思路类似如何让汽车在路上跑的更快,首先要解决的问题是让单个汽车在路上跑的快,我们可以通过修公路来解决,尽可能让路平滑,没有坑坑洼洼,这样汽车在运行过程中可以一直处于高速运行状态;其次要解决多辆汽车并行的时候如何跑的快,我们可以通过加宽公路,多车道并行,并且最好路上没有红绿灯,最终形成一条高速公路。
1、修建一条平滑的公路,优化单个虚拟机创建时间
(1)基于存储内部快速复制能力,缩短镜像创建卷的时间
问题描述:单个虚拟机创建耗时长的点主要集中在镜像创建卷,在创建过程中,需要下载镜像,所以创建时间跟镜像大小以及网络带宽强相关
解决思路:可以基于存储内部快速复制卷的能力,解决系统卷创建慢的问题,有以下三种方式,
- 方式1:在cinder上对镜像卷进行缓存
openstack社区提供了缓存镜像卷的能力,核心思想,第一次创建卷的时候,在存储后端缓存对应的镜像卷,后续创建都是基于这个镜像卷复制一个新的卷。【社区相关链接】 方式2:glance后端对接cinder,镜像直接以卷的形式存在cinder上
这种方式,在镜像上传的过程中,直接以卷的形式存放,在从镜像创建的卷的过程中,直接走卷复制卷的能力。这种方式可以解决首次发放慢的问题。【社区相关链接】方式3:基于存储的链接克隆能力实现卷的快速创建
这一功能需要实现cinder volume中的clone_image方法,在这个方法里面,可以先缓存镜像快照,然后基于快照创建差分卷
(2)采用rootwrap daemon方式运行命令,缩短nova-compute/neutron等组件调用系统命令的时间
问题描述:rootwrap 主要用来做权限控制。在openstack中,非root用户想执行需要root权限相关的命令时,用rootwrap来控制。 启动虚拟机过程中,会多次调用系统命令;调用命令时,会经过rootwrap命令进行封装,这个命令在每次允许过程中,都会加载命令白名单(允许nova组件执行命令的列表配置文件),最终再调用实际命令运行,额外耗时100ms左右。
解决思路:通过rootwrap daemon机制来解决,启动一个rootwrap daemon专门接受执行命令的请求,节省每次加载白名单的时间
nova-compute对应的rootwrap配置项:【社区相关链接】
1 2 3 | [ DEFAULT ] use_rootwrap_daemon = True |
2、修建一条多车道高速公路,优化多虚拟机并发创建时间
在并发创建过程中,主要是去除红绿灯(数据库行级锁)解决锁抢占问题,以及修多条高速公路(调整各组件进程数)最终提升各组件的处理能力
(1)Qutoa无锁化优化,减少操作Quota时的耗时
问题描述:openstack在Quota处理过程中,采用了数据库行级锁来解决并发更新问题,但在并发场景下,这个锁会导致耗时增加
解决思路:由于在处理Quota过程中,先select在update,所以需要加锁(悲观锁)。针对这一点,可以通过带有where的update操作来实现更新,然后根据更新行数,判断是否更新成功(乐观锁)【社区相关链接】
(2)调整各组件进程数,提升组件处理能力
问题描述:在并发过程中,各组件处理能力不足(可以观察进程对应cpu使用率,如果已经到100%,说明处理能力不足),
解决思路:可以通过横向扩展组件或调整组件worker数来解决
(3)调整nova-compute并发创建任务上线,提升组件的并发能力
问题描述:nova-compute在并发创建虚拟机过程中,有并发任务限制(M版本默认值为10)
解决思路:增大并发任务个数上线,对应参数为max_concurrent_builds
(4)keystone采用PKI机制替换UUID方式,减少keystone压力
问题描述:openstack api server在处理请求前会校验token是否合法,如果采用UUID token,则每次都会去keystone做校验
解决思路:采用PKI方式,各api在本地通过证书来校验token是否合法
(5)适当增大各组件token失效列表的缓存时间,可以减少keystone的压力
问题描述:openstack api server在处理请求前会校验token是否合法,除了校验token是否过期,同时还校验token是否在token失效列表里面;这个token失效列表会在本地缓存,如果过期,则会去keystone重新获取,在并发的时候,keystone会成为瓶颈点
解决思路:适当增大各组件token失效列表的缓存时间revocation_cache_time