前言
为什么需要Binpack功能?
Kubernetes默认开启的资源调度策略是LeastRequestedPriority
,消耗的资源最少的节点得分最高,优先被调度。这样的资源选择情况有可能导致较多的资源碎片,如下图所示,两个节点各剩余1GPU的资源,导致申请2GPU的作业无法调度,导致整体资源使用率下降。
如果使用的资源调度策略是Binpack,优先将节点填满之后,再调度下一个节点,则上图所出现的资源碎片问得到解决,申请2GPU的作业被正常调度到节点上,提升了集群的资源使用率。
实现方案
Binpack实现已经抽象成Scheduler Framework的Score插件,用于优选阶段节点打分。具体的实现可以分为两个部分,构建打分函数和打分.
构建打分函数
构建打分函数的过程比较容易理解,就是用户可以自己定义不同的利用率所对应的分值大小,以便影响调度的决策过程。
1.如果用户设定的对应方式如下所示,即如果资源利用率为0的时候,得分为0分,当资源利用率为100时,得分为10分,所以得到的资源利用率越高,得分越高,则这个行为是Binpack的资源选择方式。
2.用户也可以设置成利用率为0时,得分为10分,利用率为100时,得分为0分。这样意味着资源利用率越低,则得分越高,这种行为是spread的资源选择方式。
3.用户除了2个点之外也可以新增更多的点,对应关系可以不是线性的关系,例如可以标识资源利用率为50时,得分为8,则会将打分分割为两个区间: 0-50和50-100。
打分
用户可以自己定义在Binpack计算中所要参考的资源以及权重值,例如可以只是设定GPU和CPU的值和权重。
resourcetoweightmap:
"cpu": 1
"nvidia.com/gpu": 1
然后在打分过程总,会通过计算(pod.Request + node.Allocated)/node.Total的结果得到对应资源的利用率,并且将利用率带入上文中所述的打分函数中,得到相应的分数。最后将所有的资源根据weight值,加权得到最终的分数。
Score = line(resource1_utilization) * weight1 + line(resource2_utilization) * weight2 ....) / (weight1 + weight2 ....)
Binpack使用
前提条件
- 目前需要使用CPU和内存的Binpack时,需要支持Kubernetes 1.14及以上版本
- 需要支持GPU等扩展资源的Binpack时,需要支持Kubernetes 1.16及以上版本
配置方法
- 修改 /etc/kubernetes/manifests/kube-scheduler.yaml, 在Kube-scheduler的启动命令中增加--policy-config-file=/etc/kubernetes/scheduler-policy.json, 并且配置相应的volumes和volumeMounts支持目录挂载,配置的参考示例:
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
component: kube-scheduler
tier: control-plane
name: kube-scheduler
namespace: kube-system
spec:
containers:
- command:
- kube-scheduler
- --bind-address=127.0.0.1
- --kubeconfig=/etc/kubernetes/scheduler.conf
- --leader-elect=true
- -v=3
- --policy-config-file=/etc/kubernetes/scheduler-policy.json
image: registry-vpc.cn-beijing.aliyuncs.com/acs/kube-scheduler:v1.14.8-aliyun.1
imagePullPolicy: IfNotPresent
livenessProbe:
failureThreshold: 8
httpGet:
host: 127.0.0.1
path: /healthz
port: 10251
scheme: HTTP
initialDelaySeconds: 15
timeoutSeconds: 15
name: kube-scheduler
resources:
requests:
cpu: 100m
volumeMounts:
- mountPath: /etc/kubernetes/scheduler.conf
name: kubeconfig
readOnly: true
- mountPath: /etc/localtime
name: localtime
- mountPath: /etc/kubernetes/scheduler-policy.json
name: policy
hostNetwork: true
priorityClassName: system-cluster-critical
volumes:
- hostPath:
path: /etc/kubernetes/scheduler.conf
type: FileOrCreate
name: kubeconfig
- hostPath:
path: /etc/localtime
type: ""
name: localtime
- hostPath:
path: /etc/kubernetes/scheduler-policy.json
type: FileOrCreate
name: policy
status: {}
- 新建/etc/kubernetes/scheduler-policy.json, 用户可以自行配置其他的priorities策略。
{
"kind" : "Policy",
"apiVersion" : "v1",
"priorities" : [
{
"name":"RequestedToCapacityRatioPriority",
"weight":5,
"argument":{
"requestedToCapacityRatioArguments":{
"shape":[
{
"utilization":0,
"score":0
},
{
"utilization":100,
"score":10
}
],
"resources":[
{
"name": "cpu",
"weight": 1
},
{
"name": "nvidia.com/gpu",
"weight": 1
}
]
}
}
}
]
}
Demo演示
当前集群有3个节点, 每个节点的CPU剩余资源为3.6个cpu
1.如果当前集群没有开启Binpack的功能是,我们创建nginx容器
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: nginx
labels:
app: nginx
spec:
replicas: 6
selector:
matchLabels:
app: nginx
template:
metadata:
name: nginx
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
resources:
limits:
cpu: 500m
memory: 500Mi
requests:
cpu: 500m
memory: 500Mi
结果是所有的pod被均匀的分布到3个节点上。
# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-5rh66 1/1 Running 0 34s 172.20.0.211 cn-beijing.192.168.5.232 <none> <none>
nginx-859lz 1/1 Running 0 34s 172.20.0.210 cn-beijing.192.168.5.232 <none> <none>
nginx-bjsfq 1/1 Running 0 34s 172.20.1.8 cn-beijing.192.168.5.231 <none> <none>
nginx-hnpfg 1/1 Running 0 34s 172.20.1.75 cn-beijing.192.168.5.233 <none> <none>
nginx-kgc58 1/1 Running 0 34s 172.20.1.9 cn-beijing.192.168.5.231 <none> <none>
nginx-sbhxl 1/1 Running 0 34s 172.20.1.74 cn-beijing.192.168.5.233 <none> <none>
2.如果开启了Binpack的功能时,如下面结果所示, 所有的Nginx pod被分配到同一个节点cn-beijing.192.168.5.232上,优先打满一个节点
# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-62ltj 1/1 Running 0 68s 172.20.0.204 cn-beijing.192.168.5.232 <none> <none>
nginx-75fzz 1/1 Running 0 68s 172.20.0.206 cn-beijing.192.168.5.232 <none> <none>
nginx-8mxl8 1/1 Running 0 68s 172.20.0.209 cn-beijing.192.168.5.232 <none> <none>
nginx-pbv9s 1/1 Running 0 68s 172.20.0.208 cn-beijing.192.168.5.232 <none> <none>
nginx-qrkqh 1/1 Running 0 68s 172.20.0.207 cn-beijing.192.168.5.232 <none> <none>
nginx-xgfgq 1/1 Running 0 68s 172.20.0.205 cn-beijing.192.168.5.232 <none> <none>