欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Cinder的cinder-scheduler源码解读

程序员文章站 2022-05-11 15:41:59
...
与Nova中的调度服务nova-scheduler类似,Cinder的调度服务cinder-scheduler也用于选择一个合适的节点,不过不同的是nova-scheduler选择的是计算节点来响应用户有关虚拟机生命周期的请求,而cinder-scheduler选择的是cinder-volume节点来处理用户有关Volume周期的请求。
同样,cinder-scheduler选择的方式也可以有很多种,为了便于之后的扩展,Cinder将一个调度器必须实现的接口提取出来成为cinder.scheduler.driver.Scheduler,只要继承类SchedulerDriver并实现其中的接口,就可以实现一个自己的调度器。
# cinder / scheduler / driver.py
class Scheduler(object):
     """The base class that all Scheduler classes should inherit from."""
目前,Cinder中只实现了一个调度器FilterScheduler,但是历史上曾经存在SimpleScheduler(选择剩余空间最多的Host)和ChanceFilter(随机挑选满足条件的Host)两个调度器,但是它们现在已经被利用FilterScheduler的框架重新实现。
# cinder / scheduler / filter_scheduler.py
class FilterScheduler(driver.Scheduler):
     """Scheduler that can be used for filtering and weighing."""
     def __init__(self, *args, **kwargs):
         super(FilterScheduler, self).__init__(*args, **kwargs)
         self.cost_function_cache = None
         self.options = scheduler_options.SchedulerOptions()
         self.max_attempts = self._max_attempts()
不同的调度器不能共存,需要在/etc/cinder/cinder.conf中通过scheduler_driver选项指定,默认使用的即是FilterScheduler
Default scheduler driver to use (string value)
#scheduler_driver=cinder.scheduler.filter_scheduler.FilterScheduler
FilterScheduler的工作流程基本与Nova的FilterScheduler调度器相同。
FilterScheduler首先使用指定的Filter(过滤器)得到符合条件的cinder-volume节点,比如Volume有足够的存储空间,然后对得到的主机列表计算权重并排序,获得最佳的一个。
完整来说这个过程分为几个阶段:
一 通过cinder.scheduler.rpcapi.SchedulerAPI发出RPC请求
通常Openstack项目中各个服务所在的目录都会有一个rpcapi.py文件,其中定义了所能提供的RPC接口。对于cinder-scheduler服务来说,其他服务将cinder.scheduler.rpcapi模块导入就可以使用其定义的接口远程调用cinder-scheduler提供的服务。cinder-scheduler注册的RPC Server接收到RPC请求后,再由cinder.scheduler.manager.SchedulerManger真正地完成选择cinder-volume节点的操作。
# cinder / scheduler / rpcapi.py
class SchedulerAPI(object):
    RPC_API_VERSION = '1.0'
    def __init__(self):
        super(SchedulerAPI, self).__init__()
        target = messaging.Target(topic=CONF.scheduler_topic,
                                  version=self.RPC_API_VERSION)
        self.client = rpc.get_client(target, version_cap='1.7')
    def create_volume(self, ctxt, topic, volume_id, snapshot_id=None,
                       image_id=None, request_spec=None,
                       filter_properties=None):
        cctxt = self.client.prepare(version='1.2')
        request_spec_p = jsonutils.to_primitive(request_spec)
        return cctxt.cast(ctxt, 'create_volume',
                           topic=topic,
                           volume_id=volume_id,
                           snapshot_id=snapshot_id,
                           image_id=image_id,
                           request_spec=request_spec_p,
                           filter_properties=filter_properties)

# cinder / scheduler / manager.py
class SchedulerManager(manager.Manager):
     """Chooses a host to create volumes."""
     def create_volume(self, context, topic, volume_id, snapshot_id=None,
                       image_id=None, request_spec=None,
                       filter_properties=None):
         try:
             flow_engine = create_volume.get_flow(context,
                                                  db, self.driver,
                                                  request_spec,
                                                  filter_properties,
                                                  volume_id,
                                                  snapshot_id,
                                                  image_id)
         except Exception:
             LOG.exception(_("Failed to create scheduler manager volume flow"))
             raise exception.CinderException(
                 _("Failed to create scheduler manager volume flow"))
         with flow_utils.DynamicLogListener(flow_engine, logger=LOG):
             flow_engine.run()
二 从SchedulerManager到调度器(类SchedulerDiver)
类SchedulerManager用于接收RPC请求,在一些参数验证之后,将请求交由具体的调度器来处理,它在RPC客户端和具体调度器之间起到一个桥梁作用。
类SchedulerManager初始化的时候会根据配置文件/etc/cinder/cinder.conf中选项scheduler_driver的值初始化相应的调度器。
三 Filtering(过滤)与Weighing(权重计算与排序)
Filtering就是使用配置中指定的各种Filters去过滤掉不符合条件的主机,Weighing则是对所有符合条件的主机计算权重(Weight)并排序从而得到最佳的一个。Cinder中已经实现了几种不同的Filter和Weight,所有Filter的实现位于cinder/scheduler/filters目录,所有Weigher的实现位于cinder/scheduler/weights目录。
Filter与Weigher的实现都有特定的要求,比如所有的Filter都必须继承自cinder.openstack.common.scheduler.BaseHostFilter,我们也可以很方便通过继承类BaseHostFilter来创建一个新的Filter,新建的Filter只需实现一个函数host_passes(),返回结果只有两种,满足条件返回True,否则返回False。
我们也可以在配置文件中指定哪些Filter与Weigher:
#scheduler_default_filters=AvailabilityZoneFilter,CapacityFilter,CapabilitiesFilter
# Which weigher class names to use for weighing hosts. (list value)
#scheduler_default_weighers=CapacityWeigher


相关标签: cinder