在Kubernetes中,调度是指将Pod放置到合适的Node上,然后对应的Node上的Kubelet才能够运行这些pod。调度器通过Kubernetes的监测机制来发现集群中新创建且尚未被调度的Node上的Pod。K8s中默认的调度器是kube-scheduler, 当然,也可以自行实现一个自定义的调度器。
在开始之前,先来看几个相关的概念:
kubelet监控集群节点的CPU, 内存,磁盘空间和文件系统的inode等资源。当这些资源中的一个或多个达到特定的消耗水平,kubelet可以通过主动地使节点上一个或多个Pod失效,以回收资源防止资源不足。(当然,kubelet在终止最终用户Pod之前会尝试回收节点级资源。例如,它会在磁盘资源不足时删除未使用的容器镜像。当然这不在我们的考虑范围内。) 驱逐实质上是kubelet主动终止Pod以回收节点上资源的过程。
由kubelet发起的驱逐称为节点压力驱逐,这种方式下,如果使用了 软驱逐条件 kubelet会考虑配置的 eviction-max-pod-grace-period (驱逐宽限期), 如果使用了 硬驱逐条件 它会立即驱逐pod。
当然也可以通过API发起驱逐,API发起的驱逐通过Eviction API创建驱逐对象,由它来体面地中止Pod。API发起的驱逐将尊村你的PodDisruptionBudgets (干扰预算,即PDB) 和 terminationGracePeriodSeconds (pod生命周期)配置。
将pod调度到指定的Node上运行是一个比较复杂的过程,有几个概念需要介绍一下:
污点的effect值NoExecute会影响已经在节点上运行的Pod,此时
------------------------------------------------分割线-------------------------------------------------------------------------------------------------
下面是笔者关于descheduler的一次实验
先简单介绍一下,descheduler是由社区提供,用于支持多种策略的调度器,可以根据不同策略对pod进行二次调度,使得node的使用率更加均衡一些。descheduler本身也支持许多不同的调度策略。
社区提供了基于Helm, Kustomize等多种部署方式,这次实验采用的是手动部署的方式
kubectl create -f kubernetes/base/rbac.yaml 为descheduler授权针对要测试用的pod
1. 通过kubectl get pods -n 你的namespace -o wide 查看pod,确认确实有两个相同的pod都部署到了108节点上

2. 通过kubectl apply -f descheduler/kubernetes/cronjob/cronjob.yaml 开启descheduler的cronjob (cronjob 根据cron表达式指定的周期定期执行job,具体针对k8s来说,cronjob controller会定期创建对应的job pod)

此时的descheduler的配置为:

仅开启了RemoveDuplicates策略
3. 一段时间后再次通过kubectl get pods -n cloudadvisor-qa -o wide 查看pod,显示结果如下,发现原有pod已被驱逐并在105节点上重建

4. 通过 kubectl get jobs -n kube-system 找到当前cronjob创建的descheduler job, 然后再通过kubectl get pods -n kube-system -l job-name='jobname' 查看当前job所在的pod 注意-l 根据label选择的使用

5. 查看这个pod对应的日志,并搜索与我们要观察的oversold相关的部分(这里为了后续查看,已经导出为文件了)

这里可以看到descheduler先是发现了 duplicate的node节点,然后进行Adjusting feasible调整,并且可以看到驱逐的节点hkcl8正是刚刚我们在108创建的重复pod之一