1 scheduling framework
当前k8s的调度器使用的是scheduling framework
https://kubernetes.io/docs/concepts/scheduling-eviction/scheduling-framework/ 调度器定义了一些列的hook点, 插件可以自行扩展
2 新的调度特性
Pod Scheduling Readiness
pod在创建后, 可以定义schedulingGates, 调度器如果发现pod的spec包含了schedulingGates, 就不进行调度, pod状态为SchedulingGated
apiVersion: v1
kind: Pod
metadata:
name: test-pod
spec:
schedulingGates:
- name: example.com/foo
- name: example.com/bar
containers:
- name: pause
image: registry.k8s.io/pause:3.6
知道外部将schedulingGates移除后调度器才开始调度, 类似finalizer.
Pod Overhead
可以先定义一个RuntimeClass
apiVersion: node.k8s.io/v1
kind: RuntimeClass
metadata:
name: kata-fc
handler: kata-fc
overhead:
podFixed:
memory: "120Mi"
cpu: "250m"
然后创建pod时指定runtimeClassName:
apiVersion: v1
kind: Pod
metadata:
name: test-pod
spec:
runtimeClassName: kata-fc
...
admission controller会将RuntimeClass中定义的量设置到pod.spec.overhead上
调度器调度时会把这个pod的资源需求理解成requests+overhead
cgroup配置时:
- cpu.cfs_quota_us: limit+overhead
- memory.limit_in_bytes memory: limit+overhead
- cpu.shares: requests+overhead
3 scheduler调度策略配置
Scheduling Policies
早期通过配置predicates and priorities来修改调度策略, 1.23版本的k8s之后不再支持, 而是使用Scheduler Configuration
Scheduler Configuration
https://kubernetes.io/docs/reference/scheduling/config/
Scheduler Configuration基于Scheduling Framework定义的hook点, 允许用户自行配置.
自定义插件时, 一般拉取k8s的scheduler代码库, 然后基于这份代码库开发自己 的插件. 当然也可以完全自己开发, 本质上其实就是监听pod然后设置 pod的.spec.nodeName.
开发完成后, 可以直接将原生的调度器的镜像替换掉并修改对应的配置文件, 也可以多个调度器同时存在, 然后通过schedulerName区分 https://kubernetes.io/docs/reference/scheduling/config/#multiple-profiles
方法:在配置文件中定义好不同的schedulerName对应什么插件配置, 创建pod时 配置好需要使用哪个scheduler来调度(通过.spec.schedulerName)scheduling framework在调度pod时会查看.spec.schedulerName, 然后从配置文件中读取对 应的插件配置, 如果读取不到, 就不会调度.
4 scheduler中的几个队列
- activeQ: 根据pod优先级排序的一个heap, 调用循环会不断从中取pod进行调度
- unschedulableQ: 暂时不调度的队列
- podBackoffQ: 根据backoff time(决定多久之后重试)排序的一个heap, schedule或者binding失败后挪到这个队列, 然后等待时机挪到activeQ里
- backoff time根据失败次数不断指数增加, 一直到最大值(默认10s)