kube-scheduler
是 Kubernetes 中负责调度的组件,它本身的调度功能已经很强大了。但由于 Kubernetes 集群非常活跃,它的状态会随时间而改变,由于各种原因,你可能需要将已经运行的 Pod 移动到其他节点:
- 某些节点负载过高
- 某些资源对象被添加了 node 亲和性 或 pod (反)亲和性
- 集群中加入了新节点
一旦 Pod 启动之后 kube-scheduler
便不会再尝试重新调度它。根据环境的不同,你可能会有很多需要手动调整 Pod 的分布,例如:如果集群中新加入了一个节点,那么已经运行的 Pod 并不会被分摊到这台节点上,这台节点可能只运行了少量的几个 Pod,这并不理想,对吧?
Descheduler 如何工作?
Descheduler 会检查 Pod 的状态,并根据自定义的策略将不满足要求的 Pod 从该节点上驱逐出去。Descheduler 并不是 kube-scheduler
的替代品,而是要依赖于它。该项目目前放在 Kubernetes 的孵化项目中,还没准备投入生产,但经过我实验发现它的运行效果很好,而且非常稳定。那么该如何安装呢?
部署方法
你可以通过 Job
或 CronJob
来运行 descheduler。我已经创建了一个镜像 komljen/descheduler:v0.5.0-4-ga7ceb671
(包含在下面的 yaml 文件中),但由于这个项目的更新速度很快,你可以通过以下的命令创建你自己的镜像:
1 | ⚡ git clone https://github.com/kubernetes-incubator/descheduler |
然后打好标签 push 到自己的镜像仓库中。
通过我创建的 chart 模板,你可以用 Helm
来部署 descheduler,该模板支持 RBAC 并且已经在 Kubernetes v1.9 上测试通过。
添加我的 helm 私有仓库,然后部署 descheduler:
1 | ⚡ helm repo add akomljen-charts \ |
你也可以不使用 helm,通过手动部署。首先创建 serviceaccount 和 clusterrolebinding:
1 | # Create a cluster role |
然后通过 configmap
创建 descheduler 策略。目前只支持四种策略:
- RemoveDuplicates
RS、deployment 中的 pod 不能同时出现在一台机器上 - LowNodeUtilization
找到资源使用率比较低的 node,然后驱逐其他资源使用率比较高节点上的 pod,期望调度器能够重新调度让资源更均衡 - RemovePodsViolatingInterPodAntiAffinity
找到已经违反 Pod Anti Affinity 规则的 pods 进行驱逐,可能是因为反亲和是后面加上去的 - RemovePodsViolatingNodeAffinity
找到违反 Node Affinity 规则的 pods 进行驱逐,可能是因为 node 后面修改了 label
默认这四种策略全部开启,你可以根据需要关闭它们。下面在 kube-system
命名空间中创建一个 configmap:
1 | ⚡ cat << EOF| kubectl create -n kube-system -f - |
在 kube-system
命名空间中创建一个 CronJob,该 CroJob 每 30 分钟运行一次:
1 | ⚡ cat << EOF| kubectl create -n kube-system -f - |
当 CronJob 开始工作后,可以通过以下命令查看已经成功结束的 Pod:
1 | ⚡ kubectl get pods -n kube-system -a | grep Completed |
也可以查看这些 Pod 的日志,然后根据需要调整 descheduler 策略:
1 | ⚡ kubectl logs descheduler-1525521300-mrw4t -n kube-system |
哇哦,现在你的集群中已经运行了一个 descheduler!
总结
Kubernetes 的默认调度器已经做的很好,但由于集群处于不断变化的状态中,某些 Pod 可能运行在错误的节点上,或者你想要均衡集群资源的分配,这时候就需要 descheduler 来帮助你将某些节点上的 Pod 驱逐到正确的节点上去。我很期待正式版的发布!
参考文档:
- Meet a Kubernetes Descheduler