文档章节

Kubernetes Scheduler的Predicates和Priorities Policies解读

WaltonWang
 WaltonWang
发布于 2017/01/19 12:30
字数 1761
阅读 414
收藏 0

【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>>

本文是对Kubernetes V1.5 Scheduler 的预选策略Predicates Policies和优选策略Priorities Policies的含义解读,并附有部分样例代码代码解析。关于kubernetes调度器更全面的解析见我的其他博客:Kubernetes Scheduler源码分析, Kubernetes Scheduler原理解析

##Predicates Policies分析 在/plugin/pkg/scheduler/algorithm/predicates.go中实现了以下的预选策略:

  • NoDiskConflict:检查在此主机上是否存在卷冲突。如果这个主机已经挂载了卷,其它同样使用这个卷的Pod不能调度到这个主机上。GCE,Amazon EBS, and Ceph RBD使用的规则如下:

    • GCE允许同时挂载多个卷,只要这些卷都是只读的。
    • Amazon EBS不允许不同的Pod挂载同一个卷。
    • Ceph RBD不允许任何两个pods分享相同的monitor,match pool和 image。
  • NoVolumeZoneConflict:检查给定的zone限制前提下,检查如果在此主机上部署Pod是否存在卷冲突。假定一些volumes可能有zone调度约束, VolumeZonePredicate根据volumes自身需求来评估pod是否满足条件。必要条件就是任何volumes的zone-labels必须与节点上的zone-labels完全匹配。节点上可以有多个zone-labels的约束(比如一个假设的复制卷可能会允许进行区域范围内的访问)。目前,这个只对PersistentVolumeClaims支持,而且只在PersistentVolume的范围内查找标签。处理在Pod的属性中定义的volumes(即不使用PersistentVolume)有可能会变得更加困难,因为要在调度的过程中确定volume的zone,这很有可能会需要调用云提供商。

  • PodFitsResources:检查主机的资源是否满足Pod的需求。根据实际已经分配的资源量做调度,而不是使用已实际使用的资源量做调度。

  • PodFitsHostPorts:检查Pod内每一个容器所需的HostPort是否已被其它容器占用。如果有所需的HostPort不满足需求,那么Pod不能调度到这个主机上。

  • HostName:检查主机名称是不是Pod指定的HostName。

  • MatchNodeSelector:检查主机的标签是否满足Pod的nodeSelector属性需求。

  • MaxEBSVolumeCount:确保已挂载的EBS存储卷不超过设置的最大值。默认值是39。它会检查直接使用的存储卷,和间接使用这种类型存储的PVC。计算不同卷的总目,如果新的Pod部署上去后卷的数目会超过设置的最大值,那么Pod不能调度到这个主机上。

  • MaxGCEPDVolumeCount:确保已挂载的GCE存储卷不超过设置的最大值。默认值是16。规则同上。

下面是NoDiskConflict的代码实现,其他Predicates Policies实现类似,都得如下函数原型: type FitPredicate func(pod *v1.Pod, meta interface{}, nodeInfo *schedulercache.NodeInfo) (bool, []PredicateFailureReason, error)


func NoDiskConflict(pod *v1.Pod, meta interface{}, nodeInfo *schedulercache.NodeInfo) (bool, []algorithm.PredicateFailureReason, error) {
	for _, v := range pod.Spec.Volumes {
		for _, ev := range nodeInfo.Pods() {
			if isVolumeConflict(v, ev) {
				return false, []algorithm.PredicateFailureReason{ErrDiskConflict}, nil
			}
		}
	}
	return true, nil, nil
}


func isVolumeConflict(volume v1.Volume, pod *v1.Pod) bool {
	// fast path if there is no conflict checking targets.
	if volume.GCEPersistentDisk == nil && volume.AWSElasticBlockStore == nil && volume.RBD == nil && volume.ISCSI == nil {
		return false
	}

	for _, existingVolume := range pod.Spec.Volumes {
		...

		if volume.RBD != nil && existingVolume.RBD != nil {
			mon, pool, image := volume.RBD.CephMonitors, volume.RBD.RBDPool, volume.RBD.RBDImage
			emon, epool, eimage := existingVolume.RBD.CephMonitors, existingVolume.RBD.RBDPool, existingVolume.RBD.RBDImage
			// two RBDs images are the same if they share the same Ceph monitor, are in the same RADOS Pool, and have the same image name
			// only one read-write mount is permitted for the same RBD image.
			// same RBD image mounted by multiple Pods conflicts unless all Pods mount the image read-only
			if haveSame(mon, emon) && pool == epool && image == eimage && !(volume.RBD.ReadOnly && existingVolume.RBD.ReadOnly) {
				return true
			}
		}
	}

	return false
}

##Priorities Policies分析

现在支持的优先级函数包括以下几种:

  • LeastRequestedPriority:如果新的pod要分配给一个节点,这个节点的优先级就由节点空闲的那部分与总容量的比值(即(总容量-节点上pod的容量总和-新pod的容量)/总容量)来决定。CPU和memory权重相当,比值最大的节点的得分最高。需要注意的是,这个优先级函数起到了按照资源消耗来跨节点分配pods的作用。计算公式如下: cpu((capacity – sum(requested)) * 10 / capacity) + memory((capacity – sum(requested)) * 10 / capacity) / 2

  • BalancedResourceAllocation:尽量选择在部署Pod后各项资源更均衡的机器。BalancedResourceAllocation不能单独使用,而且必须和LeastRequestedPriority同时使用,它分别计算主机上的cpu和memory的比重,主机的分值由cpu比重和memory比重的“距离”决定。计算公式如下: score = 10 – abs(cpuFraction-memoryFraction)*10

  • SelectorSpreadPriority:对于属于同一个service、replication controller的Pod,尽量分散在不同的主机上。如果指定了区域,则会尽量把Pod分散在不同区域的不同主机上。调度一个Pod的时候,先查找Pod对于的service或者replication controller,然后查找service或replication controller中已存在的Pod,主机上运行的已存在的Pod越少,主机的打分越高。

  • CalculateAntiAffinityPriority:对于属于同一个service的Pod,尽量分散在不同的具有指定标签的主机上。

  • ImageLocalityPriority:根据主机上是否已具备Pod运行的环境来打分。ImageLocalityPriority会判断主机上是否已存在Pod运行所需的镜像,根据已有镜像的大小返回一个0-10的打分。如果主机上不存在Pod所需的镜像,返回0;如果主机上存在部分所需镜像,则根据这些镜像的大小来决定分值,镜像越大,打分就越高。

  • NodeAffinityPriority(Kubernetes1.2实验中的新特性):Kubernetes调度中的亲和性机制。Node Selectors(调度时将pod限定在指定节点上),支持多种操作符(In, NotIn, Exists, DoesNotExist, Gt, Lt),而不限于对节点labels的精确匹配。另外,Kubernetes支持两种类型的选择器,一种是“hard(requiredDuringSchedulingIgnoredDuringExecution)”选择器,它保证所选的主机必须满足所有Pod对主机的规则要求。这种选择器更像是之前的nodeselector,在nodeselector的基础上增加了更合适的表现语法。另一种是“soft(preferresDuringSchedulingIgnoredDuringExecution)”选择器,它作为对调度器的提示,调度器会尽量但不保证满足NodeSelector的所有要求。

下面是ImageLocalityPriority的代码实现,其他Priorities Policies实现类似,都得如下函数原型: type PriorityMapFunction func(pod *v1.Pod, meta interface{}, nodeInfo *schedulercache.NodeInfo) (schedulerapi.HostPriority, error)

func ImageLocalityPriorityMap(pod *v1.Pod, meta interface{}, nodeInfo *schedulercache.NodeInfo) (schedulerapi.HostPriority, error) {
	node := nodeInfo.Node()
	if node == nil {
		return schedulerapi.HostPriority{}, fmt.Errorf("node not found")
	}

	var sumSize int64
	for i := range pod.Spec.Containers {
		sumSize += checkContainerImageOnNode(node, &pod.Spec.Containers[i])
	}
	return schedulerapi.HostPriority{
		Host:  node.Name,
		Score: calculateScoreFromSize(sumSize),
	}, nil
}

func calculateScoreFromSize(sumSize int64) int {
	var score int
	switch {
	case sumSize == 0 || sumSize < minImgSize:
		// score == 0 means none of the images required by this pod are present on this
		// node or the total size of the images present is too small to be taken into further consideration.
		score = 0
	// If existing images' total size is larger than max, just make it highest priority.
	case sumSize >= maxImgSize:
		score = 10
	default:
		score = int((10 * (sumSize - minImgSize) / (maxImgSize - minImgSize)) + 1)
	}
	// Return which bucket the given size belongs to
	return score
}

其计算每个Node的Score算法为: score = int((10 * (sumSize - minImgSize) / (maxImgSize - minImgSize)) + 1)

其中: minImgSize int64 = 23 * mb, maxImgSize int64 = 1000 * mb, sumSize为Pod中定义的container Images' size 的总和

可见,Node上该Pod要求的容器镜像大小之和越大,得分越高,越有可能是目标Node。

其他Priorities Policies的实现和算法请类似分析。

© 著作权归作者所有

WaltonWang
粉丝 229
博文 106
码字总数 226882
作品 0
深圳
程序员
私信 提问
《k8s-1.13版本源码分析》- 调度器设计

本文原始地址:https://farmer-hutao.github.io/k8s-source-code-analysis/core/scheduler/desigh.html github项目地址:https://github.com/farmer-hutao/k8s-source-code-analysis 1. 概述......

CloudGeek
02/21
0
0
103 - 调度算法-寻找predicates和priorities

scheduler的主要逻辑是predicate和priority,前者回答哪些节点可以运行pod的问题,后者回答哪个节点更合适运行pod的问题。今天我们的任务是:从主函数出发,寻找predicates和priorities的入口...

CloudGeek
2018/11/18
0
0
独家解读 etcd 3.4版本 |云原生生态周报 Vol. 18

独家解读 etcd 3.4版本 |云原生生态周报 Vol. 18 作者 | 酒祝、墨封、宇慕、衷源 关注“阿里巴巴云原生”公众号,回复关键词 “资料” ,即可获得 2019 全年 meetup 活动 PPT 合集及 K8s 最全...

阿里巴巴云原生
09/05
114
0
Kubernetes 1.8抢占式调度Preemption源码分析

Author: xidianwangtao@gmail.com 阅读本博文前,建议先阅读解析Kubernetes 1.8中的基于Pod优先级的抢占式调度。 ScheduleAlgorithm的变化 在Kubernetes 1.8中,对ScheduleAlgorithm Interfa...

WaltonWang
2017/11/06
779
2
深入剖析k8s之默认调度器调度策略解析

本篇专注在调度过程中 Predicates 和 Priorities 这两个调度策略主要发生作用的阶段。 Predicates 首先,我们一起看看 Predicates。 Predicates 在调度过程中的作用,可以理解为 Filter,即:...

xiaomin0322
10/10
14
0

没有更多内容

加载失败,请刷新页面

加载更多

006-ELK的二进制安装

二进制安装ELKstack 本次搭建属于单点,在同一台机器上进行安装 基础组件部署 curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo wget -O /etc/yu...

伟大源于勇敢的开始
今天
5
0
OSChina 周四乱弹 —— 浙江台的电话号码倒是记得挺牢

Osc乱弹歌单(2019)请戳(这里) 【今日歌曲】 @巴拉迪维 :《Out On The Streets》 一直不理解北欧人对重金属和死亡摇滚的热情,听完这首歌好像理解了。#今日歌曲推荐# 《Out On The Stre...

小小编辑
今天
14
0
Leetcode PHP题解--D121 21. Merge Two Sorted Lists

D121 21. Merge Two Sorted Lists 题目链接 21. Merge Two Sorted Lists 题目分析 合并两个有序链表。 思路 逐个遍历两个链表,把小的数字塞入数组里。之后再拼起来。 最终代码 <?php/** *...

skys215
今天
6
0
mars-config 动态配置管理

mars-config 码云地址:https://gitee.com/fashionbrot/mars-config 介绍 spring mvc 、springboot 动态配置系统。http 轮训方式 更新 动态配置 软件架构 软件架构说明 后端使用技术 :sprin...

fashionbrot
今天
16
0
女朋友玩吃鸡手游被开挂老哥骗炮,我见义勇为将骗子绳之以法

大家好,我是乔哥。 晚上10点以后下班后我回到自如出租房里面,开始处理公众号粉丝发来的消息,一条一条处理,突然看到了这么几条消息,吸引了我的眼球: 然后我就和这位女粉丝小红(化名)聊...

gzc426
今天
14
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部