频道栏目
首页 > 资讯 > 虚拟机 > 正文

OpenStackNova学习总结之虚拟机调度算法的实现

18-06-23        来源:[db:作者]  
收藏   我要投稿

一、概述

虚拟机调度器主要完成以下工作:

过滤掉不满足虚拟机要求的主机 对剩余主机进行权重计算 选取权重计算值最优的主机返回

OpenStack 的虚拟机调度策略主要是由 FilterScheduler 和 ChanceScheduler 实现的,其中FilterScheduler 作为默认的调度器实现了基于主机过滤(filtering)和权值计算(weighing)的调度算法,而 ChanceScheduler 则是基于随机算法来选择可用主机的简单调度引擎。

下图是 FilterScheduler 的虚拟机调度过程,它支持多种内置的 filter 和 weigher 来满足一些常见的业务场景。在设计上,OpenStack 基于 filter 和 weigher 支持第三方扩展,因此用户可以通过自定义filter 和 weigher,或者使用 json 资源选择表达式来影响虚拟机的调度策略从而满足不同的业务需求。

作为 nova-scheduler 默认的调度器,FilterScheduler 调度过程分为两步:

1)通过过滤(filtering)选择满足条件的计算节点(运行 nova-compute)。

2)通过权重计算(weighting)选择在最优(权重值最大)的计算节点上创建实例。

这里写图片描述

上图是调度过程的一个示例:

最开始有 6 个计算节点 Host1-Host6 通过多个 filter 层层过滤,Host2 和 Host4 没有通过,被刷掉了 Host1,Host3,Host5,Host6 计算权重,结果 Host5 得分最高,最终入选

二、主机过滤

当 Filter scheduler 需要执行调度操作时,会让 filter 对计算节点进行判断,filter 返回 True 或 False。

nova.conf 中的 scheduler_available_filters 选项用于配置 scheduler 可用的 filter,默认是所有 nova 自带的 filter 都可以用于滤操作。

scheduler_available_filters = nova.scheduler.filters.all_filters

另外还有一个选项 scheduler_default_filters,用于指定 scheduler 真正使用的 filter,默认值如下

scheduler_default_filters = RetryFilter, AvailabilityZoneFilter, RamFilter, DiskFilter, ComputeFilter, ComputeCapabilitiesFilter, ImagePropertiesFilter, ServerGroupAntiAffinityFilter, ServerGroupAffinityFilter

Filter scheduler 将按照列表中的顺序依次过滤。 下面依次介绍每个 filter 及其他 filter。

1.RetryFilter

RetryFilter 的作用是刷掉之前已经调度过的节点。

举例: 假设 A,B,C 三个节点都通过了过滤,最终 A 因为权重值最大被选中执行操作,但由于某个原因,操作在 A 上失败了。 默认情况下,nova-scheduler 会重新执行过滤操作(重复次数由 scheduler_max_attempts 选项指定,默认是 3)。这时候 RetryFilter 就会将 A 直接刷掉,避免操作再次失败。

RetryFilter 通常作为第一个 filter。

2.AvailabilityZoneFilter

为提高容灾性和提供隔离服务,可以将计算节点划分到不同的 Availability Zone (可用域) 中,例如把一个机架上的机器划分在一个 Availability Zone 中。关于 Availability Zone 和 Region 等的区别,请参见《OpenStack几个物理上的概念总结》。

OpenStack 默认有一个命名为 “nova” 的可用域,所有的计算节点初始都是放在 “nova” 中。用户可以根据需要创建自己的可用域。

创建实例时,需要指定将实例部署到在哪个可用域中。

这里写图片描述

3.RamFilter

RamFilter 将不能满足 flavor 内存需求的计算节点过滤掉。

为了提高系统的资源使用率,OpenStack 在计算节点可用内存时允许 overcommit(超配),也就是可以超过实际内存大小。超过的程度是通过 nova.conf 中 ram_allocation_ratio 这个参数来控制的,默认值为 1.5。

ram_allocation_ratio = 1.5

其含义是:如果计算节点的内存有 10GB,OpenStack 则会认为它有 15GB(10*1.5)的内存。

4.DiskFilter

DiskFilter 将不能满足 flavor 磁盘需求的计算节点过滤掉。

Disk 同样允许超配,通过 nova.conf 中 disk_allocation_ratio 控制,默认值为 1。

disk_allocation_ratio = 1.0

在生产环境中,建议磁盘不超配。

5.CoreFilter

CoreFilter 将不能满足 flavor vCPU 需求的计算节点过滤掉。

vCPU 同样允许超配,通过 nova.conf 中 cpu_allocation_ratio 控制,默认值为 16。

cpu_allocation_ratio = 16.0

这意味着一个 8 CPU 的计算节点,nova-scheduler 在调度时认为它有 128 个 vCPU。

注意: nova-scheduler 默认使用的 filter 并没有包含 CoreFilter。 如果要用,可以将 CoreFilter 添加到 nova.conf 的 scheduler_default_filters 配置选项中。

6.ComputeFilter

ComputeFilter 保证只有 nova-compute 服务正常工作的计算节点才能够被 nova-scheduler 调度。

ComputeFilter 显然是必选的 filter。

7.ComputeCapabilitiesFilter

ComputeCapabilitiesFilter 根据计算节点的特性来筛选。

例如:我们的节点有 x86_64 和 ARM 架构的,如果想将实例指定部署到 x86_64 架构的节点上,就可以利用到 ComputeCapabilitiesFilter 。

flavor 中有个 Metadata,Compute 的 Capabilities 就在 Metadata 中指定,在下图中点击“更新元数据”,然后点击 “Architecture” 后面的 “+”,就可以在右边的列表中指定具体的架构,比如 x86_64。

配置好后,ComputeCapabilitiesFilter 在调度时只会筛选出 x86_64 的节点。 如果没有设置 Metadata,ComputeCapabilitiesFilter 不会起作用,所有节点都会通过筛选。
这里写图片描述

8.ImagePropertiesFilter

ImagePropertiesFilter 根据所选 image 的属性来筛选匹配的计算节点。

跟 flavor 类似,image 也有 metadata,用于指定其属性。

例如:希望某个 image 只能运行在 kvm 的 hypervisor 上,可以通过 “Hypervisor Type” 属性来指定。在下图中点击“更新元数据”,然后点击 “Hypervisor Type” 后面的 “+”,在右边的列表中选择 kvm。

配置好后,ImagePropertiesFilter 在调度时只会筛选出 kvm 的节点。如果没有设置 Image 的Metadata,ImagePropertiesFilter 不会起作用,所有节点都会通过筛选。
这里写图片描述

9.ServerGroupAntiAffinityFilter

ServerGroupAntiAffinityFilter 可以尽量将实例分散部署到不同的计算节点上。

例如:有 inst1,inst2 和 inst3 三个实例,计算节点有 A,B 和 C。

为保证分散部署,进行如下操作:

1)创建一个 anti-affinity 策略的 server group “group-1”

 nova server-group-create --policy anti-affinity group-1

请注意,这里的 server group 其实是实例 group,并不是计算节点的 group。

2)依次创建实例,将 inst1, inst2 和 inst3 放到group-1中

    nova boot --image IMAGE_ID --flavor 1 --hint group=group-1 inst1 
    nova boot --image IMAGE_ID --flavor 1 --hint group=group-1 inst2 
    nova boot --image IMAGE_ID --flavor 1 --hint group=group-1 inst3

因为 group-1 的策略是 AntiAffinity,调度时 ServerGroupAntiAffinityFilter 会将 inst1, inst2 和 inst3 部署到不同计算节点 A, B 和 C。

目前只能在命令行中指定 server group 来创建实例。

创建实例时如果没有指定 server group,ServerGroupAntiAffinityFilter 会直接通过,不做任何过滤。

10.ServerGroupAffinityFilter

与 ServerGroupAntiAffinityFilter 的作用相反,ServerGroupAffinityFilter 会尽量将实例部署到同一个计算节点上。

1)创建一个 affinity 策略的 server group “group-2”

    nova server-group-create --policy affinity group-2

2)依次创建实例,将 inst1, inst2 和inst3 放到 group-2 中

    nova boot --image IMAGE_ID --flavor 1 --hint group=group-2 inst1 
    nova boot --image IMAGE_ID --flavor 1 --hint group=group-2 inst2 
    nova boot --image IMAGE_ID --flavor 1 --hint group=group-2 inst3

因为 group-2 的策略是 Affinity,调度时 ServerGroupAffinityFilter 会将 inst1, inst2 和 inst3 部署到同一个计算节点。

创建实例时如果没有指定 server group,ServerGroupAffinityFilter 会直接通过,不做任何过滤。

11.其他 filter

名称 功能 使用方法
AggregateCoreFilter 针对某个Host Aggregate单独设置主机能够分配虚拟机的vCPU/pCPU的比例,超过比例就不能分配虚拟机了;没有设置,默认就用全局的CoreFilter配置数据 针对HostAggregate设置一个metadata(Key,Value),比如设置cpu_allocation_ratio=10
AggregateInstanceExtraSpecsFilter 在指定的HostAggregate中选定一个主机分配虚拟机 需要在HostAggregate打上flavor的对应标签,就是HostAggreagate和flavor要设置相同的metadata(key,value),比如两个都增加ssd=true的key-value metadata,则表明只在存储为固态硬盘的主机分配虚拟机规格为flavor的虚拟机
AggregateMultiTenancyIsolation 在指定的HostAggregate中只允许给某个租户分配虚拟机 HostAggregate增加一个metadata(key,value),filter_tenant_id = xxx
AggregateRamFilter 和AggregateCoreFilter类似,只不过针对的是内存 参考AggregateCoreFilter
AllHostsFilter 允许所有的HOST参加分配  
DifferentHostFilter 指定不要和某些虚拟机实例共享主机,可以用于互斥的分配场景  
SameHostFilter 在指定虚拟机所在主机上分配虚拟机  
SimpleCIDRAffinityFilter 根据某个子网IP地址范围内的主机进行虚拟机分配 如下为在192.18.1.1的子网分配虚拟机‘os:scheduler_hints’:{‘build_near_host_ip’:‘192.168.1.1’,‘cidr’:‘24’}

12.AggregateInstanceExtraSpecsFilter实验

1)创建主机聚合 agg-nova

创建主机聚合

这里写图片描述

把主机 compute1 加入到主机聚合 agg-nova 中

这里写图片描述

定义元数据 ssd=true

这里写图片描述

主机 flavor 加入元数据

这里写图片描述

通过界面查看

这里写图片描述
flavor m1.nano 也设置了元数据
这里写图片描述

2)修改nova配置文件

把 AggregateInstanceExtraSpecsFilter 放在第一个 filter 位置

 vi /etc/nova/nova.conf

这里写图片描述

重启服务

service nova-api restart
service nova-scheduler restart
service nova-conductor restart
service nova-compute restart

3)启动实例

选择 flavor m1.nano

这里写图片描述

可以看到启动的实例调度到 compute1 节点上面

这里写图片描述

查看调度日志(此示例中有两个计算节点,controller和compute1)

nova.scheduler.filters.aggregate_instance_extra_specs [req-ec42b63d-fb58-44c8-8c35-0f9a13227ab3 dac40addebd34335b6e060045de2bc12 60d1424aa7974287ae5d22e894018c8c - - -] 
(controller, controller) ram: 2445MB disk: 7168MB io_ops: 0 instances: 0 fails instance_type extra_specs requirements. Extra_spec ssd is not in aggregate. 
host_passes /usr/lib/python2.7/dist-packages/nova/scheduler/filters/aggregate_instance_extra_specs.py:64

节点controller没有通过aggregate_instance_extra_specs的过滤,pass掉

Filter AggregateInstanceExtraSpecsFilter returned 1 host(s) get_filtered_objects /usr/lib/python2.7/dist-packages/nova/filters.py:104

一个节点通过AggregateInstanceExtraSpecsFilter

Filter AvailabilityZoneFilter returned 1 host(s) get_filtered_objects /usr/lib/python2.7/dist-packages/nova/filters.py:104

一个节点通过AvailabilityZoneFilter

Filter RamFilter returned 1 host(s) get_filtered_objects /usr/lib/python2.7/dist-packages/nova/filters.py:104

一个节点通过RamFilter

Filter ComputeFilter returned 1 host(s) get_filtered_objects /usr/lib/python2.7/dist-packages/nova/filters.py:104

一个节点通过ComputeFilter

Filtered [(compute1, compute1) ram: 2445MB disk: 8192MB io_ops: 0 instances: 0] _schedule /usr/lib/python2.7/dist-packages/nova/scheduler/filter_scheduler.py:118

节点compute1通过过滤

Weighed [WeighedHost [host: (compute1, compute1) ram: 2445MB disk: 8192MB io_ops: 0 instances: 0, weight: 0.0]] _schedule /usr/lib/python2.7/dist-packages/nova/scheduler/filter_scheduler.py:123

节点compute1权重,没有其他节点对比,默认为0

Selected host: WeighedHost [host: (compute1, compute1) ram: 2445MB disk: 8192MB io_ops: 0 instances: 0, weight: 0.0] 

选择节点compute1,完成调度

三、权值计算

经过前面一堆 filter 的过滤,nova-scheduler 选出了能够部署 instance 的计算节点。

如果有多个计算节点通过了过滤,Scheduler 会对每个计算节点打分,得分最高的获胜。

打分的过程就是权值计算,是一种能够在过滤集中找出最佳主机的一种机制。为了能够控制不同的权值因素,使用权值系数。因此,最终的公式可以定义为:

weight = w1_multiplier * norm(w1) + w2_multiplier * norm(w2) + ...

权值计算是 weights.BaseHostWeigher 类的子类,可以实现 weight_multiplier 和 _weight_object 方法,也可以只实现 _weight_object 方法。

对于权值计算部分,在配置文件 nova.scheduler.weights.all_weighers 中,默认的基于scheduler_weight_classes 类,分别包括下列权值计算函数:

RAMWeigher:通过可用的RAM大小决定计算节点。

DiskWeigher:通过可用的磁盘大小进行权值分配,最大的优先级最高。

MetricsWeigher:通过主机的不同参数度量决定主机的权值。在配置文件中指定相关参数:

metrics_weight_setting = name1=1.0,name2=-1.0

IoOpsWeigher:通过主机的负载进行权重计算,默认选择负载最小的主机。

ServerGroupSoftAffinityWeigher:通过同一个主机组中运行的实例数进行权重计算。

默认实现是根据计算节点空闲的内存量计算权重值:空闲内存越多,权重越大,实例将被部署到当前空闲内存最多的计算节点上。

四、定制方案

通过分析源代码,我们可以看到 FilterScheduler 调度器有以下定制的方法:

1.不用默认的 filter_scheduler.py 的 class FilterScheduler,完全可以从 driver.py/class Scheduler 继承并实现自己的类。

2.不使用默认的物理主机状态管理类 host_manager.py/ classHostManager,自己从 HostManager 继承或者重载实现 xxxHostManager 类进行物理主机状态的管理。

3.提供自己的调度过滤器或者权重过滤器插件,参考 affinity_filter.py 或 ram.py 实现自己的插件,在部署的时候配置为自己的插件即可。

4.在物理主机中定义一个主机组 Group,然后在 Scheduler Hint 中带上这个 Group,也可以实现可定制的调度策略。

5.在 Scheduler Hint 中增加自定义的调度条件,在调度的时候通过自己的 Filter 插件增加调度能力。

6.在创建虚拟机请求的AZ参数中通过“AZ:host”的方式指定主机进行虚拟机的创建。

7.调度器始终监控一个调度配置 json 文件,如果这个文件发生变化,则动态加载这个调度配置文件,改变和调整调度策略,因此可以动态修改这个 json 文件修改调度策略。

这里写图片描述

这里写图片描述

注:此总结基于 OpenStack Mitaka 版本,最新版可能稍有不同。

Ocata版本的变化:

增加 Placement 服务。 FilterScheduler 只能基于 Placement 服务做调度 。现在只支持 CPU, RAM 和 Disk 资源 。将来会支持更多资源类型。

这里写图片描述

相关TAG标签
上一篇:shell中的常用语句 for,while语句
下一篇:Linux下SPI驱动实例讲解
相关文章
图文推荐

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训 | 举报中心

版权所有: 红黑联盟--致力于做实用的IT技术学习网站