首页 > 其他分享 >k8s 更换默认调度器两种方案-Crane-scheduler

k8s 更换默认调度器两种方案-Crane-scheduler

时间:2022-12-05 20:05:45浏览次数:59  
标签:avg name 5m scheduler usage Crane k8s cpu

k8s 更换默认调度器两种方案

背景

原生 kubernetes 调度器只能基于资源的 resource request 进行调度,然而 Pod 的真实资源使用率,往往与其所申请资源的 request/limit 差异很大,这直接导致了集群负载不均的问题:

  1. 集群中的部分节点,资源的真实使用率远低于 resource request,却没有被调度更多的 Pod,这造成了比较大的资源浪费;
  2. 而集群中的另外一些节点,其资源的真实使用率事实上已经过载,却无法为调度器所感知到,这极大可能影响到业务的稳定性。

这些无疑都与企业上云的最初目的相悖,为业务投入了足够的资源,却没有达到理想的效果。 既然问题的根源在于 resource request 与真实使用率之间的「鸿沟」,那为什么不能让调度器直接基于真实使用率进行调度呢?这就是 Crane-scheduler 设计的初衷。Crane-scheduler 基于集群的真实负载数据构造了一个简单却有效的模型,作用于调度过程中的 Filter 与 Score 阶段,并提供了一种灵活的调度策略配置方式,从而有效缓解了 kubernetes 集群中各种资源的负载不均问题。换句话说,Crane-scheduler 着力于调度层面,让集群资源使用最大化的同时排除了稳定性的后顾之忧,真正实现「降本增效」。

Crane-scheduler 介绍

(​​https://github.com/gocrane/crane-scheduler​​)

整体架构

k8s 更换默认调度器两种方案-Crane-scheduler _Crane-scheduler

如上图所示,Crane-scheduler 依赖于 Node-exporter 与 Prometheus 两个组件,前者从节点收集负载数据,后者则对数据进行聚合。而 Crane-scheduler 本身也包含两个部分:

  1. Scheduler-Controller 周期性地从 Prometheus 拉取各个节点的真实负载数据, 再以 Annotation 的形式标记在各个节点上;
  2. Scheduler 则直接在从候选节点的 Annotation 读取负载信息,并基于这些负载信息在 Filter 阶段对节点进行过滤以及在 Score 阶段对节点进行打分;

基于上述架构,最终实现了基于真实负载对 Pod 进行有效调度。

调度策略

k8s 更换默认调度器两种方案-Crane-scheduler _Crane-scheduler_02

Crane-scheduler 主要作用于图中的 Filter 与 Score 阶段,并对用户提供了一个非常开放的策略配置。这也是 Crane-Scheduler 与社区同类型的调度器最大的区别之一: 1) 前者提供了一个泛化的调度策略配置接口,给予了用户极大的灵活性; 2) 后者往往只能支持 cpu/memory 等少数几种指标的感知调度,且指标聚合方式,打分策略均受限。 在 Crane-scheduler 中,用户可以为候选节点配置任意的评价指标类型(只要从 Prometheus 能拉到相关数据),不论是常用到的 CPU/Memory 使用率,还是 IO、Network Bandwidth 或者 GPU 使用率,均可以生效,并且支持相关策略的自定义配置。

用户可以直接 Describe 节点,查看到节点的负载信息,方便问题定位:

用户可以自定义负载数据的类型与拉取周期,默认情况下,数据拉取的配置如下:

syncPolicy:
## cpu usage
- name: cpu_usage_avg_5m
period: 3m
- name: cpu_usage_max_avg_1h
period: 15m
- name: cpu_usage_max_avg_1d
period: 3h
## memory usage
- name: mem_usage_avg_5m
period: 3m
- name: mem_usage_max_avg_1h
period: 15m
- name: mem_usage_max_avg_1d
period: 3h

Filter 策略

用户可以在 Filter 策略中配置相关指标的阈值,若候选节点的当前负载数据超过了任一所配置的指标阈值,则这个节点将会被过滤,默认配置如下:

predicate:
## cpu usage
- name: cpu_usage_avg_5m
maxLimitPecent: 0.65
- name: cpu_usage_max_avg_1h
maxLimitPecent: 0.75
## memory usage
- name: mem_usage_avg_5m
maxLimitPecent: 0.65
- name: mem_usage_max_avg_1h
maxLimitPecent: 0.75

Score 策略

priority:
### score = sum((1 - usage) * weight) * MaxScore / sum(weight)
## cpu usage
- name: cpu_usage_avg_5m
weight: 0.2
- name: cpu_usage_max_avg_1h
weight: 0.3
- name: cpu_usage_max_avg_1d
weight: 0.5
## memory usage
- name: mem_usage_avg_5m
weight: 0.2
- name: mem_usage_max_avg_1h
weight: 0.3
- name: mem_usage_max_avg_1d
weight: 0.5

调度热点

在实际生产环境中,由于 Pod 创建成功以后,其负载并不会立马上升,这就导致了一个问题:

如果完全基于节点实时负载对 Pod 调度,常常会出现调度热点(短时间大量 pod 被调度到同一个节点上)。为了解决这个问题,我们设置了一个单列指标 Hot Vaule,用来评价某个节点在近段时间内被调度的频繁程度,对节点实时负载进行对冲。最终节点的 Priority 为上一小节中的 Score 减去 Hot Value。Hot Value 默认配置如下:

hotValue:
- timeRange: 5m
count: 5
- timeRange: 1m
count: 2

注:该配置表示,节点在 5 分钟内被调度 5 个 pod,或者 1 分钟内被调度 2 个 pod,HotValue 加 10 分。

方案一

方案一 在原来的调度器基础上增加调度器

Crane-scheduler

前提条件

1 [Prometheus]

(Crane-scheduler 会和Prometheus 交互获得真实的master node 节点信息 已获得真实调度)

配置规则

apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
name: example-record
labels:
prometheus: k8s
role: alert-rules
spec:
groups:
- name: cpu_mem_usage_active
interval: 30s
rules:
- record: cpu_usage_active
expr: 100 - (avg by (instance) (irate(node_cpu_seconds_total{mode="idle"}[30s])) * 100)
- record: mem_usage_active
expr: 100*(1-node_memory_MemAvailable_bytes/node_memory_MemTotal_bytes)
- name: cpu-usage-5m
interval: 5m
rules:
- record: cpu_usage_max_avg_1h
expr: max_over_time(cpu_usage_avg_5m[1h])
- record: cpu_usage_max_avg_1d
expr: max_over_time(cpu_usage_avg_5m[1d])
- name: cpu-usage-1m
interval: 1m
rules:
- record: cpu_usage_avg_5m
expr: avg_over_time(cpu_usage_active[5m])
- name: mem-usage-5m
interval: 5m
rules:
- record: mem_usage_max_avg_1h
expr: max_over_time(mem_usage_avg_5m[1h])
- record: mem_usage_max_avg_1d
expr: max_over_time(mem_usage_avg_5m[1d])
- name: mem-usage-1m
interval: 1m
rules:
- record: mem_usage_avg_5m
expr: avg_over_time(mem_usage_active[5m])
2 node_exporter

(搜集主机的内存 ,cpu 等信息)

部署步骤如下

k8s master 部署helm

tar zxvf helm-v3.5.4-linux-amd64.tar.gz 
cp -av linux-amd64//helm /usr/local/bin/

helm repo add crane https://gocrane.github.io/helm-charts
测试安装
helm install scheduler --debug --dry-run -n crane-system --create-namespace ./scheduler

# 先看下面报错点 再执行
helm install scheduler -n crane-system --create-namespace ./scheduler

报错点

以上部署过程可能遇到的问题

  1. repo 添加不上 或者 添加上了 charts 包 无法下载: 解决办法
找到官网,手动下载charts 包 上传charts 包  scheduler-0.2.0.tgz

上传服务器 解压 修改参数

判断

语句注释 : >=1.18.0 使用0.0.20

安装

测试安装
helm install scheduler --debug --dry-run -n crane-system --create-namespace ./scheduler

正式安装
helm install scheduler -n crane-system --create-namespace ./scheduler

安装后验证

观察日志
kubectl  get pod -n crane-system


kubectl logs -f crane-scheduler-controller-76864b76fb-rc4mz -n crane-system
观察节点
kubectl  get node
kubectl describe node zcsnode1

发布测试pod

[root@zcsmaster1 /]# cat /root/nginx.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
creationTimestamp: null
labels:
app: nginx3
name: nginx3
spec:
replicas: 1
selector:
matchLabels:
app: nginx3
strategy: {}
template:
metadata:
creationTimestamp: null
labels:
app: nginx3
spec:
schedulerName: crane-scheduler
containers:
- image: nginx:1.20.1
name: nginx
resources:
requests:
memory: "100Mi"
cpu: "1"
limits:
memory: "200Mi"
cpu: "2"
发布命令
kubectl  apply  -f /root/nginx.yaml
验证pod命令
kubectl  get pod 
kubectl describe pod nginx3-56696bd67-9dv82

如下可以看到 crane-scheduler 表示第二调度器安装成功
危险性
需要保证 新调度的稳定性 ,以及后台 promethes 稳定。(promethes 宕机 也可以调度)

当新调度器 丢失 。 使用新调度器发布的pod ,出现问题,将无法调度

================================================

方案二

对默认的调度器进行替换: 集群中保留一种调度器

前提条件

(如何部署,将在后面推出)

1 [Prometheus]

(Crane-scheduler 会和Prometheus 交互获得真实的master node 节点信息 已获得真实调度)

配置规则

apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
name: example-record
labels:
prometheus: k8s
role: alert-rules
spec:
groups:
- name: cpu_mem_usage_active
interval: 30s
rules:
- record: cpu_usage_active
expr: 100 - (avg by (instance) (irate(node_cpu_seconds_total{mode="idle"}[30s])) * 100)
- record: mem_usage_active
expr: 100*(1-node_memory_MemAvailable_bytes/node_memory_MemTotal_bytes)
- name: cpu-usage-5m
interval: 5m
rules:
- record: cpu_usage_max_avg_1h
expr: max_over_time(cpu_usage_avg_5m[1h])
- record: cpu_usage_max_avg_1d
expr: max_over_time(cpu_usage_avg_5m[1d])
- name: cpu-usage-1m
interval: 1m
rules:
- record: cpu_usage_avg_5m
expr: avg_over_time(cpu_usage_active[5m])
- name: mem-usage-5m
interval: 5m
rules:
- record: mem_usage_max_avg_1h
expr: max_over_time(mem_usage_avg_5m[1h])
- record: mem_usage_max_avg_1d
expr: max_over_time(mem_usage_avg_5m[1d])
- name: mem-usage-1m
interval: 1m
rules:
- record: mem_usage_avg_5m
expr: avg_over_time(mem_usage_active[5m])

2 node_exporter

(搜集主机的内存 ,cpu 等信息)

3 卸载方案一部署的调度器

helm list -A

helm unistall scheduler -n crane-system

master 节点

  1. 备份 /etc/kubernetes/manifests/kube-scheduler.yaml
  2. cp /etc/kubernetes/manifests/kube-scheduler.yaml /etc/kubernetes/
  3. 修改 kube-scheduler 的配置文件以启用动态调度程序插件并配置插件参数:scheduler-config.yaml
cp /etc/kubernetes/manifests/kube-scheduler.yaml /etc/kubernetes/
cp -r /etc/kubernetes/ /etc/kubernetes_bak

cd /etc/kubernetes/manifests

修改默认kube-scheduler.yaml

[root@zcsmaster1 manifests]# cat kube-scheduler.yaml
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
component: kube-scheduler
tier: control-plane
name: kube-scheduler
namespace: kube-system
spec:
containers:
- command:
- /scheduler
- --authentication-kubeconfig=/etc/kubernetes/scheduler.conf
- --authorization-kubeconfig=/etc/kubernetes/scheduler.conf
- --bind-address=192.168.40.180
#KubeSchedulerConfiguration文件在容器中的路径
- --config=/etc/kubernetes/scheduler-config.yaml
- --leader-elect=true
image: docker.io/gocrane/crane-scheduler:0.0.20
imagePullPolicy: IfNotPresent
livenessProbe:
failureThreshold: 8
httpGet:
host: 192.168.40.180
path: /healthz
port: 10259
scheme: HTTPS
initialDelaySeconds: 10
periodSeconds: 10
timeoutSeconds: 15
name: kube-scheduler
resources:
requests:
cpu: 100m
startupProbe:
failureThreshold: 24
httpGet:
host: 192.168.40.180
path: /healthz
port: 10259
scheme: HTTPS
initialDelaySeconds: 10
periodSeconds: 10
timeoutSeconds: 15
volumeMounts:
- mountPath: /etc/kubernetes
name: kubeconfig
hostNetwork: true
priorityClassName: system-node-critical
volumes:
- hostPath:
path: /etc/kubernetes/
type: Directory
name: kubeconfig
status: {}

修改 policy.yaml

/etc/kubernetes



[root@zcsmaster1 kubernetes]# cat policy.yaml
apiVersion: scheduler.policy.crane.io/v1alpha1
kind: DynamicSchedulerPolicy
spec:
syncPolicy:
##cpu usage
- name: cpu_usage_avg_5m
period: 15s
- name: cpu_usage_max_avg_1h
period: 15s
- name: cpu_usage_max_avg_1d
period: 15s
##memory usage
- name: mem_usage_avg_5m
period: 15s
- name: mem_usage_max_avg_1h
period: 15s
- name: mem_usage_max_avg_1d
period: 15s

predicate:
##cpu usage
- name: cpu_usage_avg_5m
maxLimitPecent: 0.65
- name: cpu_usage_max_avg_1h
maxLimitPecent: 0.75
##memory usage
- name: mem_usage_avg_5m
maxLimitPecent: 0.65
- name: mem_usage_max_avg_1h
maxLimitPecent: 0.75

priority:
##cpu usage
- name: cpu_usage_avg_5m
weight: 0.2
- name: cpu_usage_max_avg_1h
weight: 0.3
- name: cpu_usage_max_avg_1d
weight: 0.5
##memory usage
- name: mem_usage_avg_5m
weight: 0.2
- name: mem_usage_max_avg_1h
weight: 0.3
- name: mem_usage_max_avg_1d
weight: 0.5

hotValue:
- timeRange: 5m
count: 5
- timeRange: 1m
count: 2

修改scheduler-config.yaml

[root@zcsmaster1 kubernetes]# cat scheduler-config.yaml
apiVersion: kubescheduler.config.k8s.io/v1beta1
kind: KubeSchedulerConfiguration
leaderElection:
leaderElect: true
clientConnection:
kubeconfig: /etc/kubernetes/scheduler.conf
profiles:
- schedulerName: default-scheduler
plugins:
filter:
enabled:
- name: Dynamic
score:
enabled:
- name: Dynamic
weight: 3
pluginConfig:
- name: Dynamic
args:
policyConfigPath: /etc/kubernetes/policy.yaml

部署控制器

git clone https://github.com/gocrane/crane-scheduler.git

修改命名空间
kubectl apply -f ./deploy/controller/rbac.yaml && kubectl apply -f ./deploy/controller/deployment.yaml

查看日志

调度器日志

控制器日志

观察节点

###


标签:avg,name,5m,scheduler,usage,Crane,k8s,cpu
From: https://blog.51cto.com/zhaochengsheng/5908698

相关文章

  • k8s配置存储(ConfigMap、Secret)
    配置存储ConfigMapConfigMap是一种比较特殊的存储卷,它的主要作用是用来存储配置信息的。创建configmap.yaml,内容如下:apiVersion:v1kind:ConfigMapmetadata:nam......
  • Kubernetes(K8S) helm chart
    感觉和放到一个yaml文件中,用----分隔,操作繁琐程度上,没有太大区别创建自定义Chart#创建自定义的chart名为mychart[root@k8smaster~]#helmcreatemychartCre......
  • k8s-nfs
    nfs.servernfs服务器helmrepoaddnfs-subdir-external-provisionerhttps://kubernetes-sigs.github.io/nfs-subdir-external-provisioner/helminstallnfs-subdir......
  • 批处理及有状态等应用类型在 K8S 上应该如何配置?
    众所周知,Kubernetes(K8S)更适合运行无状态应用,但是除了无状态应用.我们还会有很多其他应用类型,如:有状态应用,批处理,监控代理(每台主机上都得跑),更复杂的应用......
  • K8S核心技术
    一、命令行工具Kubectlkubectl是Kubernetes集群的命令行工具,通过kubectl能够对集群本身进行管理,并能够在集群上进行容器化应用的安装部署1、基本语法kubectl[co......
  • [k8s] 删除Terminating状态的namespace
    ns=ingress-nginxkubectlgetnamespace$ns-ojson>tmp.jsonkubectlproxy--port=8081另起一个连接curl-k-H"Content-Type:application/json"-XPUT--data......
  • Kubernetes(K8S) helm 安装
    Helm是一个Kubernetes的包管理工具,就像Linux下的包管理器,如yum/apt等,可以很方便的将之前打包好的yaml文件部署到kubernetes上。Helm有3个重要概念:helm......
  • K8S-service介绍
    Service介绍在kubernetes中,pod是应用程序的载体,我们可以通过pod的ip来访问应用程序,但是pod的ip地址不是固定的,这也就意味着不方便直接采用pod的ip对服务进行访问。为了解......
  • k8s高级存储(PV、PVC)
    高级存储前面已经学习了使用NFS提供存储,此时就要求用户会搭建NFS系统,并且会在yaml配置nfs。由于kubernetes支持的存储系统有很多,要求客户全都掌握,显然不现实。为了能够屏......
  • Kubeadm高可用安装k8s集群-补充说明
    1.1k8s1.24管理用户无token处理1.24版本及以上关闭了自动生成admin-user-token的配置[root@k8s-master01dashboard]#kubectl-nkube-systemgetsecret|grepadmi......