一、前言
在上一篇文章里,我们了解了 Pod 中的nodeName和nodeSelector这两个属性,通过它们能够指定 Pod 调度到哪个 Node 上。今天,我们将进一步深入探索 Pod 相关知识。这部分内容不仅信息量较大,理解起来也有一定难度,如果在学习过程中感觉吃力,建议大家反复研读,以便更好地掌握。
二、亲和性
在 Kubernetes 的 Pod 调度场景中,尽管我们可以借助nodeName和nodeSelector指定 Pod 的调度节点,但它们存在明显的局限性。nodeName依赖节点名称进行调度,nodeSelector则基于节点标签来确定调度目标,二者都不够灵活,扩展性也欠佳。那么,是否存在其他更丰富的属性能够助力 Pod 调度呢?例如,能否依据 CPU、内存等资源属性来决定 Pod 的部署节点?作为强大的容器编排工具,Kubernetes 显然考虑到了这一需求,接下来我们将深入学习的 “亲和性”,便是解决这一问题的关键。
亲和性同样用于 Pod 的节点调度,与nodeSelector有一定相似之处,但亲和性的优势更为显著。它支持定义多个调度规则,还能为这些规则设定优先级,从而实现更精细的调度控制。亲和性主要分为节点亲和性和 Pod 亲和性。简单来讲,亲和性就是一组预先设定的规则,其作用是明确告知 Kubernetes 该如何调度 Pod。
其中,节点亲和性又细分为软亲和性和硬亲和性。软亲和性是一种较为灵活的调度策略,当多个节点都满足设定条件时,它会优先选择优先级更高的节点;若所有节点都无法完全满足条件,Pod 依然可以被调度到其他相对合适的节点。打个比方,这就像是你向 Kubernetes 提出请求:“请帮我把 Pod 调度到某个节点上,这个节点最好能满足条件 1 和条件 2,如果实在没有完全符合的,那就找一个最接近要求的节点部署吧。”
而硬亲和性则截然不同,它是一种严格的调度策略。只有当节点完全满足设定的所有条件时,Pod 才会被调度到该节点;若不存在任何满足条件的节点,Pod 将无法运行,这正如成语 “宁缺毋滥” 所表达的含义。
软亲和性例子:
女生A和媒婆说:我要找个男朋友,条件1:身高1米8;条件2:有车有房,如果两者都不满足那么性格好就行了。
硬亲和性例子:我要个男朋友条件1:身高1米8;条件2:有车有房,这两个条件缺一不可,否则我宁可单身!
1、先查看一下描述
kubectl explain pods.spec.affinity
亲和性总共有3个字段:节点亲和性、pod亲和性、pod反亲和性
- nodeAffinity(节点亲和性):通过标签选择器和表达式来约束Pod
- podAffinity(pod亲和性):用于指定Pod应该被部署到符合某些条件的Pod所在的Node:例如我们将多个业务关联性高的Pod部署在同一个节点。
- podAntiAffinity(Pod反亲和性):用于指定Pod应该避免部署到符合某些条件的Pod所在的Node,场景:例如避免把相似的Pod都部署到同一个Node,从而可能产生单点故障。
三、节点亲和性(nodeAffinity)
1、解释
kubectl explain pods.spec.affinity
这里有两个字段
- preferredDuringSchedulingIgnoredDuringExecution :软亲和性
它是一种建议性的规则,Kubernetes 调度器会尽量依据此规则来调度 Pod 到符合条件的节点上,但并非强制要求。若不存在满足规则的节点,Pod 依然可以被调度到其他节点。此规则在调度阶段起作用,调度器会优先考虑将 Pod 调度到满足软亲和性规则的节点上。而在 Pod 运行期间,一旦节点的标签发生变化,导致不再符合软亲和性规则,Pod 不会被驱逐。
- requiredDuringSchedulingIgnoredDuringExecution:硬亲和性
和软亲和性不同,硬亲和性是一种强制的规则,要求调度器在调度的时候必须满足一定的规则,否则将不会进行调度,pod会一直处于pending状态。同时运行期间如果节点的标签发生变化导致不符合规则,Pod会被驱逐。
2、实操
我们现在有两个节点,分别是node2和node3,其中node2包含标签cpu=high ,而node3包含标签cpu=low,我们用这个标签来测试节点亲和性。
1、软亲和性
(1)我们先测试软亲和性,即期望pod会被调度到cpu=high的节点,资源清单如下
apiVersion: v1
kind: Pod
metadata:name: buybox-pod
spec:containers:- name: buybox-containerimage: buybox:1.28imagePullPolicy: IfNotPresentaffinity:nodeAffinity:preferredDuringSchedulingIgnoredDuringExecution:- weight: 100preference:matchExpressions:- key: cpuoperator: Invalues:- high
接下来我们使用命令 apply -f busybox.yaml 来创建这个pod,预期的效果是会被调度到node2节点,结果如下
可以看到和我们的预期一样,Pod被调度到了node2节点上。
(2)我们修改一下资源清单,写一个不存在的标签值看是否能够调度。预期结果:也能正常调度只不过会在node2和node3中随机选择。
apiVersion: v1
kind: Pod
metadata:name: buybox-pod
spec:containers:- name: buybox-containerimage: buybox:1.28imagePullPolicy: IfNotPresentaffinity:nodeAffinity:preferredDuringSchedulingIgnoredDuringExecution:- weight: 100preference:matchExpressions:- key: cpuoperator: Invalues:- best
调度结果:node3 (不用管这里的状态是 ErrImagePull,这个是笔者网络问题导致拉取镜像有问题,但是和调度没关系)
(3)小结
案例1 | 预期结果 | 实际结果 |
---|---|---|
正常情况,标签cpu=high | 节点2 | 节点2 |
都不满足,标签cpu=best | 节点2或者节点3 | 节点3 |
小结:软亲和性是一种建议,即如果满足要求就选择某个节点,若不存在满足规则的节点,Pod 依然可以被调度到其他节点。
1、硬亲和性
还是刚才的案例,我们把软亲和性换成硬亲和性
(1)cpu=high 我们预期是调度到node2
apiVersion: v1
kind: Pod
metadata:name: buybox-pod
spec:containers:- name: buybox-containerimage: buyboxports:- containerPort: 80affinity:nodeAffinity:requiredDuringSchedulingIgnoredDuringExecution:nodeSelectorTerms:- matchExpressions:- key: cpuoperator: Invalues:- high
结果调度了node2,符合预期
(2)我们修改规则,将values改成不存的值,预期无法调度到任何一个节点
apiVersion: v1
kind: Pod
metadata:name: buybox-pod
spec:containers:- name: buybox-containerimage: buyboxports:- containerPort: 80affinity:nodeAffinity:requiredDuringSchedulingIgnoredDuringExecution:nodeSelectorTerms:- matchExpressions:- key: cpuoperator: Invalues:- best
结果如下
可以看到状态一直处于Pending状态,查看一下pod详细信息,使用命令 kubectl describe pods buybox-pod
错误信息:
Warning FailedScheduling 12s (x3 over 89s) default-scheduler 0/3 nodes are available: 1 node(s) had taint {node-role.kubernetes.io/master: }, that the pod didn’t tolerate, 2 node(s) didn’t match Pod’s node affinity.
调度失败了,因为3个节点都不满足亲和性条件。
小结:
案例1 | 预期结果 | 实际结果 |
---|---|---|
正常情况,标签cpu=high | 节点2 | 节点2 |
都不满足,标签cpu=best | 无法调度 | 无法调度 |
四、总结
本文聚焦 Kubernetes 的节点亲和性。在 Pod 调度中,以往的 nodeName 和 nodeSelector 存在局限,亲和性则更为强大,其中节点亲和性包含软、硬亲和性。
软亲和性是建议性规则。测试时,期望调度到cpu=high的节点,Pod 成功被调度到 node2;设置不存在的标签值,Pod 也能在现有节点随机调度,如被调度到 node3,说明无满足节点时 Pod 仍可调度。硬亲和性requiredDuringSchedulingIgnoredDuringExecution是强制规则。同样的测试场景下,要求调度到cpu=high的节点,Pod 被调度到 node2;设置不存在的标签值,Pod 处于 Pending 状态,调度失败,表明不满足条件时 Pod 无法调度。
学习节点亲和性的软、硬亲和性,有助于精准控制 Pod 部署,提升集群资源利用率和应用稳定性,为 Kubernetes 复杂应用部署管理筑牢基础。下一篇我们将继续学习亲和性,希望对你有所帮助