Kubernetes 中需用 PodDisruptionBudget(PDB)限制主动驱逐规模,防止服务中断;推荐 maxUnavailable 控制不可用副本比例,minAvailable 保底在线数,并配合 preStop 和 readinessProbe 消除流量丢失。

在 Kubernetes 集群自动升级(如节点 OS 升级、kubelet 版本更新)过程中,Cluster Autoscaler 或运维脚本调用 kubectl drain 时若未加约束,可能一次性驱逐节点上全部 Pod,导致服务副本数归零、SLA 彻底崩溃;这不是滚动更新逻辑缺陷,而是缺少对“主动驱逐规模”的硬性限制。
确认你的工作负载已部署且稳定运行
执行 kubectl get deploy -n your-namespace,确保目标 Deployment 处于 Available 状态,且副本数与期望值一致。若 Pod 长期处于 Pending 或 CrashLoopBackOff,PDB 无法生效——【PDB 只校验健康 Pod 数,不干预调度失败或启动失败】。
检查该 Deployment 的标签选择器:kubectl get deploy your-app -o jsonpath='{.spec.selector.matchLabels}',记下输出结果,例如 {"app":"user-api"}。这将用于后续 PDB 的精准匹配。
创建 PodDisruptionBudget 控制驱逐上限
方法一:用 maxUnavailable 限定“最多允许几个不可用”(推荐用于无状态服务)
编写 YAML 文件 app-pdb.yaml:
apiVersion: policy/v1kind: PodDisruptionBudgetmetadata: name: user-api-pdb namespace: your-namespacespec: maxUnavailable: 25% selector: matchLabels: app: user-api
执行 kubectl apply -f app-pdb.yaml。若 Deployment 有 8 个副本,该配置允许最多 2 个 Pod 同时被驱逐(25% 向下取整),其余 6 个持续提供服务。
方法二:用 minAvailable 保底“最少必须几个在线”(适用于有状态集群)
例如 etcd 3 节点集群,仲裁需 ≥2,就设 minAvailable: 2。此时即使节点只剩 1 个健康 Pod,drain 也会被阻塞,直到其他 Pod 恢复。
验证 PDB 是否生效
第一步:查看 PDB 当前状态
kubectl get pdb -n your-namespace user-api-pdb -o wide,确认 CURRENT HEALTHY 与 MIN AVAILABLE 数值合理(如 CURRENT HEALTHY=8,MIN AVAILABLE=6)。
第二步:模拟一次受控驱逐
执行 kubectl drain node-xxx --dry-run=client -o wide,观察输出中是否包含 Would evict 2 pods 且未报错。若提示 Cannot evict pod: xxx, no matching PDB,说明 labelSelector 不匹配,立即修正 YAML 中的 matchLabels。
第三步:真实驱逐时观察行为
运行 kubectl drain node-xxx --ignore-daemonsets --delete-emptydir-data,终端会卡住并提示 error: unable to drain node "node-xxx", aborting since 2 pods would be left unavailable —— 这不是失败,是 PDB 正常拦截。此时你必须先扩容副本、或等部分 Pod 自动恢复,才能继续。
配合 preStop 和 readinessProbe 消除残留中断
仅靠 PDB 不足以覆盖所有中断路径。当 PDB 允许驱逐发生后,Pod 仍可能因退出过快或就绪过晚导致流量丢失。
在 Deployment 的容器 spec 中添加:
lifecycle: preStop: exec: command: ["/bin/sh", "-c", "sleep 10"]
这确保 SIGTERM 发出后,Pod 继续处理存量请求至少 10 秒,等 Endpoint 从 Service 中彻底移除。
同时配置 readinessProbe,避免新 Pod 在业务未就绪时就被加入 Endpoint:
readinessProbe: httpGet: path: /healthz port: 8080 initialDelaySeconds: 15 periodSeconds: 5
注意:【initialDelaySeconds 必须大于应用实际初始化耗时,否则 probe 会连续失败,Pod 永远无法 Ready】。


















