
Nova 调度器如何选主机一文读懂【免费下载链接】novaOpenStack Compute (Nova). Mirror of code maintained at opendev.org.项目地址: https://gitcode.com/gh_mirrors/no/novaOpenStack Nova 调度器负责决定新虚拟机该放到哪台计算节点上是 nova-scheduler 服务里的决策引擎。它解决的问题很实际在几十上百台资源各异的计算节点中避开容量不足、能力不匹配的主机把资源账提前扣好并给失败留一条换机重试的路。它为什么存在想象一次并发扩容10 个租户同时开机集群里有 40 台计算节点内存和 CPU 余量各不相同。没有集中决策的话要么虚拟机落到装不下的节点上构建失败要么全部堆到同一两台主机上争抢 I/O 把宿主机拖垮多 cell多单元部署里跨单元迁移更慢更危险更需要有人提前判断留在本 cell 还是出去。Nova 调度器把这件事拆成三件事容量匹配哪台装得下、资源记账Placement 里提前扣减防止两个实例抢同一份资源、备用方案首选节点失败时直接换机重试不必重新走完整流程。核心机制拆解一次调度由 4 个环节串成因果链先缩小候选再淘汰不合格的然后给剩下的排队最后扣账并留后路。环节一候选集查询——先问 Placement谁装得下职责一句话把请求翻译成资源需求让 Placement 服务做全局容量粗筛。select_destinations收到 conductor 发来的 RequestSpec 后先经request_filter.process_reqspec做请求级预处理租户聚合限制、可用区映射、镜像类型检查等再由utils.resources_from_request_spec把 flavor、镜像、调度提示翻译成资源请求调用placement_client.get_allocation_candidates。Placement 返回装得下的主机清单和每个候选的资源分配方案allocation request。返回为空就直接抛NoValidHost后面的过滤权重一步都不会跑。你能干预创建实例时的 scheduler hintshost、node、availability_zone、聚合体 metadata都会在这一阶段生效。环节二过滤——逐个淘汰不合格的主机职责一句话候选集进入get_filtered_hosts按enabled_filters的顺序逐台过host_passes。每个过滤器只回答一个问题这台主机现在能不能跑这个实例。默认启用 5 个ComputeFilter查 ComputeNode 表里的资源余量、ComputeCapabilitiesFilterCPU 架构、hypervisor 能力、ImagePropertiesFilter镜像属性比如 x86_64 镜像不能落到 aarch64 节点、ServerGroupAntiAffinityFilter和ServerGroupAffinityFilterserver group 的反亲和/亲和。你能干预enabled_filters的顺序——限制最强的放前面剪枝最快hints 里的force_hosts、ignore_hosts会在过滤器执行之前就把名单锁死。环节三权重评分——给活下来的主机排队职责一句话get_weighed_hosts让每个权重器按顺序给主机加减分按总分降序排列。RAMWeigher、CPUWeigher、DiskWeigher基于空闲资源打分BuildFailureWeigher对最近构建失败的主机大幅降分默认乘数 1000000。排好序后并不是直接取第一名而是从最重的host_subset_size台里随机选一台放到队首——这是专门避免多个调度进程同时抢同一台最优主机的设计。你能干预各个*_weight_multiplier。正数偏散开选资源最多的负数偏堆叠填满一台再换下一台绝对值控制该因素相对其他因素的强度。环节四资源预留与备机——扣账并留后路职责一句话选中主机后向 Placement 发起 claim同时按max_attempts挑出备用主机。claim 成功这台主机的资源在 Placement 里正式记账别的调度请求不会再占到同一份资源失败就换排序后的下一台主机再试全部失败会回滚已扣的资源并抛NoValidHost。成功的主机连同同 cell 里的若干候选被打包成 Selection 对象返回给 conductor——构建失败时 conductor 直接按序换备机省掉一次完整调度。多实例请求multi-create里每选中一台就在本地 HostState 上执行consume_from_request虚拟扣减让下一台实例的过滤和评分基于更新后的状态。环节输入输出可调参数候选集查询RequestSpec候选主机 allocation requestsscheduler hints、租户聚合限制过滤候选主机合格主机enabled_filters、available_filters评分排序合格主机按权重排序的主机weight_classes、各 weight_multiplier预留与备机排序后的主机Selection主选 备机max_attempts、host_subset_size读懂关键代码评分之后的随机挑选nova/scheduler/manager.py的_get_sorted_hosts约 15 行骨架def _get_sorted_hosts(self, spec_obj, host_states, index): # 过滤只留 host_passes 的主机 filtered_hosts self.host_manager.get_filtered_hosts(host_states, spec_obj, index) if not filtered_hosts: return [] # 评分按权重器累加分数后降序排列 weighed_hosts self.host_manager.get_weighed_hosts(filtered_hosts, spec_obj) ... host_subset_size CONF.filter_scheduler.host_subset_size weighed_subset weighed_hosts[0:host_subset_size] # 取前 N 名 chosen_host random.choice(weighed_subset) # N 名里随机挑 1 台 weighed_hosts.remove(chosen_host) return [chosen_host] weighed_hosts # 它排第一其余保持原序真正值得注意的不是过滤和评分本身而是最后两行默认host_subset_size 1时随机只发生在第一名之间等价于必选第一名但一旦有大批主机权重并列Ironic 裸机集群很常见随机就从 1 台扩大到并列的全体明显降低争用和反复调度的概率。候选集为空就直接失败select_destinations的主流程骨架如下def select_destinations(self, context, request_specNone, ..., spec_obj_sentinel, ...): # hints 等请求级预处理失败抛 NoValidHost request_filter.process_reqspec(context, spec_obj) # 翻译资源需求并问 Placement哪些主机装得下 res self.placement_client.get_allocation_candidates(context, resources) alloc_reqs res[0] or [] if not alloc_reqs: raise exception.NoValidHost(reason) # 候选为空直接失败 # 过滤 评分 claim 备机 return self._select_destinations(...)值得注意的是alloc_reqs为空时的处理此时日志里会出现 Got no allocation candidates from the Placement API且NoValidHost的 reason 是空字符串——排查时看到这个组合应该去查 flavor 容量和 Placement 服务状态而不是怀疑过滤器。配置速查参数默认值作用调优建议enabled_filtersComputeFilter, ComputeCapabilitiesFilter, ImagePropertiesFilter, ServerGroupAntiAffinityFilter, ServerGroupAffinityFilter按顺序执行的过滤器限制最强的放最前面weight_classesnova.scheduler.weights.all_weighers参与评分的权重器集合一般不动调乘数即可host_subset_size1从权重最高的 N 台里随机选 1 台并发量大时设 2~3 降低争用ram_weight_multiplier1.0正数偏好内存多的主机散开负数偏好内存少的堆叠想堆叠密度时设 -1.0max_attempts3构建失败时最多换几台备机重试资源紧张集群调大max_placement_results1000Placement 返回候选的主机数上限大集群调小以省内存和流量max_instances_per_host50单主机实例数上限须配合启用 NumInstancesFiltertrack_instance_changesTrue允许调度器向 compute 查实例信息多 cell 且 cell MQ 独立时必须关闭常见问题与反模式现象调度失败NoValidHostreason 为空。原因Placement 返回的候选为空flavor 超过全集群容量。处理查 flavor 规格或等节点资源释放。现象改完enabled_filters后服务起不来。原因新过滤器没登记进available_filters。处理两边同时修改并重启 nova-scheduler。现象限流不生效比如单主机实例数上限没起作用。原因max_instances_per_host只有启用NumInstancesFilter才生效。处理确认过滤器在enabled_filters列表里。现象同一台主机被反复选中构建失败重试频繁。原因host_subset_size 1且权重最高者固定。处理增大host_subset_size或启用shuffle_best_same_weighed_hosts。现象多 cell 部署里亲和性过滤表现异常。原因track_instance_changes依赖 compute 直连顶层消息队列。处理关闭它改用[workarounds] disable_group_policy_check_upcall。源码入口nova/scheduler/manager.py调度服务主逻辑select_destinations与_schedulenova/scheduler/rpcapi.py调度 RPC 接口定义conductor 的调用入口nova/scheduler/host_manager.pyHostState 维护过滤与评分的执行nova/scheduler/filters/18 个内置过滤器均实现host_passesnova/scheduler/weights/12 个权重器均实现_weigh_objectnova/conf/scheduler.py[scheduler]与[filter_scheduler]配置项定义【免费下载链接】novaOpenStack Compute (Nova). Mirror of code maintained at opendev.org.项目地址: https://gitcode.com/gh_mirrors/no/nova创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考