背景
原生 Kubernetes 调度器仅基于资源的 Request 进行调度,在生产环境资源的真实使用率和申请率往往相差巨大,造成资源浪费的同时也会造成节点的负载不均衡。
开源方案对比 koordinator VS crane
crane-scheduler 架构
前置条件是安装了 Prometheus , 从 Prometheus 中获取数据。
koord-scheduler 架构
监控指标是从 koordlet 中获取, koordlet 是一个 daemonset 类型的插件,负责收集指标,并存储在本地 Prometheus 中
对比
crane-scheduler | koord-scheduler | |
---|---|---|
指标收集周期 | 依赖于外置 Prometheus 的收集周期,默认为 30s (颗粒度较粗,不容易收集到突刺) | ds 方式 的 koordlet 插件收集, 相当于每个 Node 节点都有一个 Prometheus, 收集周期默认为 1s |
数值类型 | avg 、max | avg、p50、p90、p95、p99 |
在离线混部 | 不支持 | 支持 在线 Pod(LSE/LSR/LS)和离线 Pod(BE) |
hotValue 资源预估 | 支持 | 支持 |
使用率 分母 | 宿主机 Total 资源(不合理) | Node allocatable (合理) |
综上,选用 koord-scheduler 。
koordinator 使用实践
新增 UsageAggregatedDuration 为 18h 的时间段
kubectl -n koordinator-system edit cm slo-controller-config
data:
colocation-config: |
{
"enable": true,
"metricAggregatePolicy": {
"durations": [
"5m",
"10m",
"30m",
"18h"
]
}
}
修改 koordlet 中 Prometheus 的存储时间
kubectl -n koordinator-system edit ds koordlet
containers:
- args:
- -addr=:9316
- -cgroup-root-dir=/host-cgroup/
- --logtostderr=true
- --tsdb-retention-duration=18h
可以使用promtool 工具进入 Pod 查看数据:./promtool tsdb list /metric-data/
修改 阈值 触发规则, 需要重启 koord-scheduler 才生效。
kubectl -n koordinator-system edit cm koord-scheduler-config
aggregated:
usageThresholds:
cpu: 55
memory: 85
usageAggregationType: "p99"
scoreAggregationType: "p99"
estimatedScalingFactors:
cpu: 85
memory: 70
kubectl -n koordinator-system rollout restart deployment koord-scheduler
考虑到 公有云资源 可能有自己的 调度实现, 所以只改 IDC 机房的调度器,增加 mutatingwebhook 进行拦截修改,有问题可以快速回退。
生效方式:
kubectl label ns ${NsName} koordinator-injection=enabled
回退方式:
kubectl label ns ${NsName} koordinator-injection-
源代码地址:https://github.com/koordinator-sh/koordinator
魔改代码地址:https://github.com/clay-wangzhi/koordinator
魔改代码 快速部署:
git clone https://github.com/clay-wangzhi/koordinator
cd koordinator/manifests
kubectl apply -f setup/
kubectl apply -f koordlet/
kubectl apply -f koord-scheduler/
kubectl apply -f koord-manager/
测试
1) 找出 负载较高的 Node
kubectl top node | sort -nk 3
kubectl get nodemetrics.slo.koordinator.sh
2) 给一个 负载较高的 Node + 几个 负载正常的 Node 打标签
kubectl label node $(NodeName) test=true
3)找到应用所在 Ns,打标,设置 SchedulerName 为 koord-scheduler 是通过 mutatingwebhook 实现的
kubectl label ns ${NsName} koordinator-injection=enabled
4)找一个应用,加上节点亲和性 和 Pod 反亲和性, 并把副本数 设置为 和 打标的 Node 数 相等
spec:
replicas: 4
template:
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: test
operator: In
values:
- "true"
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: appid
operator: In
values:
- $(AppidName)
topologyKey: kubernetes.io/hostname
5)查看结果,当有一个 Pod 处于 Pending ,且时间 Reson 包涵如下字样,代表设置成功
参考链接:
Crane-Scheduler:真实工作负载感知的调度器设计与实现:https://cloud.tencent.com/developer/article/2296515?areaId=106005 koordinator 负载感知调度:https://koordinator.sh/zh-Hans/docs/user-manuals/load-aware-scheduling