文章目录
前言
在复杂的 Kubernetes 集群中,不同应用对资源的需求和业务重要性各不相同。核心支付服务需要 100% 的可用性,而批量数据处理任务可以容忍延迟。当集群资源紧张时,如何确保关键业务优先获得资源?如何避免低优先级任务“挤占”高优先级服务的空间?
Kubernetes 的 Pod 优先级(Priority)与抢占(Preemption)机制 正是为解决这一问题而设计。它允许你为 Pod 赋予不同的“权重”,在资源不足时,让高优先级 Pod “挤掉”低优先级 Pod,实现智能的资源分配策略。
本文将深入剖析 PriorityClass、Pod 优先级设置、抢占流程及最佳实践,助你构建真正高可用、可预测的云原生应用架构。
一、为什么需要Pod优先级?
1.1 调度困境:公平≠合理
默认情况下,Kubernetes 调度器(kube-scheduler)遵循“先到先得”的原则。这看似公平,但在生产环境中可能引发严重问题:
- ❌ 核心服务被阻塞:一个大型批处理任务占满节点资源,导致新创建的订单服务 Pod 无法调度。
- ❌ 滚动更新失败:升级支付服务时,因资源不足,新版本 Pod 无法启动,旧版本又已终止,造成服务中断。
- ❌ 资源碎片化:小规格的高优先级 Pod 因找不到合适节点而 pending。
🎯 解决方案:引入“等级制度”——通过优先级明确业务重要性,让关键应用在资源竞争中胜出。
二、核心概念:PriorityClass 与 Pod Priority
2.1 PriorityClass:优先级的“定义模板”
PriorityClass 是集群级别的对象,用于定义一个优先级等级及其对应的整数值。
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
name: high-priority
value: 1000000 # 整数,值越大优先级越高
globalDefault: false # 是否作为全局默认值(谨慎使用)
description: "用于核心生产服务"
preemptionPolicy: PreemptLowerPriority # 抢占策略
2.2 内置优先级等级(建议)
| PriorityClass | Value | 用途 |
|---|---|---|
system-node-critical | 2000001000 | kubelet、容器运行时等节点关键组件 |
system-critical | 2000000000 | CoreDNS、etcd 等系统组件 |
high-priority | 1000000 | 核心生产应用(如支付、订单) |
medium-priority | 500000 | 普通生产应用 |
low-priority | 100000 | 测试、开发环境应用 |
| (无) | 0 | 默认优先级 |
✅ 建议:不要修改系统内置的
system-*PriorityClass。
2.3 在Pod中指定优先级
apiVersion: v1
kind: Pod
metadata:
name: critical-app
spec:
priorityClassName: high-priority # 引用 PriorityClass
containers:
- name: app
image: nginx
或直接设置 priority 字段(不推荐):
priority: 1000000
三、抢占机制:高优先级Pod的“入场权”
3.1 什么是抢占?
当高优先级 Pod 无法调度(因资源不足)时,调度器会尝试抢占(驱逐) 一个或多个低优先级 Pod,腾出资源以容纳高优先级 Pod。
3.2 抢占流程详解
3.3 抢占策略(preemptionPolicy)
| 策略 | 说明 |
|---|---|
PreemptLowerPriority(默认) | 允许抢占低优先级 Pod |
Never | 禁止抢占,即使资源不足也不驱逐其他 Pod |
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
name: batch-job
value: 10000
preemptionPolicy: Never # 批处理任务绝不抢占他人
四、真实场景与配置示例
4.1 场景1:保障核心服务升级
问题:支付服务滚动更新时,因集群资源紧张,新 Pod 无法创建。
解决方案:为支付服务设置高优先级。
# Deployment 片段
spec:
template:
spec:
priorityClassName: high-priority
containers:
- name: payment-service
image: payment:v2.0
✅ 当 v2 Pod 无法调度时,调度器会抢占低优先级 Pod(如测试任务),确保升级顺利完成。
4.2 场景2:防止批处理任务影响生产
问题:每日数据导出任务消耗大量资源,影响在线服务性能。
解决方案:为批处理任务设置低优先级且禁止抢占。
apiVersion: batch/v1
kind: Job
spec:
template:
spec:
priorityClassName: low-priority
preemptionPolicy: Never # 绝不干扰他人
containers:
- name: data-export
image: exporter:latest
resources:
requests:
cpu: "4"
memory: 8Gi
✅ 该任务只能在资源充足时运行,绝不会驱逐生产 Pod。
4.3 场景3:关键守护进程(DaemonSet)
某些 DaemonSet(如日志采集、监控代理)对节点至关重要,应设置高优先级。
apiVersion: apps/v1
kind: DaemonSet
spec:
template:
spec:
priorityClassName: system-node-critical # 使用系统最高优先级
containers:
- name: fluentd
image: fluentd:latest
✅ 确保关键守护进程永不被驱逐。
五、高级特性与最佳实践
5.1 多维度优先级设计
结合命名空间、应用类型、环境等因素设计优先级体系:
Priority:
System (2e9) >
Prod-Critical (1e6) >
Prod-General (5e5) >
Staging (2e5) >
Dev/CI (1e5)
5.2 与QoS协同工作
优先级与 QoS(服务质量)共同决定 Pod 的“生存能力”:
- 高优先级 + Guaranteed QoS:最稳定,最后被驱逐。
- 低优先级 + BestEffort QoS:最脆弱,优先被抢占或驱逐。
✅ 关键生产应用应同时配置高优先级和合理的资源请求/限制。
5.3 监控与告警
关键指标:
scheduler_elected_preemption_attempts_total:抢占尝试次数scheduler_preemption_victims:被抢占的 Pod 数量kube_pod_status_reason{reason="Preempted"}:被抢占的事件
🔔 建议:对频繁抢占设置告警,可能意味着集群资源不足或优先级设置不合理。
5.4 避免“优先级风暴”
- ❌ 不要为所有生产应用设置相同超高优先级。
- ✅ 合理分级,确保抢占行为可控。
- ⚠️ 谨慎使用
globalDefault,可能导致意外抢占。
六、调试与验证
6.1 查看Pod优先级
kubectl get pod <pod-name> -o jsonpath='{.spec.priority}'
kubectl describe pod <pod-name> | grep Priority
6.2 模拟抢占场景
# 1. 创建一个占用大量资源的低优先级 Pod
kubectl run stress-pod --image=busybox --requests='cpu=4,memory=8Gi' -- sleep 3600
# 2. 尝试创建高优先级 Pod
kubectl run critical-pod --image=nginx --priority-classname=high-priority
# 3. 观察 events
kubectl get events --sort-by=.metadata.creationTimestamp
预期:stress-pod 被驱逐,critical-pod 成功调度。
七、总结:优先级是调度的“指挥棒”
- PriorityClass 定义了集群的“等级制度”。
- Pod Priority 决定了其在资源竞争中的“话语权”。
- 抢占机制 确保高优先级应用在关键时刻获得资源。
🌟 记住:没有优先级管理的 Kubernetes 集群,就像没有交通规则的城市——看似自由,实则混乱。
通过合理的优先级设计,你不仅能保障核心业务的 SLA,还能优化资源利用率,实现关键任务与弹性计算的和谐共存。
如需获取更多关于Kubernetes性能调优、安全加固、多集群管理、GitOps实践、服务网格深度解析等进阶内容,请持续关注本专栏《云原生技术深度解析》系列文章。
214

被折叠的 条评论
为什么被折叠?



