ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

K8S PriorityClass实战:从调度排队到抢占驱逐的CKA备考指南

K8S PriorityClass实战:从调度排队到抢占驱逐的CKA备考指南 做K8S一段时间后你会发现真正决定一个Pod能不能被快速调度出去的往往不是资源够不够而是调度器在资源紧张时的“排队规则”。PriorityClass这个对象平时不太起眼但在CKA考试里它频繁出现在Pod调度、抢占、驱逐相关的题目里。2025年新版CKA题库中PriorityClass相关题目几乎成了必考项而且题目风格从“让我创建个PriorityClass”变成了“模拟资源紧张场景验证高优先级Pod如何抢占低优先级Pod”。这篇文章围绕这个点把我搭建CKA备考练习环境时对PriorityClass的完整理解、实操过程和踩坑记录整理出来给正在备考的同学一条可复现的路径。PriorityClass解决的其实是一个很朴素的问题当集群资源不够时谁先调度谁靠后谁可以挤掉别人。默认情况下K8S里所有Pod的优先级是一样的调度器按队列顺序来处理。但生产环境里核心业务和批量任务通常需要差异化策略考试里更是直接把这个机制作为考点。理解PriorityClass不只是背一个API对象更要理顺它与调度队列、抢占策略、PodDisruptionBudget、节点压力驱逐之间的联动关系。这也是新版CKA题目越来越“场景化”的原因。我这套练习环境没有用复杂的多节点集群而是按照CKA考试环境的规格在本地用轻量方式模拟了一个可复现的沙箱专门用来反复试验PriorityClass的各类行为。下面我先把核心概念拆开再给你完整实操流程和排查思路尽量做到每个细节都能直接照着敲。1. 为什么CKA新题绕不开PriorityClass1.1 调度优先级不只是“谁先谁后”PriorityClass在K8S里的定位是全局调度策略对象它本身不直接运行任何容器而是通过给Pod打上优先级标记影响调度器的行为。可以把它理解成排队叫号系统里的“VIP号”号码数字越大越靠近队首而且当队伍占满时VIP号可以让普通号先离开把位置让出来。具体落地时调度器内部维护了多个调度队列Pod按PriorityClass的value值进入不同队列。value高的Pod调度时会先被调度器处理甚至在资源不足时触发抢占。这套机制在生产环境非常有用比如线上核心服务必须优先调度而离线批处理任务可以随时被挤掉。CKA考试不会只让你默写yaml它考察的是你能不能在实际集群环境里通过PriorityClass完成这种差异化的调度控制。还有一个容易忽略的点PriorityClass不仅影响调度还会影响节点压力驱逐。节点资源不足时kubelet会先驱逐低优先级的Pod优先保护高优先级Pod。新版CKA题目里有不少是围绕这个场景展开的如果你只盯着调度抢占而忽视驱逐环节很容易栽在细节上。1.2 2025新题里的典型考法结合近一年CKA的真题回顾和练习平台反馈PriorityClass相关题目主要分为三类第一类是基础创建题要求你创建指定名称、指定value的PriorityClass并新建或更新Pod关联它。这种题考察的是对API对象字段的熟悉程度属于送分题但创建时的参数、globalDefault的配置细节会成为拉开差距的地方。第二类是调度场景题创建一个低优先级Deployment占满所有可用资源再创建一个高优先级Pod观察它如何抢占低优先级Pod。这题就涉及抢占策略、Pod如何被终止、事件如何查看等一堆联动知识。第三类是策略判断或修复题给你一个已经存在的错误配置比如PriorityClass名称拼写错误、Pod的priorityClassName引用了不存在的类让你定位并修复。这类题目最能考察实际动手时的排查能力也是很多考生丢分的地方。我的建议是备考时不要只看题要在练习环境里把三种场景都完整跑几遍。考试时你才能不看文档就写出正确的yaml也能在看到Pod一直Pending时第一时间反应过来是优先级配置出了问题。2. 动手搭环境PriorityClass核心概念与准备2.1 PriorityClass对象到底长什么样先看一个最基础的PriorityClass定义apiVersion: scheduling.k8s.io/v1 kind: PriorityClass metadata: name: high-priority value: 1000000 globalDefault: false description: 用于核心业务Pod的高优先级Class这里核心字段就四个apiVersion和kind是固定的注意版本是scheduling.k8s.io/v1不是v1beta1新版K8S已经全面使用v1。name是PriorityClass的唯一标识后续Pod的priorityClassName字段直接引用它。value是一个32位整数范围是-2147483648到100000000010亿。超过10亿会被K8S拒绝这个边界值在考试场景里偶尔会考。globalDefault表示是否为未指定priorityClassName的Pod提供默认优先级但注意它不会影响已经指定了优先级的Pod。实际使用中最容易忽略的是value的数值选择。K8S官方建议用1到10亿之间的值考试里经常会让你设置为一个具体数字比如1000000你直接照抄即可。但如果题目没给值只有百分比或描述比如“配置最高优先级”那你就需要知道10亿是上限。还有一点系统默认内置了两个PriorityClasssystem-cluster-criticalvalue为2000000000但这个是系统保留类不能直接给业务Pod用。system-node-criticalvalue为2000001000大部分情况下只给kubelet、容器运行时等系统组件使用。这两个class在考试环境里存在但题目一般不会让你动它们。2.2 三个关键行为value、globalDefault、PreemptionPolicy先说value它决定Pod在调度队列中的位置。调度器把所有待调度的Pod按优先级从高到低排列如果两个Pod优先级相同再按时间先后排队。value越高越容易被调度器选中。再说globalDefault它的作用是给那些没有指定priorityClassName的Pod一个默认优先级。这里有个坑一个集群里只能有一个globalDefault为true的PriorityClass如果创建多个K8S会报错。而且即使你把某个PriorityClass设为globalDefault它也不会改变已经存在于集群中的、没有指定优先级的Pod只对新建的Pod生效。这个细节在题目里经常被用来设置“默认高优先级”坑点十足。最后是PreemptionPolicy这是CKA新题特别爱带出来的字段。它有两种取值PreemptLowerPriority默认和Never。默认情况下高优先级Pod在无法调度时会抢占低优先级Pod如果设置为Never高优先级Pod不会抢占只会排队等待资源释放。考试里如果明确说“不要抢占其他Pod”就要主动设置这个字段。很多同学在练习PriorityClass时只关注value大小忽略了PreemptionPolicy导致调度行为和自己预期不一样。我建议在练习环境里两个策略都建一遍对比事件日志感受一下两者在处理“资源不足”时的差别。2.3 准备一套可复现的练习环境CKA考试用的是K8S集群但备考时你不需要一上来就搭完整的多节点集群。我自己的做法是用轻量级方式快速起一个单节点集群重点在于能反复创建、清理资源方便测试各种调度行为。这里说一下我的练习环境规格系统层面Linux虚拟机或云主机均可2核4G起步低于这个配置做大规模的抢占实验会卡顿。K8S版本1.28及以上。新版本对调度和驱逐的日志输出更清晰也更贴近2025年CKA考试环境。网络插件准备一个可用的CNI插件否则Pod之间无法正常通信有些调度验证看不出来。命令行工具安装kubectl并配置好自动补全考试时能省一点时间。对于PriorityClass的实验单节点集群其实够用了。因为抢占和优先级调度主要是控制平面kube-scheduler的工作单节点也能触发。实验时建议准备以下脚本# 查看当前集群的调度器和节点状态 kubectl get nodes -o wide kubectl get pods -n kube-system | grep scheduler这一步不是废话。因为网上很多教程默认你已经有集群了但如果你本地环境连调度器日志都看不到后面排查问题时无从下手。我在实践过程中发现很多PriorityClass“不生效”的问题其实是集群版本或网络插件异常导致调度器根本没在正常工作。3. 实操过程与核心环节实现3.1 创建自定义PriorityClass并把Pod绑定上去实际操作的第一件事是创建一个高优先级PriorityClass。考试场景里题目可能会要求名称是critical-app、高优先级类value给一个具体数字比如1000000。下面是我在练习环境里的完整操作apiVersion: scheduling.k8s.io/v1 kind: PriorityClass metadata: name: critical-app value: 1000000 globalDefault: false description: 关键应用专用高优先级把上面内容保存为pc-critical.yaml然后执行kubectl apply -f pc-critical.yaml kubectl get priorityclass执行后你会看到类似下面的输出NAME VALUE GLOBAL-DEFAULT AGE critical-app 1000000 false 5s system-cluster-critical 2000000000 false 12d system-node-critical 2000001000 false 12d创建PriorityClass成功后再创建一个Pod并绑定这个类yaml如下apiVersion: v1 kind: Pod metadata: name: test-high-pod spec: priorityClassName: critical-app containers: - name: nginx image: nginx注意Pod的priorityClassName字段要和PriorityClass的metadata.name完全匹配。如果拼错创建Pod时会直接报错。创建成功后看Pod详情kubectl get pod test-high-pod -o yaml | grep -A 3 priority kubectl describe pod test-high-pod | grep -i priority在describe的输出里你会看到Priority和PriorityClassName字段已生效。到了这一步基础绑定就算是完成了但考试不仅仅考这个。3.2 模拟资源紧张观察高优先级Pod抢占低优先级Pod为了真正验证PriorityClass的调度抢占逻辑我建议你搭建一个“资源耗尽”的模拟场景。这个实验我在本地跑了不下十遍每遍都踩出一些新理解下面是一个标准复现流程。先创建一个低优先级的Deployment资源请求设置成和节点容量几乎一样大把节点资源占满。比如2核4G的节点我通常这样写apiVersion: apps/v1 kind: Deployment metadata: name: low-priority-app labels: app: low-priority-app spec: replicas: 2 selector: matchLabels: app: low-priority-app template: metadata: labels: app: low-priority-app spec: priorityClassName: low-priority containers: - name: busybox image: busybox command: [sh, -c, while true; do echo hello; sleep 5; done] resources: requests: cpu: 1 memory: 1Gi在创建之前先建好对应的low-priority PriorityClassvalue设为100低于critical-app。这样两个Pod的优先级差异就拉开了。把低优先级Deployment调度上去后节点资源基本耗尽。接着创建那个critical-app的Podkubectl apply -f test-high-pod.yaml kubectl get pods -o wide正常情况下高优先级Pod会进入Pending状态一小段时间然后调度器触发抢占终止部分低优先级Pod释放资源再调度高优先级Pod。用下面命令确认抢占过程kubectl get events --sort-by.metadata.creationTimestamp | tail -20 kubectl describe pod test-high-pod事件里会出现类似“preempting”的关键字。这时候你就能清楚看到高优先级Pod把低优先级Pod挤走了。这个过程非常直观尤其配合kubectl get pods -o wide观察低优先级Pod如何变成Terminating。3.3 验证PreemptionPolicyNever的效果PreemptionPolicyNever这个配置是将高优先级Pod设为“不抢占”但依然保有调度顺序的优先级。在实际生产环境里有一些追求稳定性的团队会这么用因为抢占毕竟会中断低优先级业务不是所有场景都适合暴力抢占。测试方法很简单创建另一个PriorityClass把PreemptionPolicy设为NeverapiVersion: scheduling.k8s.io/v1 kind: PriorityClass metadata: name: critical-app-no-preempt value: 1000000 preemptionPolicy: Never然后创建Pod并绑定这个class。在节点资源仍然被低优先级Pod占满的情况下高优先级Pod会一直处于Pending而不会触发抢占。通过kubectl describe查看事件你会发现它只提示“资源不足等待调度”完全没有抢占行为。这个对比实验特别重要。因为CKA新题里有不少题目会给你一段“看似高优先级”的配置但preemptionPolicy设置错误结果导致Pod无法抢占要求你修复。你在练习环境里跑过一次考试时一眼就能分辨。3.4 节点压力驱逐里的优先级别忽略除了调度抢占PriorityClass还影响节点压力驱逐的顺序。kubelet在节点内存或磁盘不足时会按优先级从低到高驱逐Pod。这个行为有一个前提Pod必须设置了对应的优先级且节点处于资源压力状态。在单节点环境里模拟节点压力有点麻烦因为要真把内存或磁盘耗尽。但CKA考试往往会给你一个高度仿真环境或者只是让你解释驱逐顺序。我在练习中验证过几种方案最靠谱的是用stress容器把内存压到接近Limit触发节点MemoryPressure然后观察低优先级Pod先被驱逐。apiVersion: v1 kind: Pod metadata: name: memory-stress spec: priorityClassName: low-priority containers: - name: stress image: polinux/stress command: [stress] args: [--vm, 1, --vm-bytes, 3G, --vm-hang, 1] resources: requests: memory: 3Gi limits: memory: 3Gi如果你的节点内存接近4G这个stress容器很容易把节点压到MemoryPressure。此时再创建一个高优先级且已经运行的Pod正常情况下它会保留低优先级Pod会被先驱逐掉。这个实验需要小心你的本地环境如果节点配置太低小心自己被卡死。我建议至少4G内存节点才尝试。4. 常见问题与排查技巧实录4.1 Pod一直Pending查PriorityClass没用这是我在备考群看到最多的问题也是我最初练PriorityClass时被卡住最久的地方。创建一个高优先级Pod后它一直Pendingunable去抢占。网上很多人搜到“no preemption victims found for incoming pod”这句日志然后一脸懵。这个日志的意思是调度器想要触发抢占但在目标节点上找不到可以被抢占的低优先级Pod。出现这种情况通常有四个原因节点上所有低优先级Pod都设置了PodDisruptionBudgetPDB并且PDB规则不允许被打断。低优先级Pod的优先级刚刚好和高优先级Pod是同一个PriorityClass或优先级值不低于它调度器认为它没有资格被抢占。要抢占的Pod运行在系统关键命名空间或者由于某种保护策略被排除在抢占范围外。节点上的低优先级Pod虽然存在但抢占动作会导致违反节点亲和性、拓扑分布约束等调度规则调度器判定这个节点不适合放置。排查方法很简单直接看调度器日志kubectl logs -n kube-system -l componentkube-scheduler --tail100或者直接查询事件kubectl get events --sort-by.lastTimestamp | grep -i preempt看到“no preemption victims found”这句再回到Pod所在的节点检查PDB就能准确找到原因。考试里如果遇到一个高优先级Pod一直Pending别只盯着PriorityClass查节点状态、PDB、资源富余度都要查一遍。4.2 创建多个globalDefault为true的PriorityClass会怎样集群里如果已经存在一个globalDefault为true的PriorityClass你再创建一个新的且也设置为trueK8S会直接拒绝。我在练习环境里遇到过这个情况提交yaml时报错提示“There can be only one global default priority class”。生产环境和考试里都有可能遇到这类场景。如果你想“备胎”一个默认类必须先把旧的globalDefault改成false再创建新的。不能同时有两个。另外删除globalDefault为true的PriorityClass后K8S不会自动把默认优先级回退到0因为系统没有兜底机制新建的Pod会使用默认值0即普通优先级。4.3 删除PriorityClass后引用它的Pod会怎样这个问题非常经典。如果一个PriorityClass被删除但集群里还有Pod的priorityClassName指向它那么这些Pod不会自动被删除它们会以原来的优先级继续运行直到重建。但有一个潜在风险如果Pod需要重新调度它就无法被调度器正确处理因为找不到对应的PriorityClass了。所以实际操作中删除PriorityClass前一定要先确认没有Pod引用它。可以用下面这个命令查找kubectl get pods -A -o custom-columnsNAMESPACE:.metadata.namespace,NAME:.metadata.name,PRIORITY:.spec.priorityClassName | grep priorityclass-name考试里出现这类修复题时常规解法是先重新创建PriorityClass再检查Pod状态。如果Pod已经处于异常状态直接删除重建即可。这里顺便说一句多容器Pod的生命周期和优先级调度也有关联如果一个Pod里有多个容器某个容器启动失败Pod整体不会进入Running状态优先级调度事件依然会触发但最终能否稳定运行还得看容器恢复情况。4.4 2C4G节点到底能跑多少Pod这个热搜词看起来和PriorityClass没有直接关系但它确实是CKA调度题里绕不开的问题。很多人想知道2核4G的节点能支撑多少Pod并发。官方默认的每节点Pod数量上限是110但实际取决于资源请求和系统组件消耗。如果用默认配置系统组件大约占用0.5核和1G内存剩下的资源分摊给业务Pod。假如每个Pod请求0.1核和128Mi内存那么理论上一个2C4G节点能跑大约20到30个Pod。但注意控制器、存储卷、网络插件都会占用一定资源实际肯定达不到理论上限。CKA考试里涉及Pod并发量时更关注的是你怎么合理设置资源request和limit而不是盲目追求Pod数量。PriorityClass在高并发调度中扮演的角色就是保证某些Pod在资源不足时仍然能快速调度进来所以我建议你在做这类实验时给测试Pod设置合理的resources否则部署批次一大节点可能瞬间被打爆。4.5 考试常用命令速查考前背熟能省时间CKA考试是允许查文档的但查文档的时间也是时间。把下面这些命令在练习环境里敲熟考试能节省不少宝贵的分钟。# 创建PriorityClass kubectl create priorityclass name --valuenumber --global-defaultfalse --descriptiondesc # 查看PriorityClass kubectl get priorityclass kubectl get priorityclass name -o yaml # 删除PriorityClass kubectl delete priorityclass name # 查看Pod优先级 kubectl get pod pod-name -o yaml | grep -i priority kubectl describe pod pod-name | grep -i priority # 查看调度器相关事件 kubectl get events --sort-by.metadata.creationTimestamp | tail -30这里有个小技巧kubectl create priorityclass命令可以直接用命令行参数创建不用写yaml非常适合考试时快速创建。但如果你需要设置preemptionPolicy为Never命令行创建就不太方便因为目前kubectl create priorityclass并没有直接的--preemption-policy参数还是建议用yaml。考前把yaml格式记牢比硬背命令行更稳。4.6 环境搭建常见坑版本差异和默认行为如果你用的K8S版本比较老比如1.20以下PriorityClass的行为和日志输出会和新版本有一些差异。新版K8S默认开启了PodPriority特性但老版本有时需要额外开启特性门控否则创建PriorityClass后Pod根本不识别。另一个常见坑是集群里存在多个控制面节点时kube-scheduler可能是多副本直接查kube-system命名空间下的scheduler日志时要注意确认你查的是当前正在工作的那个副本。用-l componentkube-scheduler这一招能省很多事。从备考环境搭建的角度来说不同平台的K8S部署方式也会影响PriorityClass实验效果。比如rocky等系统上二进制部署K8S和使用kubeadm部署对调度器日志和默认策略的影响不大但容器运行时不同会带来一些细微行为差异。我建议你始终在一个干净的环境里做实验避免因为历史资源残留而干扰结果。5. 我把这套实验连起来做了一遍几个心得供你参考PriorityClass从概念到实操其实连起来做一遍比看十篇教程都有用。我个人在练习环境里反复跑了几轮之后有三个比较深的感受。第一看事件日志是理解PriorityClass最直接的手段。无论是调度成功、抢占触发还是pod一直Pendingkubectl get events都能给出明确线索。不要一上来就翻调度器的源码先把事件看懂很多问题就解决了一大半。第二做抢占实验时一定要设置好资源请求。如果Pod不写resources.requests调度器可能会因为节点资源充足而直接调度根本不会触发抢占你也就看不到PriorityClass的威力。这个细节特别容易被新手忽略。第三在考试练习阶段把preemptionPolicy字段和各种优先级值组合都试一遍。不要只背yaml模板理解每个字段背后的调度语义考试时即使遇到完全没见过的场景也能根据原理推出来怎么改配置。另外搭建练习环境这件事如果你不想从零开始搭集群可以先用网上现成的模拟环境但我还是建议你在自己的虚拟机或云主机上完整部署一次。因为CKA考试用的是真实集群环境你对环境越熟悉考试时越不会慌。我自己的备考路线就是先本地起集群再逐步把调度、驱逐、网络策略这些高频考点都在上面过一遍最后刷题时才觉得游刃有余。最后再分享一个小技巧做PriorityClass实验时给每个PriorityClass和Pod都写清楚description和命名别用test1、test2这种无意义名称。你一旦开始做多组对比实验清晰的命名能让你少走不少弯路排查问题时也能一眼看出哪个是哪个。备考时间宝贵少一点无用功多一分从容这比熬夜刷题更有用。
返回列表