Kubernetes:默认调度器的优先级与Pod 抢占机制

本文涉及的产品
容器服务 Serverless 版 ACK Serverless,952元额度 多规格
容器服务 Serverless 版 ACK Serverless,317元额度 多规格
简介: Kubernetes:默认调度器的优先级与Pod 抢占机制

在本篇文章中,讲解一下 Kubernetes 调度器里的另一个重要机制,即:优先级(Priority )和抢占(Preemption)机制


首先需要明确的是,优先级和抢占机制,解决的是 Pod 调度失败时该怎么办的问题

正常情况下,当一个 Pod 调度失败后,它就会被暂时“搁置”起来,直到 Pod 被更新,或者集群状态发生变化,调度器才会对这个 Pod 进行重新调度。

但在有时候,我们希望的是这样一个场景。当一个高优先级的 Pod 调度失败后,该 Pod 并不会被“搁置”,而是会“挤走”某个 Node 上的一些低优先级的 Pod 。这样就可以保证这个高优先级 Pod 的调度成功。这个特性,其实也是一直以来就存在于 Borg 以及 Mesos 等项目里的一个基本功能。


而在 Kubernetes 里,优先级和抢占机制是在 1.10 版本后才逐步可用的。要使用这个机制,你首先需要在 Kubernetes 里提交一个 PriorityClass 的定义,如下所示:

apiVersion: scheduling.k8s.io/v1beta1
kind: PriorityClass
metadata:
  name: high-priority
value: 1000000
globalDefault: false
description: "This priority class should be used for high priority service pods only."


上面这个 YAML 文件,定义的是一个名叫 high-priority 的 PriorityClass,其中 value 的值是 1000000 (一百万)。


Kubernetes 规定,优先级是一个 32 bit 的整数,最大值不超过 1000000000(10 亿,1 billion),并且值越大代表优先级越高。而超出 10 亿的值,其实是被 Kubernetes 保留下来分配给系统 Pod 使用的。显然,这样做的目的,就是保证系统 Pod 不会被用户抢占掉。


而一旦上述 YAML 文件里的 globalDefault 被设置为 true 的话,那就意味着这个 PriorityClass 的值会成为系统的默认值。而如果这个值是 false,就表示我们只希望声明使用该 PriorityClass 的 Pod 拥有值为 1000000 的优先级,而对于没有声明 PriorityClass 的 Pod 来说,它们的优先级就是 0。


在创建了 PriorityClass 对象之后,Pod 就可以声明使用它了,如下所示:

apiVersion: v1
kind: Pod
metadata:
  name: nginx
  labels:
    env: test
spec:
  containers:
  - name: nginx
    image: nginx
    imagePullPolicy: IfNotPresent
  priorityClassName: high-priority

注意:PriorityClass是非namespace隔离的,是global的。因此metadata下面是不能设置namespace field的。

  • apiVersion: scheduling.k8s.io/v1alpha1 # enable的时候需要配置的runtime-config参数;
  • metadata.name: 设置PriorityClass的名字;
  • value: 32-bit 整型值,值越大代表优先级越高,但是必须小于等于 1 billion,大于 1 billion的值是给集群内的critical system Pods保留的,表示该Priority的Pod是不能被抢占的。
  • globalDefault: true or false,注意只能有一个PriorityClass的这个字段为true,如果没有一个PriorityClass的该字段为true,则那些没有明确引用PriorityClass的Pod的Priority value就为最低值0.
  • description: String,写给人看的备注,Kubernetes不做处理;

注意:

  • PriorityClass只会影响那些还没创建的Pod,一旦Pod创建完成,那么admission Controller就已经将Pod Spec中应用的PriorityClassName对应的PriorityClass的value设置到Pod的Priority field了。意味着你再修改PriorityClass的任何field,包括globalDefault,也不会影响已经创建完成的Pod。
  • 如果你删除某个PriorityClass,那么不会影响已经引用它的Pod Priority,但你不能用它来创建新的Pod了。这其实是显而易见的。


可以看到,这个 Pod 通过 priorityClassName 字段,声明了要使用名叫 high-priority 的 PriorityClass。当这个 Pod 被提交给 Kubernetes 之后,Kubernetes 的 PriorityAdmissionController 就会自动将这个 Pod 的 spec.priority 字段设置为 1000000。


而我在前面的文章中曾为你介绍过,调度器里维护着一个调度队列。所以,当 Pod 拥有了优先级之后,高优先级的 Pod 就可能会比低优先级的 Pod 提前出队,从而尽早完成调度过程。这个过程,就是“优先级”这个概念在 Kubernetes 里的主要体现。

而当一个高优先级的 Pod 调度失败的时候,调度器的抢占能力就会被触发。这时,调度器就会试图从当前集群里寻找一个节点,使得当这个节点上的一个或者多个低优先级 Pod 被删除后,待调度的高优先级 Pod 就可以被调度到这个节点上。这个过程,就是“抢占”这个概念在 Kubernetes 里的主要体现。


为了方便叙述,我接下来会把待调度的高优先级 Pod 称为“抢占者”(Preemptor)。

当上述抢占过程发生时,抢占者并不会立刻被调度到被抢占的 Node 上。事实上,调度器只会将抢占者的 spec.nominatedNodeName 字段,设置为被抢占的 Node 的名字。然后,抢占者会重新进入下一个调度周期,然后在新的调度周期里来决定是不是要运行在被抢占的节点上。这当然也就意味着,即使在下一个调度周期,调度器也不会保证抢占者一定会运行在被抢占的节点上。


这样设计的一个重要原因是,调度器只会通过标准的 DELETE API 来删除被抢占的 Pod,所以,这些 Pod 必然是有一定的“优雅退出”时间(默认是 30s)的。而在这段时间里,其他的节点也是有可能变成可调度的,或者直接有新的节点被添加到这个集群中来。所以,鉴于优雅退出期间,集群的可调度性可能会发生的变化,把抢占者交给下一个调度周期再处理,是一个非常合理的选择。


而在抢占者等待被调度的过程中,如果有其他更高优先级的 Pod 也要抢占同一个节点,那么调度器就会清空原抢占者的 spec.nominatedNodeName 字段,从而允许更高优先级的抢占者执行抢占,并且,这也就是得原抢占者本身,也有机会去重新抢占其他节点。这些,都是设置 nominatedNodeName 字段的主要目的。

参考链接:

https://my.oschina.net/jxcdwangtao/blog/1559580

http://docs.kubernetes.org.cn/769.html


相关实践学习
通过Ingress进行灰度发布
本场景您将运行一个简单的应用,部署一个新的应用用于新的发布,并通过Ingress能力实现灰度发布。
容器应用与集群管理
欢迎来到《容器应用与集群管理》课程,本课程是“云原生容器Clouder认证“系列中的第二阶段。课程将向您介绍与容器集群相关的概念和技术,这些概念和技术可以帮助您了解阿里云容器服务ACK/ACK Serverless的使用。同时,本课程也会向您介绍可以采取的工具、方法和可操作步骤,以帮助您了解如何基于容器服务ACK Serverless构建和管理企业级应用。 学习完本课程后,您将能够: 掌握容器集群、容器编排的基本概念 掌握Kubernetes的基础概念及核心思想 掌握阿里云容器服务ACK/ACK Serverless概念及使用方法 基于容器服务ACK Serverless搭建和管理企业级网站应用
目录
相关文章
|
22天前
|
Kubernetes API 调度
k8s中节点无法启动Pod
【10月更文挑战第3天】
61 6
|
22天前
|
存储 Kubernetes Perl
K8S中Pod启动异常
【10月更文挑战第3天】
48 2
|
24天前
|
应用服务中间件 调度 nginx
Kubernetes的Pod调度:让你的应用像乘坐头等舱!
Kubernetes的Pod调度:让你的应用像乘坐头等舱!
|
28天前
|
Kubernetes API 调度
k8s学习--pod的所有状态详解(图例展示)
k8s学习--pod的所有状态详解(图例展示)
|
24天前
|
JSON Kubernetes API
在K8S中,什么是静态Pod?
在K8S中,什么是静态Pod?
|
25天前
|
消息中间件 Java Kafka
Kafka ACK机制详解!
本文深入剖析了Kafka的ACK机制,涵盖其原理、源码分析及应用场景,并探讨了acks=0、acks=1和acks=all三种级别的优缺点。文中还介绍了ISR(同步副本)的工作原理及其维护机制,帮助读者理解如何在性能与可靠性之间找到最佳平衡。适合希望深入了解Kafka消息传递机制的开发者阅读。
102 0
|
25天前
|
Kubernetes 应用服务中间件 调度
k8s的Pod常见的几种调度形式
k8s的Pod常见的几种调度形式
18 0
|
28天前
|
Kubernetes 固态存储 调度
k8s学习--如何控制pod调度的位置
k8s学习--如何控制pod调度的位置
|
5天前
|
JSON Kubernetes 容灾
ACK One应用分发上线:高效管理多集群应用
ACK One应用分发上线,主要介绍了新能力的使用场景
|
6天前
|
Kubernetes 持续交付 开发工具
ACK One GitOps:ApplicationSet UI简化多集群GitOps应用管理
ACK One GitOps新发布了多集群应用控制台,支持管理Argo CD ApplicationSet,提升大规模应用和集群的多集群GitOps应用分发管理体验。

推荐镜像

更多