HPA、滚动更新和 PDB 都与副本数量有关,但它们控制的是三条不同路径。
| 机制 | 主要职责 | 关键配置 |
|---|---|---|
| HPA | 根据指标调整副本数 | minReplicas、maxReplicas、目标指标 |
| RollingUpdate | 发布时替换新旧 Pod | maxSurge、maxUnavailable |
| PDB | 限制主动驱逐造成的不可用 | minAvailable 或 maxUnavailable |
HPA 依赖指标链路
基于 CPU 或内存的 HPA 需要 Resource Metrics API,通常由 metrics-server 提供。指标不可用时,HPA 无法正常计算期望副本数;此外,CPU 利用率目标还依赖合理的资源 requests。
PDB 只约束可协商的主动驱逐
PodDisruptionBudget(PDB)可以理解为:给“可协商的主动维护操作”设置一道门槛,而不是保护 Pod 永远不出故障。它约束的是通过 Eviction API 发起的主动驱逐,例如节点维护时的 kubectl drain。
| 场景 | PDB 能否阻止 | 原因 |
|---|---|---|
kubectl drain 驱逐 Pod | 能 | drain 使用 Eviction API,驱逐前会检查 PDB |
| 节点自动缩容前排空节点 | 取决于实现,通常能 | 通过 Eviction API 驱逐时受 PDB 约束 |
| Deployment 滚动更新 | 不能 | 由 Deployment 的 maxUnavailable、maxSurge 控制 |
kubectl delete pod | 不能 | 直接删除绕过 Eviction API |
| 节点突然宕机 | 不能 | 故障已经发生,无法事先协商 |
| 容器 OOM 或进程崩溃 | 不能 | 属于运行故障,通常由 kubelet 重启容器 |
| Pod 被抢占 | 不能作为绝对保证 | 调度器会尽量遵守 PDB,但抢占过程可能违反 PDB |
例如应用有 A、B、C 三个可用 Pod,并设置 minAvailable: 2:
- 驱逐 A 后仍有 B、C 两个可用 Pod,因此 Eviction API 允许驱逐。
- 如果 A 已经不可用,此时再驱逐 B 就只剩 C 可用,因此 Eviction API 拒绝驱逐。
但管理员直接执行 kubectl delete pod B 时,PDB 不会拦截。PDB 判断的是“现在是否允许主动驱逐这个 Pod”,不负责阻止 Pod 自己崩溃、节点故障或工作负载更新与缩容。
两种“缩容”不是一回事
容易混淆的是,HPA 和节点自动伸缩器都可能执行“缩容”,但它们缩减的对象不同。
| 机制 | 缩减对象 | 示例 | 与 PDB 的关系 |
|---|---|---|---|
| HPA | 工作负载的 Pod 副本数 | Deployment 从 10 个副本降到 4 个 | 修改工作负载的期望副本数,PDB 不限制这次缩容 |
| Node Autoscaler / Cluster Autoscaler | 集群节点数 | 集群从 5 个节点降到 3 个 | 移除节点前若通过 Eviction API 驱逐 Pod,会检查 PDB |
两者可能前后发生:
业务负载下降
↓
HPA:Pod 10 → 4
↓
部分节点变得空闲
↓
Node Autoscaler:节点 5 → 3
↓
排空待移除节点,通过 Eviction API 驱逐剩余 Pod 并检查 PDB节点自动伸缩器是否排空节点、如何调用 Eviction API,以及在什么情况下跳过缩容,取决于具体实现和云厂商。更准确的说法是:遵循 Kubernetes PDB 语义的节点自动伸缩实现,在移除节点前通常会排空节点;其中通过 Eviction API 发起的驱逐受 PDB 约束。
一个容易卡住维护的配置
单副本服务设置 minAvailable: 1,会让受 PDB 约束的节点驱逐无法继续。配置前要同时考虑副本数、调度容量和维护流程。
实际可用性通常来自多个机制的组合:replicas 提供冗余,readiness probe 控制流量,反亲和性或拓扑分布避免副本集中在同一故障域,maxUnavailable 与 maxSurge 控制滚动发布,HPA 处理负载变化,PDB 给主动维护留出安全边界。
参考:Horizontal Pod Autoscaling、Disruptions、Node Autoscaling、Pod Priority and Preemption