01
前言
在近期的工作中,我们发现 k8s 集群中有些节点资源使用率很高,有些节点资源使用率很低,我们尝试重新部署应用和驱逐 Pod,发现并不能有效解决负载不均衡问题。
02
调度不均衡的原因
1.1 sceduler 不是根据node负载进行调度
k8s 调度器默认会根据Pod cpu和内存request 值调度,Pod request 值大的优先调度到Node 可用资源(可用资源=Node实际资源-Pod request )较多的节点,并不是根据Node 实时动态cpu负载进行资源调度的。
1.2 设置的requests和limits不合理
有些项目接入k8s时,cpu 和内存的request 设置的不合理,有的偏大,有的偏小。比如,项目cpu 使用率高,request设置的很大,那这个项目会调度到负载低的Node,这样没什么问题;如果项目cpu使用率低,request设置很大,那会导致这个Node可用资源很小,其他Pod 不会调度到这个Node,从而导致资源利用率很低。
03 descheduler的不足
descheduler缺少对Node真实资源占用的支持,也就说并不是根据Node真实cpu 内存使用来驱逐调度的,并不能完全解决问题,因此我们并没有采用这个方案。
04 如何解决
为了解决调度不均问题,我们主要做了几方面的工作。
- 动态采集node节点的内存使用率,如果内存使用率超过设定阈值,就将此node节点设置为禁止调度。
- 定期判断node节点内存负载率,如果内存使用率降下来,低于阈值,则放开调度。
- 判断整个k8s集群中禁止调度的nde节点占整个集群node节点总数的占比,如果小于30%(比例自行调整),则告警通知k8s集群管理员增加node节点。
4. 以下脚本仅仅实现了上述1、2 点的功能,建议每5-10分钟运行一次,告警通知的节点请自行实现。
#! /bin/bash
#对实际使用内存大于75%的机器停止调度,对实际使用内存小于65%的 关闭调度
# 获取实际内存小于或等于65%的机器
memory_lt_65=`kubectl top nodes |awk '{if($5+0<=65) print $1}'`
# 获取实际内存大于或等于75%的机器
memory_gt_75=`kubectl top nodes |awk '{if($5+0>=75) print $1}'`
#获取已经关闭调度的机器
SchedulingDisabled=`kubectl get nodes |egrep -v "control-plane|master" |grep SchedulingDisabled | awk '{print $1}'`
# 如果有关闭调度的机器,判断其内存小于或等于65%,则放开调度
if [ -n "$SchedulingDisabled" ];then
for node in $SchedulingDisabled ;do
if [[ $memory_lt_65 =~ $node ]];then
kubectl uncordon $node
fi
done
fi
#如果有内存大于或等于75%的机器,判断其是否停止调度,如果没有,则停止调度
if [ -n "$memory_gt_75" ];then
for node in $memory_gt_75 ;do
if [[ $SchedulingDisabled =~ $node ]];then
echo $node is aleady cordorned
else
kubectl cordon $node
fi
done
fi