共计 4395 个字符,预计需要花费 11 分钟才能阅读完成。
Kubernetes 自带了一个默认调度器 kube-scheduler,其内置了很多节点预选和优选的调度算法,一般调度场景下可以满足要求。但是在一些特殊场景下,默认调度器不能满足我们复杂的调度需求。我们就需要对调度器进行扩展,以达到调度适合业务场景的目的。
背景
中间件 redis 容器化后,需要两主不能在同一个节点上,一对主从不能在同一节点上;elasticsearch 容器化后,两个 data 实例不能在同一节点上。在这类场景下,默认调度器内置的预选、优选算法不能满足需求,我们有以下三种选择:
将新的调度算法添加到默认调度程序中,并重新编译镜像,最终该镜像运行的实例作为 kubernetes 集群调度器;
参考 kube-scheduler 实现满足自己业务场景的调度程序,并编译镜像,将该程序作为独立的调度器运行到 kubernetes 集群内,需要用该调度器调度的 pod 实例,在 spec.schedulerName 里指定该调度器;
image
实现“调度扩展程序“:默认调度器 kube-scheduler 在进行预选时会调用该扩展程序进行过滤节点;在优选时会调用该扩展程序进行给节点打分,或者在 bind 操作时,调用该扩展器进行 bind 操作。
对上述三种方式进行评估:
第一种:将自己的调度算法添加到默认调度器 kube-scheduler 中,对原生代码侵入性较高,而且随着 kubernetes 版本升级,维护成本也较高;
第二种:默认调度器里内置了很多优秀调度算法,如:检查节点资源是否充足;端口是否占用;volume 是否被其他 pod 挂载;亲和性;均衡节点资源利用等,如果完全使用自己开发的调度器程序,可能在达到了实际场景调度需求同时,失去更佳的调度方案,除非集成默认调度器中的算法到自己独立调度程序中,但这无疑是不现实的;
第三种:通过启动参数的 policy 配置,选用某些默认调度器中的预选、优选调度算法的同时,也可以调用外部扩展调度程序的算法,计算得到最优的调度节点,无需修改 kube-scheduler 代码,只需要在启动参数中增加配置文件即可将默认调度程序和扩展调度程序相互关联。
可以参考:
https://github.com/kubernetes…
故采用第三种:实现扩展调度程序的方案。
整体架构
image
kube-scheduler 在调度 pod 实例时,首先获取到 Node1、Node2、Node3 三个节点信息,进行默认的预选阶段,筛选满足要求的节点,其次再调用扩展程序中的预选算法,选出剩下的节点,假设预选阶段 Node3 上资源不足被过滤掉,预选结束后只剩 Node1 和 Node2;Node1 和 Node2 进入 kube-scheduler 默认的优选阶段进行节点打分,其次再调用扩展调度程序中的优选算法进行打分,kube-scheduler 会将所有算法的打分结果进行加权求和,获得分数最高的节点作为 pod 最终 bind 节点,然后 kube-scheduler 调用 apiserver 进行 bind 操作。
实现步骤
实现扩展调度程序代码
编写扩展调度器程序代码,根据实际业务调度场景编写预选逻辑、优选逻辑:
image
实现预选接口,入参为 schedulerapi.ExtenderArgs,出参为 schedulerapi.ExtenderFilterResult:
image
实现优选接口,入参为 schedulerapi.ExtenderArgs,出参为 schedulerapi.HostPriorityList:
image
暴露 http 接口:
image
参考:
https://github.com/ll83744879…
默认调度器部署
由于 kubernetes 集群内已经有了一个名为 default-scheduler 的默认调度器,为了不影响集群正常调度功能,下面会创建一个名为 my-kube-scheduler 的调度器,这个调度器和 default-scheduler 除了启动参数不一样外,镜像无差别。
1、创建一个名为 my-scheduler-config 的 configmaps,data 下的 config.yaml 文件指定了调度器的一些参数,包括 leader 选举,调度算法策略的选择(指定另一个 configmaps),以及指定调度器的名称为 my-kube-scheduler。
相应的创建一个 my-scheduler-policy 的 configmaps,里面指定了选择哪些预选、优选策略,以及外部扩展调度程序的 urlPrefix、扩展预选 URI、扩展优选 URI、扩展 pod 优先级抢占 URI、扩展 bind URI、扩展优选算法的权重等。
以保证 my-kube-scheduler 和扩展调度程序的通信。
apiVersion: v1
kind: ConfigMap
metadata:
name: my-scheduler-config
namespace: kube-system
data:
config.yaml: |
apiVersion: kubescheduler.config.k8s.io/v1alpha1
kind: KubeSchedulerConfiguration
schedulerName: my-kube-scheduler
algorithmSource:
policy:
configMap:
namespace: kube-system
name: my-scheduler-policy
leaderElection:
leaderElect: false
lockObjectName: my-kube-scheduler
lockObjectNamespace: kube-system
apiVersion: v1
kind: ConfigMap
metadata:
name: my-scheduler-policy
namespace: kube-system
data:
policy.cfg : |
{
"kind" : "Policy",
"apiVersion" : "v1",
"predicates" : [{"name" : "PodFitsHostPorts"},
{"name" : "PodFitsResources"},
{"name" : "NoDiskConflict"},
{"name" : "MatchNodeSelector"},
{"name" : "HostName"}
],
"priorities" : [{"name" : "LeastRequestedPriority", "weight" : 1},
{"name" : "BalancedResourceAllocation", "weight" : 1},
{"name" : "ServiceSpreadingPriority", "weight" : 1},
{"name" : "EqualPriority", "weight" : 1}
],
"extenders" : [{
"urlPrefix": "http://10.168.107.12:80/scheduler",
"filterVerb": "predicates/always_true",
"prioritizeVerb": "priorities/zero_score",
"preemptVerb": "preemption",
"bindVerb": "","weight": 1,"enableHttps": false,"nodeCacheCapable": false
}],
"hardPodAffinitySymmetricWeight" : 10
}
2、在 my-kube-scheduler yaml 文件中将 configmaps:my-scheduler-config 以文件的形式挂载到容器内 /my-scheduler 目录下,并在启动参数中指定 –config=/my-scheduler/config.yaml,使用和默认调度器一样的镜像。
image
增加挂载:
image
image
扩展调度器镜像制作和部署
1、编译扩展调度程序 my-scheduler-extender 镜像,以下为 Dockerfile:
image
推送 my-scheduler-extender 镜像到 harbor:
image
2、创建外部扩展程序 my-scheduler-extender 的 deployment,如下为 yaml 描述:
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-scheduler-extender
namespace: kube-system
labels:
app: my-scheduler-extender
spec:
replicas: 1
selector:
matchLabels:
app: my-scheduler-extender
template:
metadata:
labels:
app: my-scheduler-extender
spec:
containers:
- name: my-scheduler-extender
image: 192.168.26.46/k8s-deploy/my-scheduler-extender:v1.0
imagePullPolicy: Always
livenessProbe:
httpGet:
path: /version
port: 80
readinessProbe:
httpGet:
path: /version
port: 80
ports:
- containerPort: 80
验证
查看 my-kube-scheduler pod 日志,加载到了 policy 里的 extender 信息,获取到了扩展调度器的接口地址:
image
创建一个 nginx 的 pod,指定 schedulerName 为 my-kube-scheduler:
image
查看扩展调度器 pod 日志,发现默认调度器会调用 extender 扩展调度器,如下为 extender 日志打印的入参、出参:
image
从而可以通过编写扩展调度程序,对默认调度器的预选和优选算法进行扩展。
参考
https://github.com/kubernetes…
https://github.com/ll83744879…
最后,csdn 资源,收集了海量学习资料,如果你准备入 IT 坑,励志成为优秀的程序猿,那么这些资源很适合你,包括 java、go、python、springcloud、elk、嵌入式、大数据、面试资料、前端等资源。同时我们组建了一个技术交流群,里面有很多大佬,会不定时分享技术文章,如果你想来一起学习提高,可以关注以下公众号后回复【2】,获取。
我是小碗汤,我们一起学习,扫码关注,精彩内容第一时间推给你
长按扫码关注一起交流
Docker 与 … kubernetes Kubernetes
2
小礼物走一走,来简书关注我
赞赏支持
老公在这里买翡翠超划算,缅甸天然翡翠!
广告