4. Pod 驱逐机制:kubelet 节点压力驱逐、API 驱逐与优先级抢占

在多租户集群中,Pod 驱逐是保障节点稳定性和租户隔离的关键手段。当节点资源紧张或需要维护时,Kubernetes 通过三种核心机制决定哪些 Pod 被终止以及何时终止:kubelet 节点压力驱逐、API 驱逐(Eviction API)和优先级与抢占(Priority & Preemption)。理解这三者的协同关系,是设计多租户故障域策略的基础。

4.1 kubelet 节点压力驱逐

kubelet 持续监控节点资源(内存、磁盘、PID 等)。当资源使用超过预设阈值时,kubelet 主动驱逐 Pod 以回收资源,保障节点整体健康。

核心驱逐信号与阈值

驱逐信号 描述 默认硬驱逐阈值 默认软驱逐阈值
memory.available 节点可用内存 100Mi 200Mi
nodefs.available 节点根文件系统可用空间 10% 15%
nodefs.inodesFree 节点根文件系统可用 inode 5% 10%
imagefs.available 容器镜像存储文件系统可用空间 15% 20%
pid.available 节点可用 PID 数量 100 200
软驱逐 vs 硬驱逐:软驱逐在阈值持续超过指定时长(默认 5 分钟)后才触发,并允许 Pod 优雅终止;硬驱逐一旦达到阈值立即触发,Pod 被强制终止。多租户场景下,建议为关键租户 Pod 设置 priorityClassName 以避免被软驱逐优先选中。

驱逐顺序与 QoS 类

kubelet 根据 Pod 的 QoS 类决定驱逐顺序:

  1. BestEffort(无资源限制)—— 最先被驱逐
  2. Burstable(部分资源限制)—— 其次被驱逐
  3. Guaranteed(所有资源限制且相等)—— 最后被驱逐

同一 QoS 类内,kubelet 按 Pod 使用资源与请求量的比例排序,使用比例最高的 Pod 优先被驱逐。

kubelet 节点压力驱逐流程 kubelet 持续监控节点资源 资源超过硬/软驱逐阈值? 按 QoS 类排序:BestEffort → Burstable → Guaranteed 驱逐 Pod(优雅终止 / 强制终止)

4.2 API 驱逐(Eviction API)

API 驱逐提供了一种编程化的驱逐方式,允许集群管理员或控制器通过 Kubernetes API 主动驱逐 Pod,而无需等待 kubelet 节点压力触发。这在多租户场景中尤为重要,例如租户资源超限、节点维护或安全隔离时。

Eviction API 工作原理

客户端向 PodEviction 子资源提交驱逐请求,kube-controller-manager 中的 驱逐控制器 处理该请求:

  1. 检查 Pod 是否受 PodDisruptionBudget(PDB) 保护
  2. 如果 PDB 允许(即驱逐后不会低于最小可用副本数),则执行驱逐
  3. 如果 PDB 不允许,请求被拒绝,返回 429 Too Many Requests 或 409 Conflict
多租户关键点:API 驱逐会遵守 PDB 约束,而 kubelet 节点压力驱逐不遵守 PDB。因此,对于需要高可用性的租户关键服务,必须同时设置 PDB 和合理的优先级,以在节点压力场景下获得保护。

API 驱逐与节点压力驱逐对比

特性 kubelet 节点压力驱逐 API 驱逐(Eviction API)
触发方式 节点资源阈值自动触发 用户/控制器主动调用 API
遵守 PDB 否 是
优雅终止 软驱逐支持,硬驱逐不支持 始终支持(受 terminationGracePeriodSeconds 控制)
适用场景 节点资源紧急回收 计划内维护、租户隔离、资源配额管理
优先级影响 按 QoS 和资源使用比例 不直接考虑优先级,但受 PDB 约束

使用 Eviction API 驱逐 Pod

# 创建驱逐请求(YAML 格式)
cat <<EOF | kubectl create -f -
apiVersion: policy/v1
kind: Eviction
metadata:
  name: my-pod
  namespace: tenant-a
spec:
  deleteOptions:
    gracePeriodSeconds: 30
EOF

# 或直接使用 kubectl drain(底层调用 Eviction API)
kubectl drain node-1 --ignore-daemonsets --delete-emptydir-data

4.3 优先级与抢占(Priority & Preemption)

优先级与抢占机制确保高优先级 Pod 在资源竞争时能够获得调度机会。当调度器无法为高优先级 Pod 找到可用节点时,它会抢占(驱逐)低优先级 Pod 以释放资源。

优先级类定义

通过 PriorityClass 定义全局优先级,值越大优先级越高:

apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
  name: tenant-critical
value: 1000000
globalDefault: false
description: "用于关键租户业务 Pod,抢占非关键 Pod"
---
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
  name: tenant-batch
value: 100
globalDefault: false
description: "用于批处理任务,可被抢占"

抢占流程

优先级抢占流程 高优先级 Pod 调度请求 调度器尝试寻找可用节点 资源充足? 正常调度,无需抢占 触发抢占 驱逐低优先级 Pod 高优先级 Pod 调度成功

抢占的租户隔离影响

在多租户集群中,抢占可能导致一个租户的 Pod 被另一个租户的 Pod 驱逐,引发公平性问题。建议采取以下策略:

  • 租户优先级分层:为不同租户分配不同的优先级范围,关键租户使用高优先级,普通租户使用低优先级
  • 设置抢占策略:通过 PreemptionPolicy 控制是否允许抢占(PreemptLowerPriority 或 Never)
  • 结合资源配额:即使高优先级 Pod 也不能超过租户的资源配额,避免一个租户抢占整个集群
注意:优先级与抢占是调度时的行为,而 kubelet 节点压力驱逐是运行时行为。两者可能同时发生:高优先级 Pod 抢占低优先级 Pod 后,如果节点资源仍然紧张,kubelet 可能继续驱逐其他低优先级 Pod。务必为租户关键服务设置 PDB + 高优先级 + Guaranteed QoS 三层保护。

4.4 三种驱逐机制的协同与选择

场景 推荐机制 说明
节点内存/磁盘紧急不足 kubelet 节点压力驱逐 自动触发,快速回收资源,不遵守 PDB
计划内节点维护 API 驱逐(kubectl drain) 遵守 PDB,优雅迁移 Pod,避免服务中断
租户超配额或违规 API 驱逐(控制器调用) 可编程控制,结合租户策略自动驱逐
高优先级 Pod 等待调度 优先级与抢占 调度时触发,抢占低优先级 Pod 释放资源
节点资源碎片化 API 驱逐 + 重调度 主动驱逐 Pod 以优化节点资源分布

在实际多租户集群中,这三种机制通常组合使用。例如:为关键租户设置高优先级和 Guaranteed QoS,使其在节点压力驱逐中处于最后被驱逐的位置;同时设置 PDB 保护,确保 API 驱逐不会导致服务不可用;最后通过优先级抢占确保关键任务在资源竞争时能够获得调度机会。