kubernetes scheduler 浅析
什么是kubernetes scheduler?
小到运行着几十个工作负载的 kubernetes 集群,大到运行成千上万个工作负载 kubernetes 集群,每个工作负载到底应该在哪里运行,这需要一个聪明的大脑进行指挥,kubernetes scheduler 就是这个聪明的大脑。从结果看,他的工作很简单,只是为 pod.spec.nodeName 填充上一个 node 的名字而已,从过程看,他又是极其复杂的,因为到底要选哪个节点才最合理,答案往往是和场景强相关的,几乎找不到一套适应各种场景的调度算法。因此,各式各样的算法插件也层出不穷,公司对调度算法的定制化开发也成了常见需求。
调度器如何运行的?
一个调度器主要是由这样两个大循环构成
文章来源:https://www.toymoban.com/news/detail-423058.html
- 第一个控制循环负责从 etcd 里读取未被调度的 pod,添加到调度队列。
- 第二个控制循环的主要逻辑,就是不断地从调度队列里出队一个 pod。然后,调用 Predicates 算法进行“过滤”。这一步“过滤”得到的一组 Node,就是所有可以运行这个 Pod 的宿主机列表。接下来,调度器就会再调用 Priorities 算法为上述列表里的 Node 打分,分数从 0 到 100。得分最高的 Node,就会作为这次调度的结果。调度算法执行完成后,调度器就需要将 Pod 对象的 nodeName 字段的值,修改为上述 Node 的名字。
调度器是如何保障同一个控制器的不同pod副本尽量不要在同一个node上的?
结合我们上面分析的调度器的结构,很容易可以联想到,调度器应该就是在打分阶段,根据节点的不同情况(是否存在相同副本?存在几个?)进行打分,来保证尽量分散 pod 的。没错,调度器确实就是这么做的,不过这个打分的过程又被分成了三个阶段,我们可以通过分析这部分的代码来了解其原理。 源码传送门文章来源地址https://www.toymoban.com/news/detail-423058.html
第一阶段: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 =&#
到了这里,关于kubernetes scheduler 源码解析及自定义资源调度算法实践的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!