概念定位
podAntiAffinity 让「带某标签的 Pod」不要出现在同一个拓扑域里,多个副本跨节点、跨可用区打散就靠它。适用平台是 Kubernetes。写法与节点亲和一样分硬软两种:硬约束保证不叠放,但域数量不足时多余副本会 Pending;软偏好只影响打分,容量紧张时仍会叠放。常见做法是节点级用硬约束保证不叠放、可用区级用软偏好兼顾容灾与利用率。
基本信息
| 适用平台 | Kubernetes,Pod 级字段 spec.affinity.podAntiAffinity |
|---|---|
| 拓扑键 | topologyKey 决定「域」是什么:kubernetes.io/hostname 是节点,topology.kubernetes.io/zone 是可用区 |
| 匹配范围 | labelSelector 指定与哪些 Pod 互斥,通常选工作负载自己的标签 |
| 开销提示 | 反亲和对调度器计算开销较大,超大规模集群应谨慎使用 |
典型使用场景
- 无状态服务高可用:同一 Deployment 的副本不落在同一节点
- 跨可用区容灾:副本分散到多个 zone,单机房故障不影响整体
- 避免资源争抢:把高 IO 的同类实例彼此分开,减少相互干扰
- 滚动更新保护:结合 PDB 保证更新过程中可用副本不跌破底线
- 临时隔离:维护期间用软偏好把新副本优先放到空闲节点
节点级硬打散 + 可用区级软偏好
节点级硬打散 + 可用区级软偏好
spec:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchLabels:
app: web
topologyKey: kubernetes.io/hostname
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchLabels:
app: web
topologyKey: topology.kubernetes.io/zone核对与排查
核对与排查
kubectl get pods -l app=web -o wide # 看实际落点分布
kubectl get pods -l app=web -o custom-columns='NAME:.metadata.name,NODE:.spec.nodeName'
kubectl get nodes -L topology.kubernetes.io/zone # 域的数量与容量
kubectl describe pod web-x | grep -A6 'Pod Anti-Affinity' # 解析后的约束
kubectl get events --field-selector reason=FailedScheduling --sort-by=.lastTimestamp | tail -5硬软选择与后果
| 写法 | 副本数与域的关系 | 结果 |
|---|---|---|
| 硬反亲和 + hostname | 副本数 ≤ 节点数 | 每节点最多一个副本,超出部分 Pending |
| 硬反亲和 + zone | 副本数 ≤ 可用区数 | 超出部分 Pending,容灾强但利用率低 |
| 软反亲和 | 任意副本数 | 尽量分散,容量不足时叠放不报错 |
| 无约束 | 任意 | 可能集中在一台机器,失去高可用意义 |
常见组合:节点级用硬反亲和保证不叠放,可用区级用软偏好兼顾容灾与利用率,扩副本时不会立刻 Pending。
labelSelector 若写成过宽的条件(如只按 app 匹配多个工作负载),会出现互相排斥的意外效果,选择器要尽量精确。