K8s Affinity 实战指南:精准控制Pod调度!

191 阅读3分钟

引言:你真的掌控了Pod调度吗?

很多开发者在部署应用时,往往只关注副本数量、资源限制、Service 暴露方式,却忽略了一个至关重要的问题:

Pod 到底被调度到哪台 Node 上?

Kubernetes 的调度器虽然强大,但默认的调度策略有时候并不满足业务需求,比如:

  • 多个副本集中在一台节点,影响高可用性;
  • 关键服务和日志采集服务部署在同一个节点,资源冲突;
  • 希望将某类应用部署到特定标签的节点上。

这时,我们就需要用到 Kubernetes 的调度利器 ——
节点亲和性(Node Affinity)与Pod亲和性(Pod Affinity / Anti-Affinity)


一、什么是 Affinity 和 Anti-Affinity?

Kubernetes 提供三种调度约束方式:

类型作用
Node Affinity控制 Pod 应该调度到哪些类型的 Node 上
Pod Affinity控制 Pod 应该与哪些其他 Pod 放在同一节点上(亲密)
Pod AntiAffinity控制 Pod 应该避免与哪些 Pod 放在一起(排斥)

这种机制给了开发者更强的调度控制权,尤其适合分布式服务、微服务架构场景。


二、Node Affinity:绑定到特定节点类型

1. 应用场景举例:

  • 只部署在 GPU 节点上
  • 绑定在 SSD 存储的节点
  • 根据地理区域(如北京/上海)调度

2. 配置示例

为 Node 添加标签:

kubectl label nodes node-1 disktype=ssd

Deployment 中配置 Affinity:

affinity:
  nodeAffinity:
    requiredDuringSchedulingIgnoredDuringExecution:
      nodeSelectorTerms:
      - matchExpressions:
        - key: disktype
          operator: In
          values:
          - ssd

3. 精讲:强 vs 弱 亲和性

  • requiredDuringSchedulingIgnoredDuringExecution: 必须匹配,否则调度失败;
  • preferredDuringSchedulingIgnoredDuringExecution: 尽量匹配,调度器优先考虑但不强制。

三、Pod Affinity 与 Anti-Affinity:Pod 与 Pod 的关系控制

1. 应用场景举例:

  • 多个微服务希望部署在一起(减少网络延迟)—— Pod Affinity;
  • 同一个应用的多个副本希望分布在不同节点上(防止单点故障)—— Pod Anti-Affinity。

2. Pod Anti-Affinity 示例(避免副本在同节点)

affinity:
  podAntiAffinity:
    requiredDuringSchedulingIgnoredDuringExecution:
    - labelSelector:
        matchExpressions:
        - key: app
          operator: In
          values:
          - myapp
      topologyKey: "kubernetes.io/hostname"

这段配置的含义是:

当前 Pod 不应该调度到已经运行有 app=myapp 的 Pod 的节点上。

如果你在 Deployment 中用了副本数 replicas: 3,调度器会尽量把它们分到不同节点。

3. Pod Affinity 示例(调度在一起)

affinity:
  podAffinity:
    requiredDuringSchedulingIgnoredDuringExecution:
    - labelSelector:
        matchLabels:
          app: frontend
      topologyKey: "kubernetes.io/hostname"

表示新 Pod 只会被调度到已有 app=frontend 的节点上。

适合如下情况:

  • Web 前端与缓存服务共节点部署
  • Agent/Sidecar 与主应用绑定部署

四、实战经验总结与避坑指南

✅ 实战建议一:合理使用 topologyKey

常见值包括:

  • kubernetes.io/hostname:按 Node 控制
  • topology.kubernetes.io/zone:按可用区(云厂商场景)

如果 key 写错,会导致调度器根本找不到合适节点,Pod 卡住 Pending。

✅ 实战建议二:Pod AntiAffinity + 副本数 控制高可用

如果你设置了 podAntiAffinity,但集群中 Node 数量不足以容纳副本,会导致部分 Pod 无法调度。

解决方案:

  • 确保集群节点数量 >= 副本数;
  • 或使用 preferredDuringSchedulingIgnoredDuringExecution 软约束。

✅ 实战建议三:搭配 taints/tolerations 精准调度

Affinity 是 “想要去哪里”,而 taints/tolerations 是 “禁止谁来”。
结合使用可以做出非常精细的调度控制策略!


五、总结:从默认调度到策略调度的跃迁

掌握 Affinity 系列调度机制,是从普通使用者向架构控制者迈进的重要一步。

用好 Node Affinity + Pod AntiAffinity:

✅ 可以保障高可用部署;

✅ 减少同类服务间资源抢占;

✅ 帮助你为服务性能和故障隔离提供强有力保障。