基于Kubernetes的容器云平台资源调度策略
调度,给定的N种系统资源,给定一系列任务列表,如何分配各种资源,使得系统的总资源利用达到某种目标,或者资源利用率最高,资源利用率最高等。容器与物理机的调度,主要是物理机有一定的各种资源限额,容器服务有各种不同的资源需求,如何分配这些容器服务分配到指定的物理机节点实现系统功能,以达到系统的资源利用等目标。
调度思想大致分为两种 扩散以及贪心。
扩散:尽量将服务调度到不同的集群节点上以此来保证资源的均衡利用率,避免单机故障的风险
贪心:尽量将所有服务调度到同一节点上,提高资源的利用率
集群资源调度系统分类
集中式调度系统
Swarm Borg 集群使用同一的调度算法进行调度,调度任务不可以并行执行,调度信息需要存储在存储器,任务较重延时较高。Scheduler 支持 Random、Spread 和 Binpack 三种调度策略,其中 Random 策略随机选择目标节点进行 Docker 调度;Spread 和
Binpack 则根据节点可用的 CPU、存资源量和节点上当前运行的 Docker 数量做出调度决策,Spread 将 Docker 分散调度到各个节点上,以提高系统的整体负载均衡;Binpack 与 Spread 相反,将 Docker调度到负载最高的节点上,提高集群中节点承载容器的密度。
两层式调度系统
Memos YARN 资源管理系统负责资源的统一分配和利用,任务调度系统可以执行不同的调度策略来并行调度任务
Mesos Master实现资源的统一分配和管理,调度框架可以并行调度任务。其使用DRF算法来实现对不同类型作业的不同资源需求公平分配。该算法的核心思想是在资源类型多样的环境下,一个作业的资源分配量由作业的主导份额资源决定,主导份额资源是作业请求的各类型资源中占据资源量最大的一种资源。
共享式调度系统
Kubernetes 支持使用不同的调度框架执行不同类型的任务,它的核心是共享状态。为了提高调度系统的并发性和可扩展性,共享式调度系统使用乐观锁进行并发控制,集群的相关信息都增加了版本号,在提交的时候与当前数据的版本号进行对照,若提交的状态信息版本号比当前信息的版本号高,则允许此次提交,否则决绝提交请求,这样虽然会增加资源请求的冲突几率,但是实际应用证明,系统的整体性能并不会因为这些冲突而整体下降。
k8s的Scheduler调度思想:
通过调度策略(算法)依次为待调度 Pod 队列的每一个 Pod 从可用 Node 队列中选择一个最合适的作为宿主机。目标节点上的 Kublet 进程通过 API Server 监听到 Kubernetes 调度器发出的 Pod 绑定事件,然后从 etcd 中获取对应的 Pod 资源描述文件,下载 Image 镜像,启动容器,挂载持久化存储系统。
kubernetes主要使用Pod来作为实际的服务对象,其Pod调度流程如下:
k8s的默认调度策略分析:
默认调度过程如下:
- 首先,客户端通过API Server的REST API/kubectl/helm创建pod/service/deployment/job等,支持类型主要为JSON/YAML/helm tgz。
- 接下来,API Server收到用户请求,存储到相关数据到etcd。
- 调度器通过API Server查看未调度(bind)的Pod列表,循环遍历地为每个Pod分配节点,尝试为Pod分配节点。调度过程分为2个阶段:
- 第一阶段:预选过程,过滤节点,调度器用一组规则过滤掉不符合要求的主机。比如Pod指定了所需要的资源量,那么可用资源比Pod需要的资源量少的主机会被过滤掉。
- 第二阶段:优选过程,节点优先级打分,对第一步筛选出的符合要求的主机进行打分,在主机打分阶段,调度器会考虑一些整体优化策略,比如把容一个Replication Controller的副本分布到不同的主机上,使用最低负载的主机等。
- 选择主机:选择打分最高的节点,进行binding操作,结果存储到etcd中。
- 所选节点对于的kubelet根据调度结果执行Pod创建操作。
k8s的调度优化
k8s的默认指标使用物理机的CPU以及内存等指标来计算物理节点的虚拟性能状态,将Pod对象调度到某个最合适的Node物理节点
物理节点性能指标优化:
可以考虑物理机的cpu,内存,IO,网络,响应时间,链接数等系统资源
论文中主要使用CPU,内存,镜像下载速度,数据传输速度四个指标
镜像下载速度:宿主机需要到 Pod 资源描述文件指定的网络地址下载 Pod 中所有容器的镜像文件,宿主机与镜像存储系统之间的网络传输速度直接关系到 Pod 的启动速度的快慢;这个问题可以通过搭建私有镜像仓库来解决,但是集群规模过大还是会存在的。
数据传输速度:Pod 中数据是临时的,当 Pod 销毁时,其中的数据会丢失,所以 Pod 需要通过数据卷的方式将数据持久化。因此 Pod 在启动运行后,Pod 还需要挂载持久化存储系统进行数据的存取,宿主机与持久化存储之间的数据传输速度会直接影响 Pod中运行的应用的 IO 速度。
用户绑定策略:
论文中提出了各种绑定策略,即指定Pod到某个确定的Node,现在版本应该已经支持很好,可以使用Label标签实现
抢占式调度策略:
现在版本支持Pod优先级抢占,通过PriorityClass来实现同一个Node节点内部的Pod对象抢占。根据 Pod 中运行的作业类型判定各个 Pod 的优先级,对于高优先级的 Pod 可以抢占低优先级 Pod 的资源。Pod priority指的是Pod的优先级,高优先级的Pod会优先被调度,或者在资源不足低情况牺牲低优先级的Pod,以便于重要的Pod能够得到资源部署.
定义PriorityClass对象:
apiVersion: scheduling.k8s.io/v1alpha1
kind: PriorityClass
metadata:
name: high-priority
value: 1000000
globalDefault: false
description: "This priority class should be used for XYZ service pods only."
在Pod的spec. priorityClassName中指定已定义的PriorityClass名称
apiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
env: test
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
priorityClassName: high-priority
当节点没有足够的资源供调度器调度Pod、导致Pod处于pending时,抢占(preemption)逻辑会被触发。Preemption会尝试从一个节点删除低优先级的Pod,从而释放资源使高优先级的Pod得到节点资源进行部署。
论文中按照Pod的重启策略来定义pod优先级,Always>OnFailure>Never
利用容器资源请求量使用优先级队列来进行排序 OnFailure队列 Never队列
Always可以抢占Never,OnFailure资源,依次回收低优先级的Pod对象资源直到宿主机资源满足Always的资源请求
OnFailure可以抢占Never资源
动态负载均衡策略
依据Node节点的衡量指标,定量度量Node节点性能情况,建立高负载队列以及低负载队列,根据系统的实施运行情况来不断调整不同Node节点之间的容器对象,实现资源的均衡利用,主要是扩散思想。
优选策略的设计
假定服务器集群N台,其物理集群定义如下:
各物理节点的资源规格,定义各物理节点的性能度量指标:
其中
ci, mi分别为cpu以及内存的资源配额。
各物理节点的规格系数向量:
其中
分别为cpu以及内存的规格系数 例cpu2核,内存4G 其表示规格系数 2 4
第i个物理节点的资源规格:
集群的资源规格系数:
综合考虑 CPU、内存、镜像网络下载速度、持久化存储网络传输速度四方面因素来决定 Pod 的调度目的地。
计算集群的cpu负载均值,及集群的cpu利用率的加权平均值:
![]()
为第i个节点的cpu规格系数
集群的内存负载均值:
集群镜像网络的传输均值:
集群数据网络的传输均值:
计算第i个物理节点的各种指标得分:
利用均值与节点值的比值作为节点的衡量分数,当该比值越大时表示该节点越低于平均性能,即节点的性能越优。节点相对于集群整体的相对负载情况。
各种指标的权值因子:
该物理节点的性能综合得分:各种指标的加权平均值取对数
值大于零表示,节点的负载低于平均值 小于零表示节点的负载高于平均值
负载队列的实现
建立高负载队列以及低负载队列,得分大于 0 的表示综合负载相对于集群较空闲,存储在低负载队列,小于 0 表示综合负载相对于集群较重,存储在高负载队列。通过周期检测集群的负载情况,将负载较高的节点的一些 Pod 迁移到负载较低的节点上,以保证集群的负载均衡。
利用二叉堆来实现,高负载队列使用最大堆,堆顶元素即为负载最大的Node节点;低负载队列使用最小堆,堆顶元素即为负载最小的Node节点。根据调节阈值,将高负载队列上的容器服务动态调度到低负载队列上,以保证集群的整体资源利用的均衡。
动态控制流程
总体调度算法的设计:
动态调度的具体实现:
算法的负载均衡度的衡量:使用Node集群得分的标准差
总结一下:
同一个Node节点内部实行抢占式调度 根据pod重启策略来定制优先级 优先级高可以抢占优先级低的资源
不同Node节点执行动态调度,衡量每个Node节点分数,建立高负载队列以及低负载队列,然后将高负载队列的pod对象迁移到低负载队列以此来实现资源的均衡利用。
参考论文如下,这篇论文写的真好,学习了。
[1]唐瑞. 基于Kubernetes的容器云平台资源调度策略研究[D].电子科技大学,2017. |