Kubernetes调度器异常:Pod反亲和性不生效问题求助
问题场景
我有一个副本数设为2的Deployment应用,配置了Pod反亲和性规则,具体配置如下:
apiVersion: apps/v1 kind: Deployment metadata: name: service-user spec: replicas: 2 template: metadata: labels: app: service-user spec: affinity: podAntiAffinity: preferredDuringSchedulingIgnoredDuringExecution: - podAffinityTerm: matchExpressions: - key: app operator: In values: - service-user topologyKey: kubernetes.io/hostname weight: 100
将该应用部署到目标问题集群时,两个副本始终被调度至同一节点,但在其他集群中部署时表现正常。尝试重启kube-scheduler服务无法解决问题,而重启kube-apiserver服务后,调度恢复正常。请问这是否是kube-apiserver的Bug?
环境信息
- Kubernetes版本:1.21.6
- K8s Master节点:3台,配置为8C16G
- K8s Node节点:3台,配置为128C512G
- 服务器负载:低
- 操作系统:CentOS 8.2
结论
大概率是kube-apiserver的缓存一致性问题,而非明确的代码Bug,但属于Kubernetes 1.21.x版本中可能出现的已知类问题。
分析过程
反亲和性规则生效逻辑
你的配置使用preferredDuringSchedulingIgnoredDuringExecution软约束,调度器会优先尝试满足规则,只有当所有节点都不满足条件时才会忽略。但你的集群节点资源充足、负载低,正常情况下应触发分散调度逻辑。重启kube-scheduler无效的原因
kube-scheduler本身不存储集群状态,完全依赖从kube-apiserver获取实时的Pod、节点等资源信息。如果kube-apiserver返回的信息有误(比如缓存中未同步已调度的第一个Pod标签),调度器无法识别节点上已有同应用Pod,自然不会执行反亲和性调度。重启kube-apiserver恢复的原因
kube-apiserver重启会清空自身缓存,重新从etcd拉取完整集群状态数据,此时调度器请求能拿到准确的Pod分布信息,从而正确执行反亲和性规则。对应版本的已知问题
Kubernetes 1.21.x存在部分与apiserver缓存、etcd数据同步相关的小问题,比如apiserver缓存未及时更新Pod标签或节点拓扑信息,导致调度器决策出错。这类问题在1.22+版本中已被逐步修复。
建议
- 优先升级Kubernetes版本到1.22或更高稳定版本,从根源上避免缓存一致性问题。
- 临时解决方案:若无法立即升级,遇到此类问题时可滚动重启多Master节点的kube-apiserver(避免集群不可用),或在部署前清空apiserver缓存(操作需谨慎)。
内容的提问来源于stack exchange,提问作者zhashuyu

