You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

K8s Deployment缩容违反Pod反亲和规则,如何实现Pod均匀分布?

K8s Deployment缩容后Pod均匀分布问题

场景

我有一个包含3个工作节点(K8s版本v1.22.17)的集群,运行着一个配置12个副本的Deployment。该Deployment配置了偏好性Pod反亲和(preferredDuringSchedulingIgnoredDuringExecution),具体定义如下:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  replicas: 12
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      affinity:
        podAntiAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
            - weight: 100
              podAffinityTerm:
                labelSelector:
                  matchLabels:
                    app: nginx
                topologyKey: kubernetes.io/hostname
      containers:
      - name: nginx
        image: nginx:1.14.2
        ports:
        - containerPort: 80

初始状态下Pod分布符合反亲和规则,每个节点上运行4个Pod。但执行kubectl scale deployment nginx --replicas 6一次性缩容到6个副本时,Pod分布变得不均,违反了预期的均匀分布要求。

问题

  1. 如何实现Deployment缩容后Pod在3个节点上均匀分布(每个节点保留2个副本)?
  2. 为什么缩容时nginx-9未被终止,而nginx-5被终止?

原因分析

根据K8s ReplicaSet控制器的Pod删除优先级规则,删除顺序由以下因素决定(优先级从高到低):

  1. Pod状态(异常状态的Pod优先被删除)
  2. controller.kubernetes.io/pod-deletion-cost注解值(值越高,越优先被删除)
  3. 副本数更多的节点上的Pod优先被删除
  4. Pod创建时间(更早创建的Pod优先被删除)

针对当前场景:

  • 一次性缩容时,初始所有节点的Pod副本数都是4,规则3无法触发(没有节点副本数更多),因此控制器会触发规则4,优先删除创建时间更早的Pod。nginx-5的创建时间早于nginx-9,所以会被优先终止。
  • 偏好性反亲和(preferredDuringSchedulingIgnoredDuringExecution)仅在Pod调度阶段生效,缩容阶段不会被控制器考虑,因此一次性缩容时无法自动维持均匀分布。

解决方案

临时解决办法

通过逐步缩容,每次只减少1个副本,让控制器每次都能触发“副本数更多节点优先删”的规则,最终实现均匀分布:

  • kubectl scale deployment nginx --replicas 11
  • kubectl scale deployment nginx --replicas 10
  • kubectl scale deployment nginx --replicas 9
  • kubectl scale deployment nginx --replicas 8
  • kubectl scale deployment nginx --replicas 7
  • kubectl scale deployment nginx --replicas 6

更优解决方案:使用Pod拓扑分布约束(PodTopologySpreadConstraints)

从K8s 1.19版本开始,PodTopologySpreadConstraints可以在调度和缩容阶段同时生效,确保Pod在拓扑域(如节点)上均匀分布。修改Deployment的Pod模板部分,替换原有的反亲和规则:

spec:
  template:
    spec:
      topologySpreadConstraints:
        - maxSkew: 1
          topologyKey: kubernetes.io/hostname
          whenUnsatisfiable: DoNotSchedule
          labelSelector:
            matchLabels:
              app: nginx

参数说明:

  • maxSkew:1:任意两个节点上的Pod数量差异不超过1
  • whenUnsatisfiable: DoNotSchedule:如果无法满足分布要求,就不调度新Pod(也可设为ScheduleAnyway做偏好性约束)
  • 该规则在缩容时,控制器会优先删除Pod数量更多的节点上的Pod,自动维持均匀分布,无需逐步缩容。

备选方案:自定义Pod删除成本

通过给Pod添加controller.kubernetes.io/pod-deletion-cost注解,控制缩容时的删除优先级。比如给每个节点上超过目标数量的Pod设置更高的删除成本,让控制器优先删除这些Pod。可通过MutatingAdmissionWebhook或手动批量添加注解实现。


内容的提问来源于stack exchange,提问作者willyw0nka

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 00:32:33