您的位置:首页 > 运维架构

Nova Scheduler 调度过程简述

2013-11-06 13:03 363 查看
      《Nova创建虚拟机实例过程简述》文章中,讲述了创建虚拟机实例的一个整体过程,现在,我们要开始着重分析和研究compute-api将请求发送到Scheduler后,Scheduler是如何实现初始调度工作的。

关于Scheduler的作用资料很多,我下面就引用下大神的一段话(

“Nova-Scheduler主要完成虚拟机实例的调度分配任务,创建虚拟机时,虚拟机该调度到哪台物理机上,迁移时若没有指定主机,也需要经过scheduler。资源调度是云平台中的一个很关键问题,如何做到资源的有效分配,如何满足不同情况的分配方式,这些都需要nova-scheduler来掌控,并且能够很方便的扩展更多的调度方法,可能我需要虚拟机调度到空闲的机器,可能还需要将某类型的虚拟机调度到固定的机架等等”

下面让我们来看一看具体的调度过程。

(一)Scheduler启动相关分析

         (1)compute-api通过一层层调用,最后调用/nova/compute/manager.py的run_instance(),如下图:

#启动虚拟机
def run_instance(self, context, request_spec, admin_password,
injected_files, requested_networks, is_first_time,
filter_properties, legacy_bdm_in_spec=True):
"""Tries to call schedule_run_instance on the driver.

Sets instance vm_state to ERROR on exceptions
"""
instance_uuids = request_spec['instance_uuids']
"""Compute-related Utilities and helpers."""
#compute_utils = utils
#EventReoprt()是一个类
with compute_utils.EventReporter(context, conductor_api.LocalAPI(),
'schedule', *instance_uuids):
try:

#调用driver(filter_scheduler.py)中的schedule_run_instance()
return self.driver.schedule_run_instance(context,
request_spec, admin_password, injected_files,
requested_networks, is_first_time, filter_properties,
legacy_bdm_in_spec)


最后调用self.driver.schedule_run_instance(context,***)

我们再来看看,这个driver是什么东西

scheduler_driver_opt = cfg.StrOpt('scheduler_driver',
default='nova.scheduler.filter_scheduler.FilterScheduler',
help='Default driver to use for the scheduler')

这里配置文件中,Scheduler_driver的默认值default = nova.scheduler.filter_scheduler.FilterScheduler

注意,在早些版本的时候,这个默认值都是MultiScheduler,现在nova-volumn用一个新的项目cinder代替了,所以,也就不采用原来的那个方案了。直接driver= FilterScheduler

  

     (2)通过self.driver.schedule_run_instance(context,***)调用,我们转到了/nova/scheduler/filter_scheduler.py文件,看到class FilterScheduler类。

def schedule_run_instance(self, context, request_spec,
admin_password, injected_files,
requested_networks, is_first_time,
filter_properties, legacy_bdm_in_spec):
"""This method is called from nova.compute.api to provision
an instance.  We first create a build plan (a list of WeightedHosts)
and then provision.

Returns a list of the instances created.
"""
payload = dict(request_spec=request_spec)
self.notifier.info(context, 'scheduler.run_instance.start', payload)

instance_uuids = request_spec.get('instance_uuids')
LOG.info(_("Attempting to build %(num_instances)d instance(s) "
"uuids: %(instance_uuids)s"),
{'num_instances': len(instance_uuids),
'instance_uuids': instance_uuids})
LOG.debug(_("Request Spec: %s") % request_spec)


schedule_run_instance()这个函数里面有一个非常重要的语句是:

#*******************开始调用_schedule方法,来实现调度******************************#
#关键调用
#通过下面的_schedule()进行调度,返回list_host
weighed_hosts = self._schedule(context, request_spec,
filter_properties, instance_uuids)
#**********************************************************************************#


上述通过_scheduler来调度产生最终筛选好的compute node,即weight_hosts(当然,它返回的是一个列表)

(二)让我们看看_scheduler()到底做了什么?

         _scheduler()方法的标准定义如下:
                   
""Returns a list of hosts that meet the required specs,ordered by their fitness.""  ------定义简单明了


FilterScheduler的过程分为两步=Filter+weight,如下图所示



这一个图是官方提供的非常经典的主机过滤过程流程图,照着这个图,我们再去理解代码的含义会相对简单一点。
过程分为1->2->3,最后黄色的host即为_schedule的返回值,下面是对该图过程的具体解释

(1)先解决途中1的hosts是从哪里来的,在_schedule中,我们看到了如下的调用:

hosts = self.host_manager.get_all_host_states(elevated)


再来看上面的函数,我们打开/nova/shceduler/host_manager.py文件,找到对应的get_all_states()方法

def get_all_host_states(self, context):
"""Returns a list of HostStates that represents all the hosts
the HostManager knows about.

Also, each of the consumable resources
in HostState are pre-populated and adjusted based on data in the db.
"""

# Get resource usage across the available compute nodes:
#通过下面的语句,在数据库中得到所有的计算节点信息
#IMPL.compute_node_get_all(context, no_date_fields)
compute_nodes = db.compute_node_get_all(context)


(2)在获取到了hosts列表之后,接下来的工作当然是图中的第2步,Filter,函数调用如下:

hosts = self.host_manager.get_filtered_hosts(hosts,
filter_properties, index=num)


将filter_proprerties,hosts作为参数传到get_filtered_hosts()函数中去,得到Filter之后的hosts

(3)第一次筛选过后,要开始计算每个host的权值,也就是图中的第三步。

weighed_hosts = self.host_manager.get_weighed_hosts(hosts,
filter_properties)


(4)最后返回选择好的主机给compute去执行

在_schedule函数中:

return selected_hosts


在/nova/scheduler/filetr_scheduler中,将weight_hosts再通过另外的函数去执行。

weighed_hosts = self._schedule(context, request_spec,
filter_properties, instance_uuids)


下面有很多比较重要的参数,比如filter_properties,scheduler_hints,request_spec等等,我会通过另外的博文来说明这几个参数到底指代的是什么东西,这里不做讨论。另外,Scheduler的具体细节也是以后再做介绍

好了,一个简单的Scheduler 调度过程讲述完毕,望大神指教




内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息