16.6.5 优先级与抢占

优先级与抢占用于保证关键业务在资源紧张时获得调度机会。Kubernetes 通过 PriorityClass 定义全局优先级,数值越大优先级越高,Pod 通过 priorityClassName 引用;globalDefault 可设定默认优先级。调度器在筛选与打分后,会优先考虑高优先级 Pod,并在必要时触发抢占。

原理草图(调度与抢占路径):

文章图片

安装/启用检查(PriorityClass 内置,无需额外安装):

# 确认集群版本支持(1.14+ 默认启用,1.8-1.13 需检查特性开关)
kubectl version --short

# 查看已存在的优先级类
kubectl get priorityclass

命令解释:
- kubectl version --short:确认 API Server 版本,评估是否需要启用特性门控。
- kubectl get priorityclass:列出现有优先级定义与数值。

PriorityClass 与 Pod 示例(含默认优先级):

# 文件:/opt/k8s/priority/high-priority.yaml
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
  name: high-priority
value: 100000
globalDefault: false
description: "关键业务优先级"

---
# 文件:/opt/k8s/priority/default-priority.yaml
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
  name: default-priority
value: 1000
globalDefault: true
description: "默认优先级"
# 文件:/opt/k8s/priority/app-high.yaml
apiVersion: v1
kind: Pod
metadata:
  name: app-high
spec:
  priorityClassName: high-priority
  containers:
  - name: nginx
    image: nginx:1.25
    resources:
      requests:
        cpu: "500m"
        memory: "256Mi"
# 应用配置并观察效果
kubectl apply -f /opt/k8s/priority/high-priority.yaml
kubectl apply -f /opt/k8s/priority/default-priority.yaml
kubectl apply -f /opt/k8s/priority/app-high.yaml

# 查看 Pod 实际优先级数值
kubectl get pod app-high -o jsonpath='{.spec.priority}{"\n"}'

命令解释:
- kubectl apply -f:创建/更新 PriorityClass 与 Pod。
- jsonpath='{.spec.priority}':返回 Pod 实际解析后的数值优先级。

抢占场景演示(低优先级批任务被驱逐):

# 文件:/opt/k8s/priority/low-batch.yaml
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
  name: low-batch
value: 10
globalDefault: false
description: "低优先级批处理"

---
apiVersion: v1
kind: Pod
metadata:
  name: batch-low
spec:
  priorityClassName: low-batch
  containers:
  - name: busybox
    image: busybox:1.36
    command: ["sh","-c","sleep 3600"]
    resources:
      requests:
        cpu: "1"
        memory: "512Mi"
kubectl apply -f /opt/k8s/priority/low-batch.yaml

# 查看调度事件与抢占事件
kubectl describe pod app-high | sed -n '/Events/,$p'
kubectl describe pod batch-low | sed -n '/Events/,$p'

命令解释:
- kubectl describe pod:查看调度失败原因、抢占/驱逐事件。
- sed -n '/Events/,$p':聚焦事件字段,便于排查。

与 PDB 约束联动示例(限制可被驱逐的数量):

# 文件:/opt/k8s/priority/pdb-web.yaml
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: web-pdb
spec:
  minAvailable: 2
  selector:
    matchLabels:
      app: web
kubectl apply -f /opt/k8s/priority/pdb-web.yaml
kubectl get pdb web-pdb

命令解释:
- minAvailable: 2:限制最少可用副本数,抢占时会尊重该约束。
- kubectl get pdb:查看 PDB 是否生效。

关键策略建议:
- 建立分层:系统关键(100000+)> 核心业务(10000)> 普通业务(1000)> 批处理(10)。
- 避免全量高优先级,防止饥饿与频繁驱逐。
- 配合 LimitRange/ResourceQuota 限制高优先级 Pod 的请求上限。
- 对核心业务设置合理 PDB,降低抢占抖动。

排错清单与命令:

# 1) 观察调度失败与抢占事件
kubectl describe pod <pod-name> | sed -n '/Events/,$p'

# 2) 确认 PriorityClass 是否正确
kubectl get priorityclass
kubectl get priorityclass high-priority -o yaml

# 3) 查看调度器日志(按实际集群组件名)
kubectl -n kube-system logs deploy/kube-scheduler | tail -n 200

# 4) 观察被驱逐 Pod 的状态
kubectl get pod -A | grep Evicted

命令解释:
- describe pod:定位调度失败具体原因。
- get priorityclass -o yaml:验证 valueglobalDefault 是否冲突。
- logs deploy/kube-scheduler:分析抢占决策与资源瓶颈。
- grep Evicted:快速定位被抢占/驱逐的 Pod。

练习(可在测试集群完成):
1. 创建 high-priority 与 low-batch 两个优先级类,启动 3 个低优先级 Pod,占满节点资源;再创建 1 个高优先级 Pod,观察低优先级 Pod 是否被驱逐。
2. 给低优先级工作负载加 PDB(minAvailable: 2),再次触发抢占,观察高优先级 Pod 是否仍能成功调度。
3. 调整高优先级 Pod 的 resources.requests,记录调度结果变化,并总结“请求过大导致无法抢占”的现象。