1 | +----------------------------------------------------------+ |
Controller Manager 负责将集群调整至预期的状态,而 Scheduler 则是集群调度器,将预期的 Pod 资源调度到正确的 Node 节点上,进而令该 Pod 可完成启动
kube-scheduler 是一个策略丰富,拓扑感知的调度程序,会显著影响可用性,性能和容量
服务端二进制文件解压后,便可看到 kube-scheduler 的可执行文件。当给它传递 --help 查看其支持参数的时候,便可以看到它支持使用 --address 或者 --bind-address 等参数指定所启动的 HTTP server 所绑定的地址之类的。
它和 kube-controller-manager 有点类似,同样是通过定时的向 kube-apiserver 请求获取信息,并进行处理。而他们所起到的作用并不相同
从上层的角度来看,kube-scheduler 的作用就是将待调度的 Pod 调度至最佳的 Node 上,而这个过程中则需要根据不同的策略,考虑到 Node 的资源使用情况,比如端口,内存,存储等
当实际进行部署操作的时候,首先会通过 kubectl 之类的客户端工具与 kube-apiserver 进行交互,在经过一系列的处理后,数据将持久化到 etcd 中;
此时,kube-controller-manager 通过持续的观察,开始按照我们的配置,将集群的状态调整至预期状态;
而 kube-scheduler 也在发挥作用,决定 Pod 应该调度至哪个或者哪些 Node 上;之后则通过其他组件的协作,最总将该 Pod 在相应的 Node 上部署启动
处理阶段
kube-scheduler 将处理阶段主要分为三个阶段 Computing predicates,Prioritizing和 Selecting host:
1 | Computing predicates: |
// 给每个经过第一步筛选出来的 Node 一个 Score,再按照各种条件进行打分,最终得到一个优先级列表。
for i := range nodes {
result = append(result, schedulerapi.HostPriority{Host: nodes[i].Name, Score: 0})
for j := range priorityConfigs {
result[i].Score += results[j][i].Score * priorityConfigs[j].Weight
}
}
1 |
|
func (g *genericScheduler) selectHost(priorityList schedulerapi.HostPriorityList) (string, error) {
if len(priorityList) == 0 {
return “”, fmt.Errorf(“empty priorityList”)
}
sort.Sort(sort.Reverse(priorityList))
maxScore := priorityList[0].Score
firstAfterMaxScore := sort.Search(len(priorityList), func(i int) bool { return priorityList[i].Score < maxScore })
g.lastNodeIndexLock.Lock()
ix := int(g.lastNodeIndex % uint64(firstAfterMaxScore))
g.lastNodeIndex++
g.lastNodeIndexLock.Unlock()
return priorityList[ix].Host, nil
}
参考资料:
<https://kubernetes.io/docs/reference/command-line-tools-reference/kube-scheduler/>