3. Pod亲和性基础:Node亲和性、Pod亲和性与反亲和性、required与preferred策略
在Kubernetes集群中,Pod的调度决策直接影响应用的高可用性与故障恢复能力。当Pod因存储挂载故障进入CrashLoop时,不合理的亲和性配置可能加剧问题——例如将多个副本调度到同一故障节点,或使Pod与依赖的存储Pod分离。本节系统梳理Pod亲和性的三大核心维度:Node亲和性、Pod亲和性与Pod反亲和性,并深入解析required(硬约束)与preferred(软偏好)策略的适用场景与配置方法。
3.1 亲和性体系总览
Kubernetes调度器通过亲和性规则将Pod调度到最合适的节点或与其他Pod协同部署。下表对比三种亲和性类型的核心差异:
| 类型 | 作用对象 | 匹配依据 | 典型场景 |
|---|---|---|---|
| Node亲和性 | Pod → Node | 节点标签(如topology.kubernetes.io/zone) |
将Pod调度到特定地域、硬件配置的节点 |
| Pod亲和性 | Pod → Pod | 目标Pod的标签与拓扑域 | 将Web Pod与Cache Pod部署在同一节点或可用区 |
| Pod反亲和性 | Pod → Pod | 目标Pod的标签与拓扑域 | 将同一应用的多个副本分散到不同节点或可用区 |
关键认知:Node亲和性控制Pod与节点的关系;Pod亲和性/反亲和性控制Pod之间的部署关系。在CrashLoop场景中,反亲和性常被用于避免单点故障,而亲和性则用于确保依赖服务的本地性。
3.2 Node亲和性:将Pod绑定到特定节点
Node亲和性允许运维人员基于节点标签定义调度规则,替代已被弃用的nodeSelector。它支持两种策略模式:
- requiredDuringSchedulingIgnoredDuringExecution(硬约束):调度时必须满足规则,否则Pod处于Pending状态。
- preferredDuringSchedulingIgnoredDuringExecution(软偏好):调度时优先满足规则,若不满足则降级到其他节点。
以下YAML示例展示一个要求Pod必须调度到SSD节点、且优先选择可用区A的配置:
apiVersion: v1
kind: Pod
metadata:
name: nginx-ssd
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: disk-type
operator: In
values:
- ssd
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 80
preference:
matchExpressions:
- key: topology.kubernetes.io/zone
operator: In
values:
- us-east-1a
containers:
- name: nginx
image: nginx:1.25
运维提示:硬约束(required)的
nodeSelectorTerms支持多个条件之间为“或”关系;每个matchExpressions内的多个条件为“与”关系。软偏好(preferred)的weight取值范围1~100,调度器按加权评分选择最优节点。
3.3 Pod亲和性与反亲和性:控制Pod间部署关系
Pod亲和性/反亲和性通过拓扑域(topologyKey)定义“距离”概念。常见的拓扑域包括kubernetes.io/hostname(节点级)、topology.kubernetes.io/zone(可用区级)。
3.3.1 Pod亲和性:将相关Pod调度到一起
以下配置确保cache Pod与web Pod部署在同一节点:
spec:
affinity:
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- web
topologyKey: kubernetes.io/hostname
3.3.2 Pod反亲和性:分散副本避免单点故障
对于高可用应用,反亲和性强制副本分布在不同节点:
spec:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- nginx
topologyKey: kubernetes.io/hostname
CrashLoop关联风险:当存储挂载故障发生时,若Pod反亲和性将副本分散到不同节点,但存储后端(如NFS、Ceph)本身存在单点瓶颈,可能导致所有副本同时CrashLoop。此时应结合Pod亲和性将应用Pod与存储代理Pod调度到同一拓扑域,减少网络延迟与故障域。
3.4 required与preferred策略对比
| 策略 | 调度行为 | 不满足时的后果 | 适用场景 |
|---|---|---|---|
| required | 强制匹配,不满足则调度失败 | Pod处于Pending状态,调度器持续重试 | 合规性要求(如数据本地化)、硬件依赖(如GPU节点) |
| preferred | 优先匹配,不满足则选择其他节点 | Pod正常调度,但评分较低 | 性能优化(如优先同可用区)、成本控制 |
最佳实践:在CrashLoop根因分析中,优先检查required规则是否因节点标签变更导致调度失败;对于preferred规则,关注调度器评分日志(
kube-scheduler日志中的plugin=NodeAffinity条目),确认软偏好是否被意外忽略。
3.5 亲和性调度流程SVG
下图展示调度器处理Pod亲和性规则的核心决策路径:
3.6 亲和性配置常见陷阱
- 拓扑域选择不当:使用
kubernetes.io/hostname作为反亲和性拓扑域时,若集群节点数少于副本数,部分副本将无法调度。 - 标签键值不匹配:Pod亲和性依赖目标Pod的标签,若目标Pod未打标签或标签变更,亲和性规则失效。
- required与preferred混用冲突:硬约束与软偏好同时定义时,软偏好仅在硬约束满足后生效,不会绕过硬约束。
- 忽略调度器日志:当Pod因亲和性规则Pending时,
kubectl describe pod的Events字段和调度器日志是首要排查入口。
CrashLoop排查联动:在存储挂载故障场景中,若Pod因Node亲和性被调度到无存储驱动的节点,或Pod反亲和性导致副本分散后无法同时访问本地存储,应优先调整亲和性规则而非直接修改存储配置。使用
kubectl get pods -o wide查看Pod所在节点,结合kubectl describe node确认节点标签与存储挂载状态。