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分布变得不均,违反了预期的均匀分布要求。
问题
- 如何实现Deployment缩容后Pod在3个节点上均匀分布(每个节点保留2个副本)?
- 为什么缩容时nginx-9未被终止,而nginx-5被终止?
原因分析
根据K8s ReplicaSet控制器的Pod删除优先级规则,删除顺序由以下因素决定(优先级从高到低):
- Pod状态(异常状态的Pod优先被删除)
controller.kubernetes.io/pod-deletion-cost注解值(值越高,越优先被删除)- 副本数更多的节点上的Pod优先被删除
- Pod创建时间(更早创建的Pod优先被删除)
针对当前场景:
- 一次性缩容时,初始所有节点的Pod副本数都是4,规则3无法触发(没有节点副本数更多),因此控制器会触发规则4,优先删除创建时间更早的Pod。nginx-5的创建时间早于nginx-9,所以会被优先终止。
- 偏好性反亲和(
preferredDuringSchedulingIgnoredDuringExecution)仅在Pod调度阶段生效,缩容阶段不会被控制器考虑,因此一次性缩容时无法自动维持均匀分布。
解决方案
临时解决办法
通过逐步缩容,每次只减少1个副本,让控制器每次都能触发“副本数更多节点优先删”的规则,最终实现均匀分布:
kubectl scale deployment nginx --replicas 11kubectl scale deployment nginx --replicas 10kubectl scale deployment nginx --replicas 9kubectl scale deployment nginx --replicas 8kubectl scale deployment nginx --replicas 7kubectl 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数量差异不超过1whenUnsatisfiable: DoNotSchedule:如果无法满足分布要求,就不调度新Pod(也可设为ScheduleAnyway做偏好性约束)- 该规则在缩容时,控制器会优先删除Pod数量更多的节点上的Pod,自动维持均匀分布,无需逐步缩容。
备选方案:自定义Pod删除成本
通过给Pod添加controller.kubernetes.io/pod-deletion-cost注解,控制缩容时的删除优先级。比如给每个节点上超过目标数量的Pod设置更高的删除成本,让控制器优先删除这些Pod。可通过MutatingAdmissionWebhook或手动批量添加注解实现。
内容的提问来源于stack exchange,提问作者willyw0nka
相关产品推荐
相关产品推荐

