题干与适用场景
你维护一个由 Deployment 管理、期望副本数为 5 的服务。集群升级时需要 drain 节点,团队担心同时失去多个副本。面试官要求你设计或审查 PodDisruptionBudget(PDB),并解释它对滚动发布、节点故障和直接删除 Pod 的影响。
这道题考察 Kubernetes 可用性边界和运维推理。PDB 限制的是受选择器匹配的副本因自愿中断而同时不可用的数量;它不是副本控制器,也不是对所有故障的可用性保证。回答必须把期望副本数、选择器、驱逐入口和剩余容量联系起来。
面试官在评估什么
- 能否区分 voluntary disruption 与 involuntary disruption。
- 能否正确解释
minAvailable和maxUnavailable的互斥语义。 - 能否说明 PDB 依赖控制器的期望副本数和正确的 Pod selector。
- 能否判断 drain 重试、PDB 不生效和滚动更新的边界。
- 能否从副本、跨区分布、探针和容量角度补足 PDB 之外的可用性措施。
回答前需要澄清的问题
- 服务由 Deployment、StatefulSet 还是其他控制器管理?PDB 需要能推导期望副本数。
- 选择器是否只匹配这一份工作负载?匹配过宽会把无关 Pod 混入预算。
- 需要保护的是节点 drain、集群缩容等自愿动作,还是要处理节点断电?后者不能靠 PDB 阻止。
- 服务是否有跨可用区副本、足够容量和正确 readiness?PDB 只限制驱逐,不创造容量。
- 维护窗口允许 drain 等待多久?预算过紧会延长操作,过松会降低可用副本数。
30 秒回答框架
“PDB 只约束通过 Eviction API 发起的自愿中断。5 个副本可以用 minAvailable: 4 或 maxUnavailable: 1 表达一次最多少一个,但两者不能同时设置。它依赖工作负载的期望副本数和精确 selector;节点故障、直接删除 Deployment 或应用滚动更新不由 PDB 完全阻止。drain 被拒绝时应检查预算、健康副本、容量和驱逐入口,同时用副本、跨区分布与探针补足可用性。”
深度回答步骤
先定义中断类型
节点 drain、节点升级和集群自动缩容通常通过 Eviction API 请求 Pod 迁移,属于自愿中断,PDB 可以让 API 暂时拒绝驱逐。节点断电、内核崩溃或网络隔离属于非自愿中断,PDB 不能阻止它们;这些 Pod 变为不可用后仍会计入预算状态。
解释两个互斥字段
minAvailable 表示驱逐后至少要保持多少个匹配 Pod 可用;maxUnavailable 表示驱逐后最多允许多少个匹配 Pod 不可用。二者不能同时设置。对期望 5 个副本的服务,minAvailable: 4 和 maxUnavailable: 1 在当前规模下表达相近意图,但百分比会随副本数变化,必须先说明期望副本数和取整行为。
预算依赖期望副本和 selector
控制面通过 Pod 的 ownerReferences 找到管理它的工作负载,并从 .spec.replicas 推导 intended 数量。selector 应与 Deployment 或 StatefulSet 的 Pod 标签一致且足够窄。若 selector 匹配多个应用,预算可能错误地把它们视为一组;若没有受支持的 owning resource,Kubernetes 无法可靠推导总数。
用一个配置说明边界
示例配置如下,表示期望 5 个匹配 Pod 时最多允许 1 个因自愿驱逐不可用:
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: checkout-api
spec:
maxUnavailable: 1
selector:
matchLabels:
app: checkout-api这段配置不保证总有 4 个健康 Pod:副本可能本来就不健康,节点也可能突然失效。上线前要核对 selector、readiness、期望副本数和多区容量。
解释 drain 被拒绝或重试
当可驱逐数量为零、健康副本已低于 minAvailable,或预算控制器暂时无法计算状态时,Eviction API 可以返回拒绝。kubectl drain 会周期性重试失败请求,直到 Pod 被终止或达到超时。排查时先确认 PDB 状态、匹配 Pod、当前健康数、未就绪原因和维护动作是否真的走 Eviction API。
区分滚动更新和直接删除
工作负载的 Deployment 或 StatefulSet 滚动更新由自身的更新策略处理,不会被 PDB 当成完全相同的限制;PDB 也不能约束直接删除 Pod 或 Deployment 的操作。发布系统应同时配置 maxUnavailable、maxSurge、readiness 和回滚策略,不能把所有发布保护都交给 PDB。
补足 PDB 之外的可靠性
PDB 只处理一类中断。要抵御节点或可用区故障,还需要足够副本、拓扑分布、容量余量、正确的 readiness/liveness、优雅终止和连接排空。对有法定人数的状态服务,预算应结合 quorum 需求;对无状态服务,先用真实流量、恢复时间和容量压测验证“可用”的定义。
高质量示范回答
“这个 Deployment 的期望副本数是 5,我会先确认 PDB selector 只匹配 checkout-api,并确认 readiness 和跨区容量。若要求自愿驱逐后至少保留 4 个可用副本,可以写 minAvailable: 4 或 maxUnavailable: 1,两者互斥;我会根据副本规模变化选择绝对数或百分比。
PDB 保护的是通过 Eviction API 的节点 drain、节点维护和某些缩容动作。节点断电、内核故障和直接删除 Pod 不会被它阻止,滚动更新也主要由 Deployment 的更新策略控制。drain 被拒绝时我会检查当前健康副本、预算状态、selector、Pod 未就绪原因和容量,并确认请求是否走 Eviction API;kubectl drain 可能会重试直到超时。
最后我会把 PDB 与副本、拓扑分布、readiness、优雅终止和发布回滚一起验证。PDB 过紧会让维护长期卡住,过松则不能满足服务的最低容量,所以阈值应来自流量和故障演练,而不是套用一个通用百分比。”
常见错误
- 说 PDB 能阻止节点故障:混淆自愿与非自愿中断 → 明确 PDB 只约束 Eviction API 路径。
- 同时设置
minAvailable和maxUnavailable:两个字段互斥 → 选择一个表达预算。 - 只看当前 Pod 数量:预算基于控制器期望副本数 → 检查 ownerReferences 和
.spec.replicas。 - selector 匹配整个命名空间:不同应用共享预算 → 使用与工作负载一致的窄 selector。
- 认为 PDB 保护滚动更新和直接删除:发布控制器与删除路径有独立语义 → 分别检查更新策略和操作权限。
- drain 卡住就删除 PDB:可能把容量风险扩大 → 先查健康副本、探针、预算状态和容量,再调整维护窗口。
- 只配 PDB 不配拓扑和容量:剩余 Pod 可能集中在同一故障域 → 配合多区分布、余量和演练。
- 把百分比当固定副本数:扩缩容后预算含义变化 → 写出期望规模、取整和扩缩容行为。
追问与回答
追问 1:minAvailable: 80% 对 5 个副本意味着什么?
它表达至少保持按规则取整后的可用副本数,具体结果应以当前 Kubernetes 版本和 API 语义验证,不能直接把百分比当成固定的 4 个。面试中应说明要检查取整和扩缩容后的状态。
追问 2:为什么 drain 仍然可能导致服务不可用?
PDB 只限制可接受的自愿驱逐数量,不能修复本来就不健康的 Pod、容量不足、单区集中或应用不承受连接迁移的问题。readiness、拓扑、容量和优雅终止需要一起验证。
追问 3:直接 kubectl delete pod 会被 PDB 拦截吗?
不应假设会。文档明确指出直接删除 Pod 或 Deployment 可以绕过 PDB;需要通过权限、审计和发布流程约束这类操作。
追问 4:PDB 状态显示没有允许驱逐,先改大预算吗?
先检查 selector、期望副本、健康副本、未就绪原因和控制器状态。盲目放宽预算可能把真实健康问题掩盖;若维护确实需要,可在评估容量和回滚后临时调整,并记录窗口。
追问 5:状态服务和无状态服务的预算有什么不同?
状态服务要先满足 quorum 或一致性协议的最低副本数,并验证重平衡和恢复;无状态服务通常关注剩余容量、延迟和连接排空。两者都不能只从副本数量推导真实可用性。
追问 6:如何验证 PDB 配置真的有效?
在预生产或受控窗口执行一次 Eviction API 和 drain 演练,观察拒绝、重试、终止宽限期、流量、错误率和恢复时间;再测试节点故障与直接删除路径,确认团队没有把 PDB 的保护边界误当成全故障保证。