Descheduler 实现 K8S Pod 二次调度
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Descheduler 实现 K8S Pod 二次调度相关的知识,希望对你有一定的参考价值。
参考技术AKubernetes中的调度是将待处理的pod绑定到节点的过程,由Kubernetes的一个名为 kube-scheduler 的组件执行。调度程序的决定,无论是否可以或不能调度容器,都由其可配置策略指导,该策略包括一组规则,称为 谓词 和 优先级 。调度程序的决定受到其在第一次调度时出现新pod时的Kubernetes集群视图的影响。由于Kubernetes集群非常动态且状态随时间而变化,因此可能需要将已经运行的pod重新调试到其它节点上,已达到节点使用资源平衡。
kube-scheduler 是 Kubernetes 集群的默认调度器,并且是集群 控制面 的一部分。
对每一个新创建的 Pod 或者是未被调度的 Pod,kube-scheduler 会选择一个最优的 Node 去运行这个 Pod。然而,Pod 内的每一个容器对资源都有不同的需求,而且 Pod 本身也有不同的资源需求。因此,Pod 在被调度到 Node 上之前,根据这些特定的资源调度需求,需要对集群中的 Node 进行一次过滤。
在一个集群中,满足一个 Pod 调度请求的所有 Node 称之为 可调度节点 。如果没有任何一个 Node 能满足 Pod 的资源请求,那么这个 Pod 将一直停留在未调度状态直到调度器能够找到合适的 Node。
调度器先在集群中找到一个 Pod 的所有可调度节点,然后根据一系列函数对这些可调度节点打分,然后选出其中得分最高的 Node 来运行 Pod。之后,调度器将这个调度决定通知给 kube-apiserver,这个过程叫做 绑定 。
在做调度决定时需要考虑的因素包括:单独和整体的资源请求、硬件/软件/策略限制、亲和以及反亲和要求、数据局域性、负载间的干扰等等。
kube-scheduler 给一个 pod 做调度选择包含两个步骤:
因此,可能会在群集中不太理想的节点上安排多个pod。 Descheduler 根据其政策,发现可以移动并移除它们的pod。请注意,在当前的实现中,Descheduler 不会安排更换被驱逐的pod,而是依赖于默认的调度程序。
这就是本文想讲的 Descheduler 项目,根据该项目二次调度策略来解决上面所说的问题。具体策略说明如下:
该策略确保只有一个Pod与在同一节点上运行的副本集(RS),Replication Controller(RC),Deployment或Job相关联。如果还有更多,则将这些重复的容器逐出,以更好地在群集中扩展容器。如果某些节点由于任何原因而崩溃,并且它们上的Pod移至其他节点,导致多个与RS或RC关联的Pod(例如在同一节点上运行),则可能发生此问题。一旦出现故障的节点再次准备就绪,便可以启用此策略以驱逐这些重复的Pod。当前,没有与该策略关联的参数。要禁用此策略,策略应如下所示:
该策略发现未充分利用的节点,并且如果可能的话,从其他节点驱逐pod,希望在这些未充分利用的节点上安排被驱逐的pod的重新创建。此策略的参数配置在 nodeResourceUtilizationThresholds 。
节点的利用率低是由可配置的阈值决定的 thresholds 。 thresholds 可以按百分比为cpu,内存和pod数量配置阈值 。如果节点的使用率低于所有(cpu,内存和pod数)的阈值,则该节点被视为未充分利用。目前,pods的请求资源需求被考虑用于计算节点资源利用率。
还有另一个可配置的阈值, targetThresholds 用于计算可以驱逐pod的潜在节点。任何节点,所述阈值之间, thresholds 并且 targetThresholds 被视为适当地利用,并且不考虑驱逐。阈值 targetThresholds 也可以按百分比配置为cpu,内存和pod数量。
这些阈值 thresholds 和 targetThresholds 可以根据您的集群要求进行调整。这是此策略的策略示例:
与该 LowNodeUtilization 策略相关的另一个参数称为 numberOfNodes 。仅当未充分利用的节点数大于配置的值时,才可以配置此参数以激活策略。这在大型群集中很有用,其中一些节点可能会频繁使用或短期使用不足。默认情况下, numberOfNodes 设置为0。
该策略可确保从节点中删除违反Interpod反亲和关系的pod。例如,如果某个节点上有 podA ,并且 podB 和 podC (在同一节点上运行)具有禁止它们在同一节点上运行的反亲和规则,则 podA 将被从该节点逐出,以便 podB 和 podC 正常运行。当 podB 和 podC 已经运行在节点上后,反亲和性规则被创建就会发送这样的问题。目前,没有与该策略关联的参数。要禁用此策略,策略应如下所示:
此策略可确保从节点中删除违反节点关联的pod。例如,在nodeA上调度了podA,它在调度时满足节点关联性规则 requiredDuringSchedulingIgnoredDuringExecution ,但随着时间的推移,nodeA不再满足该规则,那么如果另一个节点nodeB可用,它满足节点关联性规则,那么podA将被逐出nodeA。策略文件如下所示:
该策略可以确保从节点中删除违反 NoSchedule 污点的 Pod 。例如,有一个名为 podA 的 Pod ,通过配置容忍 key=value:NoSchedule 允许被调度到有该污点配置的节点上,如果节点的污点随后被更新或者删除了,则污点将不再被 Pod 的容忍满足,然后将被驱逐,策略文件如下所示:
当 Descheduler 程序决定从节点驱逐 Pod 时,它采用以下常规机制:
Descheduler 可以在k8s集群中作为 Job 或 CronJob 运行。它的优点是可以多次运行而无需用户干预。该调度程序容器在 kube-system 命名空间中作为关键容器运行,以避免被自身或kubelet逐出。
例如:
Kubernetes组件_Scheduler_02_二次调度
文章目录
一、前言
Descheduler所有资料:https://www.syjshare.com/res/V2RS2PUM
二、二次调度/运行期间调度Descheduler
2.1 机器上安装helm
小结精简命令:
1.helm包下载地址:
wget https://get.helm.sh/helm-v3.7.1-linux-amd64.tar.gz
2.解压 && 移动到 /usr/bin 目录下:
tar -xvf helm-v3.7.1-linux-amd64.tar.gz && cd linux-amd64/ && mv helm /usr/bin
3.执行 helm 显示如下说明安装成功:
#查看版本
helm version
2.2 每个机器都要准备好镜像
每个机器都要准备好镜像
这里笔者将镜像放到自己的阿里云镜像仓库,并公开权限,读者只需要下载就好了
vi /etc/hosts
47.95.181.38 registry.cn-beijing.aliyuncs.com
docker pull registry.cn-beijing.aliyuncs.com/dadfdafsd/descheduler:v0.25.0
docker tag registry.cn-beijing.aliyuncs.com/dadfdafsd/descheduler:v0.25.0 registry.k8s.io/descheduler/descheduler:v0.25.0
docker images | grep descheduler
2.3 使用helm部署
descheduler-master的源代码也有,需要的那个上面提供了,镜像无法修改源代码,这里打成这个镜像的压缩包也有
helm install releaseName mychartName
helm install descheduler descheduler ( 第一个 descheduler 是helm对象名,第二个descheduler 是mychart名称,也就是目录名)
kubectl get all -A
kubectl get configmap -A
kubectl get clusterrole -A
kubectl get clusterrolebinding -A
查询kubectl get all -A,如下:
k8s中,查看机器硬件使用情况的两条命令
# 查看集群所有机器的硬件资源使用情况 (这个top命令必须安装metrics-server才能使用)
kubectl top nodes
# 查看集群内指定机器的硬件资源使用情况 (一般还是使用这个,describe node命令没有限制)
kubectl describe node xxx
三、Descheduler需要注意的点(相关理论知识)
3.1 descheduler 调度策略
descheduler 调度策略:为了方便理解,可以类比apiserver的审计策略,表示哪些日志应该打印,这里表示那种情况需要被重调度。
查看官方仓库推荐的默认策略配置:
cat kubernetes/base/configmap.yaml
---
apiVersion: v1
kind: ConfigMap
metadata:
name: descheduler-policy-configmap
namespace: kube-system
data:
policy.yaml: |
apiVersion: "descheduler/v1alpha1"
kind: "DeschedulerPolicy"
strategies:
"RemoveDuplicates":
enabled: true
"RemovePodsViolatingInterPodAntiAffinity":
enabled: true
"LowNodeUtilization":
enabled: true
params:
nodeResourceUtilizationThresholds:
thresholds:
"cpu" : 20
"memory": 20
"pods": 20
targetThresholds:
"cpu" : 50
"memory": 50
"pods": 50
默认开启了 RemoveDuplicates、RemovePodsViolatingInterPodAntiAffinity、LowNodeUtilization 策略。我们可以根据实际场景需要进行配置。
descheduler 目前提供了如下几种调度策略:
-
RemoveDuplicates
驱逐同一个节点上的多 Pod -
LowNodeUtilization
查找低负载节点,从其他节点上驱逐 Pod -
HighNodeUtilization
查找高负载节点,驱逐上面的 Pod -
RemovePodsViolatingInterPodAntiAffinity
驱逐违反 Pod 反亲和性的 Pod -
RemovePodsViolatingNodeAffinity
驱逐违反 Node 反亲和性的 Pod -
RemovePodsViolatingNodeTaints
违反 NoSchedule 污点的 Pod -
RemovePodsViolatingTopologySpreadConstraint
驱逐违反拓扑域的 Pod -
RemovePodsHavingTooManyRestarts
驱逐重启次数太多的 Pod -
PodLifeTime
驱逐运行时间超过指定时间的 Pod -
RemoveFailedPods
驱逐失败状态的 Pod
3.2 descheduler 有哪些不足
3.2.1 基于 Request 计算节点负载并不能反映真实情况
在源码 https://github.com/kubernetes-sigs/descheduler/blob/028f205e8ccc49440bd52940eb78a737f8f5b824/pkg/descheduler/node/node.go#L253 中可以看到,descheduler 是通过合计 Node 上 Pod 的 Request 值来计算使用情况的。
这种方式可能并不太适合真实场景。如果能直接拿 metrics-server 或者 Prometheus 中的数据,会更有意义,因为很多情况下 Request、Limit 设置都不准确。有时,为了节约成本提高部署密度,Request 甚至会设置为 50m,甚至 10m。
3.2.2 驱逐 Pod 导致应用不稳定
descheduler 通过策略计算出一系列符合要求的 Pod,进行驱逐。好的方面是,descheduler 不会驱逐没有副本控制器的 Pod,不会驱逐带本地存储的 Pod 等,保障在驱逐时,不会导致应用故障。但是使用 client.PolicyV1beta1().Evictions 驱逐 Pod 时,会先删掉 Pod 再重新启动,而不是滚动更新。
在一个短暂的时间内,在集群上可能没有 Pod 就绪,或者因为故障新的 Pod 起不来,服务就会报错,有很多细节参数需要调整。
3.2.3 依赖于 Kubernetes 的调度策略
descheduler 并没有实现调度器,而是依赖于 Kubernetes 的调度器。这也意味着,descheduler 能做的事情只是驱逐 Pod,让 Pod 重新走一遍调度流程。如果节点数量很少,descheduler 可能会频繁的驱逐 Pod。
3.3 descheduler 有哪些适用场景
descheduler 的视角在于动态,其中包括两个方面:Node 和 Pod。Node 动态的含义在于,Node 的标签、污点、配置、数量等发生变化时。Pod 动态的含义在于,Pod 在 Node 上的分布等。
根据这些动态特征,可以归纳出如下适用场景:
(1) 新增了节点
(2) 节点重启之后
(3) 修改节点拓扑域、污点之后,希望存量的 Pod 也能满足拓扑域、污点
(4) Pod 没有均衡分布在不同节点
三、尾声
一般用不到,知道这个东西,会用,能跑起来就好,helm工程给出了,镜像也可以docker pull 到。
以上是关于Descheduler 实现 K8S Pod 二次调度的主要内容,如果未能解决你的问题,请参考以下文章
Kubernetes组件_Scheduler_02_二次调度
Kubernetes组件_Scheduler_02_二次调度
Kubernetes组件_Scheduler_02_二次调度