Kubernetes:Kubernetes去调度器是什么?
我调查了一个名为Kubernetes Descheduler的组件,该组件正在Kubernetes孵化器中开发,用于重新调度Pod。本文基于v0.6.0时的信息进行撰写。
Kubernetes Descheduler 是什么?
由于 Kubernetes 调度器仅在创建 Pod 时进行调度,因此从长远来看存在以下问题。
-
- ノードのリソース使用率に偏りがでてしまう
-
- スケジュール後に taints, label などが変更されても、スケジュール済みの Pod には反映されない
- 新しくノードが追加されても、その時点では Pod は分散されない
Kubernetes Descheduler 通过删除已安排 Pod 并重新安排来解决此问题。Descheduler 仅负责删除 Pod,而重新安排由现有调度程序(kube-scheduler)完成。
值得注意的是,在本文撰写时(0.6.0版本),因为该软件仍在开发中,可能存在API的未经事先告知的变更等情况,因此尚未考虑将其用于生产环境1。Descheduler是sig-scheduling的子项目,在查阅SIG的会议记录后发现,在2018年6月21日的会议上,有计划将其升级为Kubernetes 1.12的标准组件。
请示范
以下是执行descheduler时Pod的行为。在一个由3个节点组成的集群中,最右边的节点首先通过kubectl drain命令将Pod迁移并设置为可调度状态。当执行descheduler时,可以观察到Pod从其他节点中移除,并且重新部署到空闲的右侧节点。
有三个紫色方块代表节点,一个绿色方块代表Pod。我们使用kube-ops-view来进行可视化。

我在本地环境中构建了 Kubernetes Descheduler,并对 Kubernetes 集群进行了以下操作:一旦 Pod 的重新配置(删除)完成,Descheduler 将停止运行。
$ descheduler --kubeconfig ~/.kube/config --policy-config-file ./policy.yaml -v 4
policy.yaml 文件已执行以下配置。在上述演示中,只设置了 DeschedulerPolicy(如下所述)。
apiVersion: "descheduler/v1alpha1"
kind: "DeschedulerPolicy"
strategies:
"RemoveDuplicates":
enabled: true
无关调度程序的策略
Descheduler 使用配置文件来定义删除 Pod 的策略,通过组合多个策略实现。目前有以下4种策略可供选择。
去重复
如果一个由相同的ReplicaSet和ReplicationController创建的Pod被部署在同一节点上,那么将删除该Pod。kube-scheduler默认包含了名为SelectorSpreadPriority的优先级,用于将Pod分散到不同的节点或区域上,以便Pod可以重新分散到节点上。
假设有一个属于同一 ReplicaSet 的 Pod (App1) 在 Node 1 上存在多个的情况下,删除其中一个 Pod,以使得 Pod 重新分配到 Node 3 上运行。在 Node 3 发生故障并恢复之后,可能会出现最初的情况。
# Initial state
| App1 | | App1 | | |
| App1 | | | | |
| | | | | |
| | | | | |
| | | | | |
+------+ +------+ +------+
Node1 Node2 Node3
# After descheduling
| App1 | | App1 | | App1 |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
+------+ +------+ +------+
Node1 Node2 Node3
节点利用率较低
这是一种旨在将资源利用率高的节点上的Pod重新调度到资源利用率较低的节点上的策略。通过使用CPU、RAM和Pod数量来定义阈值来确定资源的使用率。删除Pod后节点的资源使用率下限由targetThresholds设置,将Pod移动到的节点的利用率上限由阈值(thresholds)设置。两个阈值之间的节点不会对处理产生影响。
需要对 Pod 的 Resource Request 的值 (spec.containers[].resources.requests) 进行计算。基本操作是计算空闲节点的可用资源总和,并从资源较高的节点中删除相应数量的 Pod。
apiVersion: "descheduler/v1alpha1"
kind: "DeschedulerPolicy"
strategies:
"LowNodeUtilization":
enabled: true
params:
nodeResourceUtilizationThresholds:
thresholds:
"cpu" : 20
"memory": 20
"pods": 20
targetThresholds:
"cpu" : 50
"memory": 50
"pods": 50
删除违反跨 Pod 反亲和性规则的容器
删除与Pod之间的AntiAffinity规则相矛盾的Pod。Pod之间的AntiAffinity是指不希望具有特定标签的Pod在同一节点上进行调度。由于AntiAffinity只在调度时考虑,所以如果存在某种原因导致调度后不满足此规则的Pod存在,则进行删除操作。
移除违反节点亲和性的Pods
删除与节点的AntiAffinity不符的Pod。节点的Affinity是用于将Pod调度到特定类型的节点的功能。节点的指定使用标签,因此目前可能存在由于标签更改而不满足此规则的情况。
请说明执行的方法。
在README.md中,介绍了通过指定kubeconfig来从集群外执行的方法以及通过在集群内使用Job来执行的方法。由于执行二进制文件会删除相应的Pod并结束,目前来看,执行的时机似乎需要个人控制。
暂时移除Pod
Pod的撤离(删除)是根据以下规则进行的。Pod通过驱逐机制进行撤离,因此也考虑到PodDisruptionBudget的设置。
scheduler.alpha.kubernetes.io/critical-pod のアノテーションのついている Critical Pod は対象外
ReplicaSet、Job などで管理されていない Pod は再作成されないため対象外
DaemonSet が作成した Pod は対象外
Local Storage を利用したPod は対象外
Pod の QosClass にBestEffort を指定したものは Bustrable、Guaranteed より先に退避させられる
总结
使用Kubernetes Descheduler,可以对Pod进行重新调度。尽管基本功能已在0.6.0版本中实现,但由于仍在开发中,尚不推荐用于生产环境1。根据sig-scheduling团队的计划,希望在Kubernetes v1.12中将其升级为标准组件,因此对未来的动向抱有期待。
请参照以下内容并用中文进行本地化改述,只需一种选项:
引用
-
- GitHub – kubernetes-incubator/descheduler: Descheduler for Kubernetes
-
- Meet a Kubernetes Descheduler
- https://qiita.com/tkusumi/items/58fdadbe4053812cb44e