K8s 中的优先级与抢占调度机制

各位亲爱的Kubernetes爱好者们,大家好!我是你们的老朋友,人称“K8s百晓生”的程序猿老王。今天咱们要聊点高级货,聊聊K8s调度器里的“宫斗剧”——优先级与抢占调度。

想象一下,你是一位皇帝,手下有一群妃子(Pod),每个妃子都想得到你的宠幸(资源)。有的妃子出身高贵(优先级高),有的妃子默默无闻(优先级低)。如果皇帝的寝宫(节点)满了,谁能入住,谁要让位?这就是我们今天的主题:优先级与抢占调度。

一、为什么需要优先级与抢占?

在K8s的世界里,资源是有限的。节点上的CPU、内存、网络带宽等,就像皇宫里的床位,僧多粥少啊!没有优先级,所有Pod一视同仁,那就会出现以下问题:

  • 重要应用得不到保障: 想象一下,核心数据库和临时测试任务争夺资源,结果测试任务占满了CPU,数据库崩溃了,这还得了?
  • 资源利用率低下: 如果所有Pod都平等竞争,可能会出现某些节点负载过高,而另一些节点却闲置的情况。
  • 难以应对紧急情况: 比如,突发流量导致某个服务需要紧急扩容,如果没有优先级,新Pod可能无法及时启动,导致服务雪崩。

所以,我们需要一种机制,能够区分Pod的重要性,让重要的Pod优先获得资源,保障核心应用的稳定运行。这就是优先级与抢占机制的意义所在。

二、什么是优先级(Priority)?

优先级,顾名思义,就是给Pod贴上一个“重要性”的标签。这个标签决定了Pod在调度时的地位。优先级越高,Pod就越容易被调度到节点上。

在K8s中,优先级是通过PriorityClass对象来定义的。PriorityClass包含两个关键字段:

  • value: 一个整数值,代表优先级的大小。数值越大,优先级越高。
  • globalDefault: 一个布尔值,表示是否将该优先级作为集群的默认优先级。
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
  name: critical-priority
value: 1000000
globalDefault: false
description: "This priority class should be used for critical pods only."

这个例子定义了一个名为critical-priorityPriorityClass,其优先级值为1000000,并且不是全局默认优先级。

定义好PriorityClass后,就可以在Pod的spec中指定priorityClassName来使用它了。

apiVersion: v1
kind: Pod
metadata:
  name: critical-pod
  labels:
    app: critical-app
spec:
  containers:
  - name: critical-container
    image: nginx
  priorityClassName: critical-priority

这个例子中,critical-pod使用了critical-priority这个PriorityClass,因此具有很高的优先级。

优先级就像古代官场上的品级制度,一品大员自然比九品芝麻官更有话语权。 👑

三、什么是抢占(Preemption)?

有了优先级,还不够。如果所有节点都已经被低优先级的Pod占满了,高优先级的Pod怎么办?难道只能眼巴巴地等着?

这时候,抢占就派上用场了。抢占是指,当调度器找不到合适的节点来调度高优先级的Pod时,它可以“驱逐”一个或多个低优先级的Pod,从而释放资源,让高优先级的Pod得以运行。

抢占就像古代战争中的“清场”,为了迎接重要人物,先把无关人等赶走。 ⚔️

抢占的流程大概是这样的:

  1. 调度器发现一个高优先级的Pod无法被调度。
  2. 调度器开始评估哪些节点上的Pod可以被抢占。
  3. 调度器选择一个或多个低优先级的Pod进行驱逐。
  4. 被驱逐的Pod进入Pending状态,等待重新调度。
  5. 高优先级的Pod被调度到释放了资源的节点上。

四、抢占的注意事项和配置

抢占不是万能的,它也有一些限制和需要注意的地方:

  • preemptionPolicy: PodSpec 中可以设置 preemptionPolicy 来控制抢占行为。可选值为 PreemptLowerPriority (默认) 和 Never。设置为 Never 时,该 Pod 永远不会抢占其他 Pod,只能等待资源。
  • terminationGracePeriodSeconds: 被抢占的Pod会收到一个SIGTERM信号,然后优雅地关闭。terminationGracePeriodSeconds定义了Pod关闭的宽限期。如果Pod在宽限期内没有关闭,K8s会强制杀死它。
  • priorityClassName的选择: 要谨慎选择priorityClassName。如果过度使用高优先级,可能会导致低优先级的Pod永远无法被调度。
  • PodDisruptionBudget (PDB): PDB可以保护某些Pod不被意外驱逐。PDB可以定义允许同时被驱逐的Pod数量。
  • 节点亲和性和反亲和性: 节点亲和性和反亲和性会影响抢占的决策。调度器会尽量避免驱逐那些与高优先级Pod有亲和性关系的Pod。
  • 容忍度(Tolerations)和污点(Taints): 如果节点上设置了污点,只有具有相应容忍度的Pod才能被调度到该节点上。抢占也会受到污点和容忍度的影响。

五、抢占的配置示例

假设我们有一个节点,上面运行着一个低优先级的Pod和一个中等优先级的Pod。现在,我们想调度一个高优先级的Pod,并且允许它抢占低优先级的Pod。

首先,定义三个PriorityClass

apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
  name: low-priority
value: 100
globalDefault: false
---
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
  name: medium-priority
value: 500
globalDefault: false
---
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
  name: high-priority
value: 1000
globalDefault: false

然后,创建一个低优先级的Pod:

apiVersion: v1
kind: Pod
metadata:
  name: low-priority-pod
spec:
  containers:
  - name: low-priority-container
    image: nginx
  priorityClassName: low-priority

创建一个中等优先级的Pod:

apiVersion: v1
kind: Pod
metadata:
  name: medium-priority-pod
spec:
  containers:
  - name: medium-priority-container
    image: nginx
  priorityClassName: medium-priority

最后,创建一个高优先级的Pod:

apiVersion: v1
kind: Pod
metadata:
  name: high-priority-pod
spec:
  containers:
  - name: high-priority-container
    image: nginx
  priorityClassName: high-priority

当你创建high-priority-pod时,调度器会发现没有足够的资源来调度它。然后,调度器会评估哪些Pod可以被抢占。由于low-priority-pod的优先级最低,它会被驱逐,high-priority-pod会被调度到该节点上。

六、如何监控和调试抢占?

抢占是一个复杂的调度过程,需要进行监控和调试,以便及时发现和解决问题。

  • 查看Pod的事件: 可以使用kubectl describe pod <pod-name>命令查看Pod的事件,了解Pod是否被抢占,以及抢占的原因。
  • 查看调度器的日志: 调度器的日志包含了详细的调度信息,可以帮助你了解抢占的决策过程。
  • 使用Metrics Server和Prometheus: 可以使用Metrics Server和Prometheus等工具来监控集群的资源利用率和Pod的调度情况。
  • 模拟抢占场景: 可以使用kubectl drain命令模拟节点故障,然后观察高优先级Pod是否能够成功抢占资源。

七、优先级与抢占的“葵花宝典”

为了帮助大家更好地理解和应用优先级与抢占机制,我总结了一份“葵花宝典”,供大家参考:

项目 描述 注意事项
PriorityClass 定义Pod的优先级。 优先级值越大,优先级越高。
priorityClassName 在Pod的spec中指定PriorityClass 确保PriorityClass已经存在。
抢占(Preemption) 当高优先级的Pod无法被调度时,可以驱逐低优先级的Pod来释放资源。 抢占可能会导致服务中断,需要谨慎使用。
preemptionPolicy 控制抢占行为。PreemptLowerPriority (默认) 允许抢占, Never 禁止抢占。 根据实际需求选择合适的策略。
PDB 保护某些Pod不被意外驱逐。 PDB会限制抢占行为,需要合理配置。
监控与调试 通过查看Pod事件、调度器日志、Metrics Server和Prometheus等工具来监控和调试抢占。 及时发现和解决问题。

八、总结

优先级与抢占是K8s调度器中非常重要的机制,它们可以帮助我们更好地管理和利用集群资源,保障核心应用的稳定运行。

希望今天的讲解能够帮助大家更好地理解和应用优先级与抢占机制。记住,在K8s的世界里,掌握了优先级与抢占,就掌握了调度的“生杀大权”!

最后,祝大家在K8s的世界里玩得开心!😊

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注