服务器K8s亲和性配置:从节点选择到Pod互斥的落地实践

先弄清亲和性到底解决什么问题

K8s亲和性配置的本质,是告诉调度器「这个Pod更愿意去哪些节点」或「必须和哪些Pod待在一起」。
默认调度器只看资源是否够用,不看业务逻辑;
而亲和性让你能用标签把节点和Pod关联起来,实现定向调度。

它主要分三类:

  • nodeAffinity:Pod和节点之间的匹配,比如只调度到带 disktype=ssd 标签的机器。
  • podAffinity:Pod和Pod靠近,比如前端服务尽量和缓存服务在同一节点。
  • podAntiAffinity:Pod和Pod互斥,比如同一应用的三个副本不要挤在一台机器上。

适用条件:集群至少有两个可调度节点,且节点或已有Pod带有可用于区分的标签。
单节点集群测不出效果,建议在测试环境先验证。

准备标签和测试环境

先确认节点状态和标签情况:

kubectl get nodes --show-labels

如果节点没有业务标签,手动打一个:

kubectl label nodes node-1 disktype=ssd
kubectl label nodes node-2 disktype=hdd

再准备一个测试用的Deployment,镜像用 nginx:alpine 即可,方便观察Pod落在哪个节点:

kubectl create deployment affinity-demo --image=nginx:alpine --replicas=2

查看调度结果:

kubectl get pods -o wide

输出中的 NODE 列就是实际落点,后续每一步都靠它验证。

nodeAffinity:把Pod绑到指定节点

节点亲和分两种写法,区别在「必须」还是「尽量」:

  • requiredDuringSchedulingIgnoredDuringExecution:硬性要求,不满足就Pending。
  • preferredDuringSchedulingIgnoredDuringExecution:软性偏好,不满足也会调度到其他节点。

下面这个YAML要求Pod必须调度到 disktype=ssd 的节点:

apiVersion: v1
kind: Pod
metadata:
  name: nginx-ssd
spec:
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
          - key: disktype
            operator: In
            values:
            - ssd
  containers:
  - name: nginx
    image: nginx:alpine

保存为 node-affinity.yaml 后执行:

kubectl apply -f node-affinity.yaml
kubectl get pod nginx-ssd -o wide

如果 NODE 显示的是带 ssd 标签的节点,说明生效。
若长时间 Pending,用 kubectl describe pod nginx-ssd 看 Events,通常会提示 node(s) didn't match node affinity。

软性写法只需把 requiredDuringScheduling... 换成 preferredDuringScheduling...,
并在 matchExpressions 同级加 weight:
1
(取值1-100),
表示偏好权重。

podAntiAffinity:避免副本扎堆

生产环境更常用反亲和,让同一Deployment的Pod分散到不同节点,降低单点故障风险。

关键点是 topologyKey,它定义「以什么为隔离单位」。
常用 kubernetes.io/hostname 表示按节点隔离:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-spread
spec:
  replicas: 3
  selector:
    matchLabels:
      app: web-spread
  template:
    metadata:
      labels:
        app: web-spread
    spec:
      affinity:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchExpressions:
              - key: app
                operator: In
                values:
                - web-spread
            topologyKey: kubernetes.io/hostname
      containers:
      - name: nginx
        image: nginx:alpine

应用后查看分布:

kubectl apply -f web-spread.yaml
kubectl get pods -l app=web-spread -o wide

三个Pod应落在不同节点。注意:如果节点数少于副本数,多余的Pod会一直Pending,这是反亲和的硬约束导致的,属于预期行为而非故障。

podAffinity的写法和它对称,把 podAntiAffinity 换成 podAffinity 即可,效果是尽量和匹配的Pod同节点。

容易踩的坑和调度失败排查

  • 标签写错或大小写不一致:K8s标签区分大小写,App 和 app 是两个不同的键,用 kubectl get nodes --show-labels 核对。
  • required太严格导致Pending:硬约束一旦无节点满足,Pod永远起不来。优先用preferred过渡,再按需要收紧。
  • topologyKey缺失或拼错:podAffinity和podAntiAffinity必须写 topologyKey,写错会报 invalid value 或调度异常。
  • 节点被污点隔离:即使亲和性匹配,节点有 NoSchedule 污点也会拒绝调度,用 kubectl describe node <节点名> 查看Taints。
  • 改了标签但Pod没重新调度:亲和性只在调度时刻生效,修改节点标签不会自动迁移已运行的Pod,需重建Pod触发重新调度。

排查通用命令:

kubectl describe pod  | tail -20
kubectl get events --sort-by=.lastTimestamp
kubectl describe node <节点名>

验证配置是否真正生效

配置完成后别只看 kubectl get pods 是否Running,要确认落点符合预期:

  1. 用 kubectl get pods -o wide 检查每个Pod的 NODE 列。
  2. 用 kubectl describe pod 查看 Node-Selectors 和 Events,确认调度决策来源。
  3. 对反亲和场景,统计每个节点上的Pod数量,确认没有超出预期。
  4. 临时给节点打错标签,观察新Pod是否被拒绝调度,反向验证规则确实在起作用。

几个常见疑问

nodeSelector和nodeAffinity怎么选?
nodeSelector只能做等值匹配,写法简单;nodeAffinity支持 In、NotIn、Exists 等操作符和软硬约束,表达能力更强。简单场景用nodeSelector就够了,需要复杂逻辑时用nodeAffinity。

podAffinity的required和preferred有什么区别?
required是硬性要求,找不到匹配Pod就不调度;preferred是尽量满足,找不到也会调度到其他节点。生产环境建议对可用性敏感的服务用preferred,避免因约束过严导致Pod无法启动。

亲和性会影响滚动更新吗?
会。滚动更新时新Pod要重新参与调度,如果反亲和约束太严或节点资源不足,新Pod可能Pending,导致更新卡住。更新前建议确认节点数量和资源余量。

如何让Pod尽量分散但不强制?
把 requiredDuringSchedulingIgnoredDuringExecution 改成 preferredDuringSchedulingIgnoredDuringExecution,并加上 weight 值,这样调度器会尽量分散,节点不够时也不会阻塞。

分享到:
上一篇
K8s Secret 管理实战:创建、挂载与安全更新
下一篇
K8s污点与容忍怎么配:让Pod避开特定节点的实操方法
1
系统公告

泽御云中秋国庆双节活动上线:新购8折,拼团3.99元起

尊敬的用户:
泽御云“月满中秋·礼贺国庆”双节活动现已开启,活动时间为2026年9月23日至10月10日。 活动期间可享以下福利:
1. 常规云服务器新购使用优惠码“泽御中秋国庆同乐”,符合条件的订单享8折优惠。
2. 香港精品云服务器5人拼团低至3.99元,部分4核4G套餐3人拼团年付388元,续费同价。
3. 新用户购买年付云服务器,符合活动规则可赠送2个月使用时长。
4. 老用户续费季度赠15天,续费年度赠2个月;活动期间升级配置免收配置迁移手续费。
5. 推荐好友成功下单,符合条件的推荐人可获赠7天服务器使用时长。
6. 活动期间享宕机补偿标准翻倍、简单网站迁移协助及技术工单优先处理权益。
温馨提示:优惠码不适用于拼团套餐、活动轻量产品、年付订单及续费订单;拼团套餐为独立特价活动,不与赠时类福利叠加。赠送时长不可折现、退款或跨账户转移,具体规则以活动页面说明为准。
服务中心
客服
在线客服
24小时为您服务
咨询
联系我们
联系我们,为您的业务提供专属服务。
24/7 技术支持
如果您遇到寻求进一步的帮助,请过工单与我们进行联系。
24/7 即时支持
泽御云
售前客服
泽御云
泽御云
售后客服
泽御云
技术支持
评价
您对当前页面的整体感受是否满意?
😞
非常不满意
😕
不满意
😐
一般
🙂
满意
😊
非常满意