1. 为什么需要Pod优先级与抢占机制
在Kubernetes集群中,资源竞争是常态。当集群资源不足时,默认的调度策略会导致所有Pod平等竞争资源,这在实际生产环境中会带来严重问题。想象一下,一个承载核心支付服务的Pod和一个后台日志收集的Pod同时申请资源,如果它们被平等对待,可能导致支付服务不可用而日志收集却正常运行——这显然不是我们想要的结果。
优先级和抢占机制的核心价值在于:
- 确保关键业务Pod能够优先获得资源
- 允许低优先级Pod在资源紧张时被优雅终止
- 提供资源分配的确定性策略
- 避免"饿死"高优先级工作负载
注意:启用优先级功能需要同时配置PriorityClass和启用PodPriority准入控制器,否则配置不会生效。这是很多初学者容易忽略的点。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. PriorityClass详解与配置实践
PriorityClass是定义Pod优先级的核心API对象。每个PriorityClass包含:
- 全局唯一的名称
- 优先级整数值(32位整数,越大优先级越高)
- 可选的描述字段
- 可选的globalDefault标志
典型配置示例:
yaml复制apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
name: high-priority
value: 1000000
globalDefault: false
description: "This priority class should be used for critical service pods only"
关键配置要点:
- value范围:通常建议系统级保留0-999999,用户自定义从1000000开始
- globalDefault:集群中只能有一个PriorityClass将此字段设为true
- 命名规范:建议使用类似"<环境>-<服务等级>"的命名方式,如prod-critical、dev-background等
实际使用中,我们通过Pod的spec.priorityClassName字段关联PriorityClass:
yaml复制apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- name: nginx
image: nginx
priorityClassName: high-priority
3. 抢占式调度的工作原理与流程
当kube-scheduler发现高优先级Pod因资源不足无法调度时,会触发抢占流程:
-
筛选阶段:
- 找出所有优先级低于待调度Pod的正在运行Pod
- 排除系统关键Pod(如kube-system命名空间下的Pod)
- 排除有preemptionPolicy: Never注解的Pod
-
候选节点评估:
- 对每个节点,计算如果抢占部分Pod后是否满足资源需求
- 选择抢占Pod数量最少的节点
- 如果多个节点条件相同,选择优先级总和最低的节点
-
优雅终止:
- 给被抢占Pod设置优雅终止期(默认30秒)
- 发送SIGTERM信号
- 超过宽限期后强制终止(SIGKILL)
-
调度执行:
- 等待目标节点资源释放
- 调度高优先级Pod
- 更新调度器缓存状态
重要细节:被抢占的Pod会进入Terminating状态,但可能被控制器(如Deployment)立即重新创建,这会导致抢占-重建循环。解决方法是为低优先级工作负载配置适当的PodDisruptionBudget。
4. 实战中的典型问题与解决方案
4.1 优先级配置不当导致的系统不稳定
常见错误模式:
- 过多Pod配置为高优先级,失去区分度
- 未为系统组件保留足够资源
- 优先级数值跳跃过大(如直接从100跳到1000000)
解决方案:
bash复制# 查看当前集群优先级分布
kubectl get pods --all-namespaces -o jsonpath='{range .items[*]}{.spec.priorityClassName}{"\t"}{.metadata.name}{"\n"}{end}' | sort | uniq -c
# 建议的优先级分段方案
0-99999 # 系统保留
100000-199999 # 关键业务
200000-299999 # 普通业务
300000-399999 # 批处理任务
400000+ # 最佳效果任务
4.2 抢占导致的服务中断
预防措施:
-
为关键Pod配置PodDisruptionBudget
yaml复制apiVersion: policy/v1 kind: PodDisruptionBudget metadata: name: zk-pdb spec: minAvailable: 2 selector: matchLabels: app: zookeeper -
使用affinity/anti-affinity分散Pod分布
yaml复制affinity: podAntiAffinity: requiredDuringSchedulingIgnoredDuringExecution: - labelSelector: matchExpressions: - key: app operator: In values: - store topologyKey: "kubernetes.io/hostname" -
合理设置terminationGracePeriodSeconds
yaml复制spec: terminationGracePeriodSeconds: 60 # 适当延长优雅退出时间
4.3 调度器性能问题
当集群规模较大时(如超过1000节点),抢占计算可能影响调度性能。优化方案:
-
调整kube-scheduler的percentageOfNodesToScore参数(默认50%)
yaml复制apiVersion: kubescheduler.config.k8s.io/v1beta3 kind: KubeSchedulerConfiguration profiles: - pluginConfig: - args: percentageOfNodesToScore: 30 name: DefaultPercentageOfNodesToScore -
分片调度(使用多个调度器)
yaml复制apiVersion: v1 kind: Pod metadata: name: foo spec: schedulerName: my-custom-scheduler # 使用自定义调度器 -
定期执行调度器性能分析
bash复制# 获取调度器性能指标 kubectl get --raw /metrics | grep scheduler_
5. 进阶场景与最佳实践
5.1 多维度优先级策略
对于复杂场景,可以组合使用:
- 常规PriorityClass
- QoS等级(Guaranteed/Burstable/BestEffort)
- ResourceQuota
- 自定义调度插件
示例架构:
code复制 +-------------------+
| Admission |
| Controller |
+--------+----------+
|
v
+-------------+ +--------+----------+ +----------------+
| Priority | | Resource Quota | | Custom |
| Class +-------> Enforcement +-------> Scheduler |
| Evaluation | | | | Plugins |
+-------------+ +-------------------+ +-------+--------+
|
v
+---------+-----------+
| Final |
| Scheduling Decision |
+---------------------+
5.2 优先级与垂直扩缩容(VPA)的协同
当同时使用优先级和VPA时,建议:
-
为VPA配置优先级感知
yaml复制apiVersion: autoscaling.k8s.io/v1 kind: VerticalPodAutoscaler metadata: name: my-app-vpa spec: targetRef: apiVersion: "apps/v1" kind: Deployment name: my-app updatePolicy: updateMode: "Auto" resourcePolicy: containerPolicies: - containerName: "*" minAllowed: cpu: "100m" memory: "50Mi" maxAllowed: cpu: "1" memory: "500Mi" controlledResources: ["cpu", "memory"] controlledValues: "RequestsOnly" -
监控指标关联
promql复制# 优先级与资源使用率关联查询 sum(rate(container_cpu_usage_seconds_total{container!="POD",container!=""}[5m])) by (pod,priority_class) / sum(kube_pod_container_resource_requests{resource="cpu"}) by (pod,priority_class)
5.3 混沌工程中的优先级测试
建议的测试方案:
- 压力测试工具(如kubemark)创建大量低优先级Pod
- 逐步提交高优先级Pod,观察抢占行为
- 监控关键指标:
- 调度延迟(scheduler_scheduling_duration_seconds)
- 抢占次数(scheduler_preemption_attempts_total)
- Pod启动耗时(kube_pod_start_time)
测试脚本示例:
bash复制# 创建低优先级负载
kubectl apply -f - <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
name: low-priority-load
spec:
replicas: 100
selector:
matchLabels:
app: low-priority
template:
metadata:
labels:
app: low-priority
spec:
containers:
- name: pause
image: k8s.gcr.io/pause:3.2
priorityClassName: low-priority
EOF
# 创建高优先级Pod并计时
time kubectl apply -f - <<EOF
apiVersion: v1
kind: Pod
metadata:
name: high-priority-test
spec:
containers:
- name: nginx
image: nginx
priorityClassName: high-priority
EOF
6. 监控与告警配置
6.1 关键监控指标
-
调度器指标:
scheduler_preemption_attempts_totalscheduler_pending_podsscheduler_scheduling_duration_seconds
-
Pod状态指标:
kube_pod_status_phase{phase="Pending"}kube_pod_status_ready{condition="false"}kube_pod_start_time
-
资源压力指标:
kube_node_status_allocatablekube_pod_container_resource_requests
6.2 推荐告警规则
yaml复制groups:
- name: PriorityScheduling
rules:
- alert: HighPriorityPodPending
expr: kube_pod_status_phase{phase="Pending"} * on(pod) group_left(priority_class) kube_pod_priority_class > 1000000
for: 5m
labels:
severity: critical
annotations:
summary: High priority pod {{ $labels.pod }} pending for more than 5 minutes
description: "Pod {{ $labels.pod }} with priority class {{ $labels.priority_class }} is pending"
- alert: FrequentPreemptions
expr: rate(scheduler_preemption_attempts_total[1h]) > 10
labels:
severity: warning
annotations:
summary: Cluster experiencing frequent pod preemptions
description: "Preemption rate is {{ $value }} per hour, check resource pressure"
6.3 可视化Dashboard配置
推荐Grafana面板包含:
-
优先级分布饼图
promql复制count by (priority_class) (kube_pod_info{priority_class!=""}) -
抢占时间序列
promql复制rate(scheduler_preemption_attempts_total[5m]) -
各优先级Pod资源满足率
promql复制sum(kube_pod_container_resource_requests{resource="cpu"}) by (priority_class) / sum(kube_node_status_allocatable{resource="cpu"}) * on() group_left() count(kube_pod_info{priority_class!=""}) by (priority_class)
7. 与其他调度特性的交互
7.1 与拓扑分布约束的协同
当Pod同时配置优先级和topologySpreadConstraints时,调度器会:
- 首先满足拓扑分布约束
- 在满足拓扑约束的节点中选择最适合抢占的节点
- 如果无法同时满足,根据preemptionPolicy决定是否放弃抢占
示例配置:
yaml复制apiVersion: v1
kind: Pod
metadata:
name: my-app
spec:
topologySpreadConstraints:
- maxSkew: 1
topologyKey: zone
whenUnsatisfiable: DoNotSchedule
labelSelector:
matchLabels:
app: my-app
priorityClassName: high-priority
7.2 与弹性伸缩的配合
优先级策略会影响HPA和Cluster Autoscaler的行为:
- HPA:高优先级Pod的资源请求会被优先保证
- Cluster Autoscaler:会考虑Pod优先级决定是否扩容
- 通过--expendable-pods-priority-cutoff参数设置可牺牲Pod的优先级阈值
- 低于此阈值的Pod所在节点可以被缩容
配置示例:
yaml复制apiVersion: autoscaling/v2beta2
kind: HorizontalPodAutoscaler
metadata:
name: my-app-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: my-app
minReplicas: 2
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 50
behavior:
scaleDown:
policies:
- type: Pods
value: 1
periodSeconds: 60
selectPolicy: Min
stabilizationWindowSeconds: 300
7.3 与批处理作业的集成
对于Job/CronJob,建议:
- 长时间运行的批处理任务使用中等优先级
- 关键批处理任务可以设置高优先级+preemptionPolicy: Never
- 使用ttlSecondsAfterFinished自动清理完成的Job
示例:
yaml复制apiVersion: batch/v1
kind: Job
metadata:
name: important-report
spec:
ttlSecondsAfterFinished: 86400 # 1天后自动删除
template:
spec:
priorityClassName: batch-medium
preemptionPolicy: Never # 禁止被抢占
containers:
- name: report-generator
image: report:latest
restartPolicy: OnFailure
