上一章节了解了pod对node节点的选择,可以通过nodeSelector来进行选择节点进行部署,这一章节讲解另一种操作更精细化调度的属性:亲和性(Affinity) 和 反亲和性(Anti-Affinity)。
在 Kubernetes 中,亲和性(Affinity) 和 反亲和性(Anti-Affinity) 是控制 Pod 调度的核心机制,通过标签匹配实现资源的智能分布。
一、核心概念与分类
1. 亲和性(Affinity)
- 定义:通过规则定义 Pod 调度的偏好,使 Pod 趋向于与特定节点或 Pod 共存。
- 分类:
- 节点亲和性(Node Affinity):基于节点标签调度,例如将 GPU 计算任务调度到带有
gpu=true
标签的节点。 - Pod 亲和性(Pod Affinity):基于已存在 Pod 的标签调度,例如将前端服务与缓存服务部署到同一节点以减少网络延迟。
- 节点亲和性(Node Affinity):基于节点标签调度,例如将 GPU 计算任务调度到带有
2. 反亲和性(Anti-Affinity)
- 定义:通过规则定义 Pod 调度的排斥,使 Pod 远离特定节点或 Pod。
- 分类:
- 节点反亲和性:避免调度到特定标签的节点(如
zone=us-west
)。 - Pod 反亲和性:确保 Pod 分散到不同节点或拓扑域,例如数据库主从分离部署。
- 节点反亲和性:避免调度到特定标签的节点(如
二、调度规则类型
1. 硬性约束(Required)
- 作用:必须满足的条件,否则 Pod 无法调度。
- 语法示例:强制调度到 标签为 env=prod的node节点:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: env
operator: In
values: [prod]
1.1.nodeAffinity举例说明:
# cat required.yaml
apiVersion: v1
kind: Pod
metadata:
name: required-affinity-demo
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution: # 硬性约束
nodeSelectorTerms:
- matchExpressions:
- key: env
operator: In
values: [prod] # 必须调度到 env=prod 的节点
containers:
- name: nginx
image: m.daocloud.io/docker.io/nginx
通过下图可以看到,pod启动在node01这个节点,而这个节点我们上一章节的时候打标过env=prod,并且成功分配到了想要去的node节点
1.2.podAffinity举例说明:
上面是针对node进行打标亲和性,下面讲解一个针对pod进行打标亲和性
先将一个已经存在的pod进行打标 <app=nginx2>
kubectl label pod required-affinity-demo app=nginx2
查看yaml文件
# cat preferred.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-app
spec:
replicas: 3
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
affinity:
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution: # 硬性约束
- labelSelector:
matchExpressions:
- key: app
operator: In
values: [nginx2] # 必须与带有 app=nginx2 的 Pod 共存
topologyKey: kubernetes.io/hostname # 同一节点拓扑域
containers:
- name: web-container
image: m.daocloud.io/docker.io/nginx:latest
通过下图可以看到,已经和想要分配的pod分配到了一起。
2. 软性偏好(Preferred)
- 作用:优先满足的条件,若无匹配则降级调度。
- 语法示例:优先调度到env=dev的node节点:
特别说明:由于现在的环境只有一个master和一个node,默认master是不允许分配pod节点的,而env=dev又恰好是master节点的标签。所以这里需要提前将master设置为允许调度。
查看master是否允许调度
# 查看master节点是否允许调度,如果出现下面就说明不允许调度
# kubectl describe nodes k8s-master | grep Taint
Taints: node-role.kubernetes.io/control-plane:NoSchedule
# 设置master允许调度节点
# kubectl taint nodes k8s-master node-role.kubernetes.io/control-plane:NoSchedule-
node/k8s-master untainted
2.1 node节点的软性偏好
查看yaml文件并应用
# cat preferred.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-preferred-demo
labels:
app: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
affinity:
nodeAffinity: # 节点亲和性软性偏好
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 80 # 权重越高优先级越高(范围1-100)
preference:
matchExpressions:
- key: env
operator: In
values: [dev] # 优先调度到 env=dev 节点
containers:
- name: nginx
image: m.daocloud.io/docker.io/nginx
ports:
- containerPort: 80
验证结果,发现确实都调度到了master上
2.2 pod节点的软性偏好
上面的2个例子都是针对node的选择,那是否可以针对pod进行选择,答案当然也是可以。
先将一个已经存在的pod进行打标 <app=nginx2>,这一操作上面已经操作过,这里不再重复演示
查看yaml文件
# cat preferred2.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-preferred-pod-demo
labels:
app: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
affinity:
podAffinity: # Pod 反亲和性软性偏好
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: app
operator: In
values: [nginx2] # 选择app=nginx2的标签
topologyKey: kubernetes.io/hostname # 拓扑域为节点级别
containers:
- name: nginx
image: m.daocloud.io/docker.io/nginx
ports:
- containerPort: 80
查看结果,新创建的pod确实和打标的pod在一起
3. 反亲和性(Anti-Affinity)
学了上面的亲和性案例,那顾名思义就知道反亲和性就是指不分配到打标的pod一起。
3.1. 硬性约束
yaml演示:
apiVersion: v1
kind: Pod
metadata:
name: example-pod
spec:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- nginx2
topologyKey: "kubernetes.io/hostname" # 同一节点,在这里表示禁止同一节点部署多个pod
containers:
- name: myapp-container
image: m.daocloud.io/docker.io/nginx
查看结果,确实没有和app=nginx2的pod分配到一个节点上
3.2. 软性约束
yaml演示:
# cat anti2.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution: # 软亲和性规则
- weight: 100 # 权重值(范围 1-100)
podAffinityTerm:
labelSelector:
matchExpressions:
- key: app
operator: In
values: [nginx2]
topologyKey: kubernetes.io/hostname # 拓扑域(如节点、可用区)
containers:
- name: app
image: m.daocloud.io/docker.io/nginx
结果验证,与我们规划的一致,没有调度到app=nginx2的pod所在的node上
三、关键配置参数
1. 标签选择器(Label Selector)
- 操作符:
In
:标签值匹配(如app=nginx
)。NotIn
:标签值不匹配。Exists
/DoesNotExist
:标签键是否存在(不关注值)。
- 示例:匹配标签
app=backend
的 Pod:
labelSelector:
matchExpressions:
- key: app
operator: In
values: [backend]
2. 拓扑域(Topology Key)
- 作用:定义调度规则的生效范围,决定 Pod 分布的粒度。
- 常用值:
kubernetes.io/hostname
:单节点。failure-domain.beta.kubernetes.io/zone
:可用区。failure-domain.beta.kubernetes.io/region
:地域。
- 示例:跨可用区部署数据库副本:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- topologyKey: failure-domain.beta.kubernetes.io/zone
四、典型应用场景
1. 高可用性设计
- Pod 反亲和性:将同一应用的多个副本分散到不同节点或可用区,避免单点故障。
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values: [my-app]
topologyKey: kubernetes.io/hostname
2. 资源优化
- 节点亲和性:将计算密集型任务(如 AI 训练)调度到 GPU 节点,存储任务调度到 SSD 节点。
3. 服务协同
- Pod 亲和性:将关联服务(如前端与缓存)部署到同一节点,减少网络延迟:
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: tier
operator: In
values: [cache]
topologyKey: kubernetes.io/hostname
4. 多租户隔离
- 节点反亲和性:将不同团队的 Pod 隔离到不同节点,避免资源争抢。
五、注意事项与调试
1. 常见问题
- 调度失败:检查标签是否匹配(
kubectl describe pod
查看 Events 报错)。 - 规则冲突:硬性规则优先级高于软性规则,需避免矛盾配置。
- 拓扑域不匹配:确保
topologyKey
对应的标签已正确标注在节点上。
2. 最佳实践
- 标签标准化:使用
env=prod
、app=frontend
等统一命名规范。 - 动态调整:节点标签更新后,需重新调度 Pod(如删除后重建)。
- 组合策略:先通过反亲和性分散 Pod,再通过亲和性优化局部性能。
六、与 nodeSelector
的对比
特性 | nodeSelector | 亲和性/反亲和性 |
---|---|---|
灵活性 | 仅支持简单键值匹配 | 支持复杂逻辑(AND/OR、权重) |
拓扑域支持 | 不支持 | 支持跨节点、可用区、地域 |
策略类型 | 仅硬性约束 | 支持硬性约束 + 软性偏好 |
通过灵活运用亲和性与反亲和性,可实现集群资源的精细化调度,平衡性能、可用性与成本。实际配置时需结合业务需求,优先保障关键服务的稳定性。