kubernetes scheduler 源码解析及自定义资源调度算法实践

kubernetes scheduler 浅析

什么是kubernetes scheduler?

小到运行着几十个工作负载的 kubernetes 集群,大到运行成千上万个工作负载 kubernetes 集群,每个工作负载到底应该在哪里运行,这需要一个聪明的大脑进行指挥,kubernetes scheduler 就是这个聪明的大脑。从结果看,他的工作很简单,只是为 pod.spec.nodeName 填充上一个 node 的名字而已,从过程看,他又是极其复杂的,因为到底要选哪个节点才最合理,答案往往是和场景强相关的,几乎找不到一套适应各种场景的调度算法。因此,各式各样的算法插件也层出不穷,公司对调度算法的定制化开发也成了常见需求。

调度器如何运行的?

一个调度器主要是由这样两个大循环构成

  • 第一个控制循环负责从 etcd 里读取未被调度的 pod,添加到调度队列。
  • 第二个控制循环的主要逻辑,就是不断地从调度队列里出队一个 pod。然后,调用 Predicates 算法进行“过滤”。这一步“过滤”得到的一组 Node,就是所有可以运行这个 Pod 的宿主机列表。接下来,调度器就会再调用 Priorities 算法为上述列表里的 Node 打分,分数从 0 到 100。得分最高的 Node,就会作为这次调度的结果。调度算法执行完成后,调度器就需要将 Pod 对象的 nodeName 字段的值,修改为上述 Node 的名字。

调度器是如何保障同一个控制器的不同pod副本尽量不要在同一个node上的?

结合我们上面分析的调度器的结构,很容易可以联想到,调度器应该就是在打分阶段,根据节点的不同情况(是否存在相同副本?存在几个?)进行打分,来保证尽量分散 pod 的。没错,调度器确实就是这么做的,不过这个打分的过程又被分成了三个阶段,我们可以通过分析这部分的代码来了解其原理。 源码传送门

第一阶段:PreScore

func (pl *SelectorSpread) PreScore(ctx context.Context, cycleState *framework.CycleState, pod *v1.Pod, nodes []*v1.Node) *framework.Status {
	if skipSelectorSpread(pod) {
		return nil
	}
	var selector labels.Selector
	selector = helper.DefaultSelector(
		pod,
		pl.services,
		pl.replicationControllers,
		pl.replicaSets,
		pl.statefulSets,
	)
	state := &preScoreState{
		selector: selector,
	}
	cycleState.Write(preScoreStateKey, state)
	return nil
}
复制代码
func DefaultSelector(pod *v1.Pod, sl corelisters.ServiceLister, cl corelisters.ReplicationControllerLister, rsl appslisters.ReplicaSetLister, ssl appslisters.StatefulSetLister) labels.Selector {
	labelSet := make(labels.Set)
	// Since services, RCs, RSs and SSs match the pod, they won't have conflicting
	// labels. Merging is safe.

	if services, err := GetPodServices(sl, pod); err == nil {
		for _, service := range services {
			labelSet = labels.Merge(labelSet, service.Spec.Selector)
		}
	}

	if rcs, err := cl.GetPodControllers(pod); err == nil {
		for _, rc := range rcs {
			labelSet = labels.Merge(labelSet, rc.Spec.Selector)
		}
	}

	selector := labels.NewSelector()
	if len(labelSet) != 0 {
		selector = labelSet.AsSelector()
	}

	if rss, err := rsl.GetPodReplicaSets(pod); err == nil {
		for _, rs := range rss {
			if other, err := metav1.LabelSelectorAsSelector(rs.Spec.Selector); err == nil {
				if r, ok := other.Requirements(); ok {
					selector = selector.Add(r...)
				}
			}
		}
	}

	if sss, err := ssl.GetPodStatefulSets(pod); err =&#
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值