Kubernetes 亲和性(Affinity)和反亲和性(Anti-Affinity)是用于控制 Pod 调度的机制,它们允许用户定义 Pod 与节点或其他 Pod 之间的关系,从而影响调度决策。
亲和性类型
1. 节点亲和性(Node Affinity)
节点亲和性用于控制 Pod 调度到哪些节点上。
requiredDuringSchedulingIgnoredDuringExecution
硬性要求,Pod 必须调度到满足条件的节点上,否则调度失败。
yamlapiVersion: v1 kind: Pod metadata: name: with-node-affinity spec: affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: kubernetes.io/e2e-az-name operator: In values: - us-west-1a containers: - name: my-container image: nginx
preferredDuringSchedulingIgnoredDuringExecution
软性偏好,调度器优先选择满足条件的节点,但如果没有满足条件的节点,也可以调度到其他节点。
yamlapiVersion: v1 kind: Pod metadata: name: with-node-affinity spec: affinity: nodeAffinity: preferredDuringSchedulingIgnoredDuringExecution: - weight: 1 preference: matchExpressions: - key: disktype operator: In values: - ssd containers: - name: my-container image: nginx
2. Pod 亲和性(Pod Affinity)
Pod 亲和性用于控制 Pod 调度到哪些节点上,基于已经运行在该节点上的 Pod。
requiredDuringSchedulingIgnoredDuringExecution
yamlapiVersion: v1 kind: Pod metadata: name: with-pod-affinity spec: affinity: podAffinity: requiredDuringSchedulingIgnoredDuringExecution: - labelSelector: matchExpressions: - key: security operator: In values: - S1 topologyKey: topology.kubernetes.io/zone containers: - name: my-container image: nginx
preferredDuringSchedulingIgnoredDuringExecution
yamlapiVersion: v1 kind: Pod metadata: name: with-pod-affinity spec: affinity: podAffinity: preferredDuringSchedulingIgnoredDuringExecution: - weight: 100 podAffinityTerm: labelSelector: matchExpressions: - key: security operator: In values: - S2 topologyKey: topology.kubernetes.io/zone containers: - name: my-container image: nginx
3. Pod 反亲和性(Pod Anti-Affinity)
Pod 反亲和性用于控制 Pod 不调度到哪些节点上,基于已经运行在该节点上的 Pod。
requiredDuringSchedulingIgnoredDuringExecution
yamlapiVersion: v1 kind: Pod metadata: name: with-pod-antiaffinity spec: affinity: podAntiAffinity: requiredDuringSchedulingIgnoredDuringExecution: - labelSelector: matchExpressions: - key: app operator: In values: - web topologyKey: kubernetes.io/hostname containers: - name: my-container image: nginx
preferredDuringSchedulingIgnoredDuringExecution
yamlapiVersion: v1 kind: Pod metadata: name: with-pod-antiaffinity spec: affinity: podAntiAffinity: preferredDuringSchedulingIgnoredDuringExecution: - weight: 100 podAffinityTerm: labelSelector: matchExpressions: - key: app operator: In values: - web topologyKey: kubernetes.io/hostname containers: - name: my-container image: nginx
操作符类型
-
In:标签的值在给定的列表中
-
NotIn:标签的值不在给定的列表中
-
Exists:标签存在
-
DoesNotExist:标签不存在
-
Gt:标签的值大于给定值(仅适用于数值)
-
Lt:标签的值小于给定值(仅适用于数值)
拓扑域键(Topology Key)
拓扑域键用于定义节点的分组方式,常见的拓扑域键包括:
-
kubernetes.io/hostname:按主机名分组
-
topology.kubernetes.io/zone:按可用区分组
-
topology.kubernetes.io/region:按区域分组
-
node.kubernetes.io/instance-type:按实例类型分组
亲和性规则的行为
调度阶段(During Scheduling)
- required:硬性要求,必须满足
- preferred:软性偏好,优先满足
执行阶段(During Execution)
- Ignored:Pod 运行后,如果条件不再满足,不影响已运行的 Pod
- Required:Pod 运行后,如果条件不再满足,需要驱逐 Pod(目前不支持)
亲和性 vs nodeSelector
| 特性 | nodeSelector | 节点亲和性 |
|---|---|---|
| 复杂度 | 简单 | 复杂 |
| 灵活性 | 低 | 高 |
| 支持的操作符 | 等值 | 多种操作符 |
| 优先级 | 无 | 支持权重 |
使用场景
节点亲和性使用场景
-
硬件要求:将 Pod 调度到具有特定硬件的节点(如 GPU、SSD)
-
区域要求:将 Pod 调度到特定区域或可用区
-
操作系统要求:将 Pod 调度到运行特定操作系统的节点
Pod 亲和性使用场景
-
通信优化:将需要频繁通信的 Pod 调度到同一节点,减少网络延迟
-
依赖关系:将依赖的 Pod 调度到同一节点,提高性能
-
数据局部性:将 Pod 调度到存储数据的节点附近
Pod 反亲和性使用场景
-
高可用性:将相同应用的 Pod 分散到不同节点,避免单点故障
-
资源竞争:避免资源密集型 Pod 调度到同一节点
-
故障隔离:将不同应用的 Pod 分散到不同节点,减少故障影响范围
最佳实践
-
合理使用硬性要求:避免过度使用 required 规则,可能导致调度失败
-
设置合理的权重:为 preferred 规则设置合适的权重,影响调度决策
-
使用标签和注解:为节点和 Pod 添加有意义的标签,便于使用亲和性规则
-
监控调度结果:监控 Pod 的调度情况,确保亲和性规则按预期工作
-
结合污点和容忍度:结合使用亲和性和污点/容忍度,实现更精细的调度控制
-
避免过度复杂:避免创建过于复杂的亲和性规则,影响调度性能
-
测试规则:在非生产环境测试亲和性规则,确保正确性
示例:高可用 Web 应用
yamlapiVersion: apps/v1 kind: Deployment metadata: name: web-app spec: replicas: 3 selector: matchLabels: app: web template: metadata: labels: app: web spec: affinity: podAntiAffinity: requiredDuringSchedulingIgnoredDuringExecution: - labelSelector: matchExpressions: - key: app operator: In values: - web topologyKey: kubernetes.io/hostname nodeAffinity: preferredDuringSchedulingIgnoredDuringExecution: - weight: 100 preference: matchExpressions: - key: disktype operator: In values: - ssd containers: - name: web image: nginx ports: - containerPort: 80
这个示例确保:
- 每个 Web Pod 调度到不同的节点(高可用性)
- 优先选择具有 SSD 的节点(性能优化)