Kubernetes PodDisruptionBudget配置指南:如何防止驱逐操作导致服务中断

PodDisruptionBudget解决什么问题

Kubernetes集群在节点维护、自动扩缩容、版本滚动更新时,kube-scheduler和controller-manager会主动驱逐Pod。如果没有保护机制,驱逐操作可能同时终止同一服务的多个Pod副本,导致服务可用性急剧下降甚至完全中断。

PodDisruptionBudget(PDB)是一种声明式约束,告诉Kubernetes在 voluntary disruption(自愿驱逐)场景下,必须保留多少Pod处于可用状态。它只对自愿驱逐生效,不影响节点硬件故障这种 involuntary disruption(非自愿驱逐)。

自愿驱逐与非自愿驱逐的区分

理解这两种驱逐的区别是正确使用PDB的前提:

  • 自愿驱逐:由管理员或控制器主动触发——kubectl drain排空节点、集群自动扩缩容缩容节点、kubectl delete pod等。这类驱逐可以被PDB拦截或延迟。
  • 非自愿驱逐:由硬件故障、内核panic、网络分区等不可控因素导致。PDB无法阻止这类驱逐,需要通过多副本+反亲和性+跨可用区部署来保证高可用。

PDB的保护范围仅限于自愿驱逐。不要指望PDB能防住节点宕机——那是亲和性调度和多副本部署的职责。

PDB的两种约束模式

PDB通过minAvailablemaxUnavailable两个字段定义约束,两者互斥,只能使用其中一个:

# 模式一:minAvailable(最少保留可用Pod数)
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: api-server-pdb
  namespace: production
spec:
  minAvailable: 2
  selector:
    matchLabels:
      app: api-server
---
# 模式二:maxUnavailable(最多不可用Pod数)
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: worker-pdb
  namespace: production
spec:
  maxUnavailable: 1
  selector:
    matchLabels:
      app: worker

两种模式的选择取决于部署规模:

  • 副本数固定且较少(2-5个):用minAvailable,确保绝对数量
  • 副本数较多或会自动扩缩容:用maxUnavailable,按比例控制

minAvailablemaxUnavailable也支持百分比形式,如minAvailable: 50%,在HPA自动扩缩容场景下更灵活。

PDB在节点维护中的实际行为

执行kubectl drain排空节点时,PDB的工作流程如下:

  1. kubelet收到drain命令,开始逐个驱逐节点上的Pod
  2. eviction API检查每个被驱逐Pod所属的PDB约束
  3. 如果驱逐该Pod会导致可用Pod数低于minAvailable,驱逐请求被拒绝
  4. kubectl drain会等待并重试,默认超时时间为0(无限等待)

实际操作中的现象——PDB阻止驱逐时,kubectl drain会报错:

error when evicting pods/"api-server-7b5f6c8d4-xkg2m" -n "production"
(to retry pass --force=false): Cannot evict pod as it would violate
the pod's disruption budget.

处理方式有两种:等待其他节点的Pod就绪后再重试drain,或者使用--disable-eviction强制删除(不推荐,会绕过PDB保护)。正确的做法是确保集群有足够的冗余节点,使得drain一个节点时,Pod可以在其他节点重建。

滚动更新与PDB的配合

Deployment的滚动更新本身不受PDB约束——Deployment控制器通过maxUnavailablemaxSurge参数控制更新节奏。但PDB会影响更新过程中节点维护的可行性。

一个常见问题:PDB的minAvailable设置过高,导致滚动更新期间所有Pod无法被驱逐,节点维护被阻塞。例如Deployment有3个副本,PDB设置minAvailable=3,意味着所有Pod都必须可用,任何驱逐都会被拒绝。

合理的配置示例——3副本Deployment,PDB保证至少2个可用:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: api-server
spec:
  replicas: 3
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 1
      maxSurge: 1
  selector:
    matchLabels:
      app: api-server
  template:
    metadata:
      labels:
        app: api-server
    spec:
      containers:
      - name: api-server
        image: api-server:v2.1.0
        readinessProbe:
          httpGet:
            path: /health
            port: 8080
          initialDelaySeconds: 5
          periodSeconds: 10
---
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: api-server-pdb
spec:
  minAvailable: 2
  selector:
    matchLabels:
      app: api-server

readinessProbe的配置至关重要。PDB计算可用Pod数时,只计算Ready状态的Pod。如果readinessProbe配置不当(探测间隔过长或路径错误),新Pod迟迟不就绪,PDB会一直阻止旧Pod被驱逐,导致更新卡住。

PDB配置的常见错误

  • minAvailable等于副本数——PDB要求所有Pod都必须可用,任何驱逐都会被拒绝。在3副本场景下设minAvailable=2或maxUnavailable=1。
  • selector匹配范围过大——PDB的selector误匹配了不该保护的Pod,导致不相关的驱逐也被阻止。通过kubectl get pods -l app=api-server --all-namespaces确认selector精确匹配目标。
  • 忘配readinessProbe——PDB依赖Pod的Ready状态判断可用性,没有readinessProbe的Pod启动后立即Ready,但可能无法处理请求,PDB的数据不准确。
  • 单可用区部署——所有副本在同一可用区,该可用区节点维护时PDB会阻塞驱逐。通过topologySpreadConstraints将副本分散到多个可用区。

PDB状态检查与故障排查

查看PDB状态:

# 查看所有PDB
kubectl get pdb -A

# 查看PDB详情
kubectl describe pdb api-server-pdb -n production

输出中的关键字段:

  • Allowed Disruptions:当前允许驱逐的Pod数量。如果为0,说明PDB正在阻止驱逐。
  • Current / Desired:当前可用Pod数 / 期望可用Pod数
  • Expected / Disruptions Allowed:预期Pod总数 / 允许驱逐数

排查PDB阻塞问题时的命令组合:

# 检查Pod状态是否Ready
kubectl get pods -n production -l app=api-server \
  -o custom-columns=NAME:.metadata.name,STATUS:.status.phase,READY:.status.containerStatuses[0].ready

# 检查PDB事件
kubectl get events -n production --field-selector reason=NoPodDisruptionBudget

# 模拟驱逐测试(dry-run)
kubectl drain node-3 --dry-run --ignore-daemonsets --delete-emptydir-data

--dry-run参数可以预演drain操作,不实际驱逐Pod,用于验证PDB配置是否正确。

集群级PDB管理策略

生产集群中建议为所有关键服务配置PDB。运维操作准则:

  • 每个Deployment至少配置一个PDB,副本数小于等于2时设minAvailable为1
  • CronJob和Job不需要PDB——它们的生命周期由自身控制器管理
  • DaemonSet不需要PDB——每个节点一个Pod,驱逐后由DaemonSet控制器重新调度
  • 使用Kyverno或OPA Gatekeeper实现PDB的强制策略——自动为带特定标签的Deployment创建PDB

监控PDB状态应该纳入集群巡检项。通过Prometheus的kube-state-metrics采集PDB指标:kube_poddisruptionbudget_status_pod_disruptions_allowed表示允许驱逐数,持续为0的PDB需要排查原因。PDB是SRE稳定性工程中成本低、收益高的防护手段,正确配置后能在节点维护和自动伸缩时有效防止服务中断。

原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/kubernetespoddisruptionbudget-pei-zhi-zhi-nan-ru-he-fang/

(0)
小编小编
上一篇 13小时前
下一篇 13小时前

相关推荐