【kubernetes】--NodeAffinity调度pod
一、NodeAffinity 介绍NodeAffinity中文叫节点亲和性用于控制 Pod 更倾向于、或者必须调度到哪些 Node 上。它基于 Node 的label工作。简单理解Node label给节点打标签 NodeAffinityPod 根据节点标签选择节点例如节点有标签workloadwebPod 可以通过nodeAffinity指定只调度到 workloadweb 的节点NodeAffinity 和nodeSelector很像但比nodeSelector更灵活。nodeSelector只能做简单等值匹配nodeSelector:workload:webnodeAffinity可以支持In、NotIn、Exists、DoesNotExist、Gt、Lt等条件。二、节点 Label 检测与管理1. 查看节点 Label查看所有节点的 labelkubectl get nodes --show-labels查看某个节点的 labelkubectl getnodenode01 --show-labels使用jq查看更清晰kubectl getnodenode01-ojson|jq.metadata.labels2. 添加节点 Label给node01添加标签kubectl labelnodenode01workloadweb再添加一个高性能节点标签kubectl labelnodenode01 node-performancehigh3. 修改节点 Label如果标签已经存在需要加--overwritekubectl labelnodenode01workloadapi--overwrite4. 删除节点 Label删除workload标签kubectl labelnodenode01 workload-删除node-performance标签kubectl labelnodenode01 node-performance-三、NodeAffinity 的两种类型NodeAffinity 常用两种requiredDuringSchedulingIgnoredDuringExecution preferredDuringSchedulingIgnoredDuringExecution这两个字段名字比较长可以拆开理解DuringScheduling调度时检查 IgnoredDuringExecutionPod 运行后忽略变化不会因为节点 label 改变而驱逐 Pod1. requiredDuringSchedulingIgnoredDuringExecution硬性要求。含义调度时必须满足条件。 如果没有符合条件的节点Pod 会 Pending。 Pod 已经运行后即使节点 label 变化也不会因此驱逐 Pod。示例affinity:nodeAffinity:requiredDuringSchedulingIgnoredDuringExecution:nodeSelectorTerms:-matchExpressions:-key:workloadoperator:Invalues:-web表示Pod 必须调度到带有 workloadweb 标签的节点。2. preferredDuringSchedulingIgnoredDuringExecution软性偏好。含义调度时尽量满足条件。 如果没有符合条件的节点也可以调度到其他节点。 Pod 已经运行后即使节点 label 变化也不会因此驱逐 Pod。示例affinity:nodeAffinity:preferredDuringSchedulingIgnoredDuringExecution:-weight:100preference:matchExpressions:-key:node-performanceoperator:Invalues:-high表示Pod 优先调度到 node-performancehigh 的节点。 如果没有合适节点也可以调度到其他节点。四、operator 匹配规则operator用来判断节点 label 是否符合条件。假设节点有这些 labelworkloadweb zoneshanghai cpu8 gputrue1. Inlabel 的值在values里就匹配。-key:workloadoperator:Invalues:-web-api匹配workloadweb workloadapi不匹配workloaddb 没有 workload 标签2. NotInlabel 不存在或者 label 的值不在values里就匹配。-key:workloadoperator:NotInvalues:-db匹配workloadweb workloadapi 没有 workload 标签不匹配workloaddb3. Exists只要存在这个 label key 就匹配不关心 value。-key:gpuoperator:Exists匹配gputrue gpufalse gpu任何值不匹配没有 gpu 标签4. DoesNotExist只要不存在这个 label key 就匹配。-key:gpuoperator:DoesNotExist匹配没有 gpu 标签不匹配gputrue gpufalse5. Gtlabel 的值大于指定数字就匹配。-key:cpuoperator:Gtvalues:-4匹配cpu8 cpu16不匹配cpu2 cpuabc 没有 cpu 标签6. Ltlabel 的值小于指定数字就匹配。-key:cpuoperator:Ltvalues:-16匹配cpu4 cpu8不匹配cpu16 cpu32 cpuabc 没有 cpu 标签注意Exists 和 DoesNotExist 不需要写 values。 Gt 和 Lt 的 values 只能写一个值并且 label value 必须能当数字解析。五、多个条件的关系1. 同一个 matchExpressions 里的多个条件是 AND示例matchExpressions:-key:workloadoperator:Invalues:-web-key:zoneoperator:Invalues:-shanghai表示节点必须同时满足 workloadweb 和 zoneshanghai。2. 多个 nodeSelectorTerms 之间是 OR示例nodeSelectorTerms:-matchExpressions:-key:workloadoperator:Invalues:-web-matchExpressions:-key:workloadoperator:Invalues:-api表示节点满足 workloadweb 或 workloadapi 都可以。六、NodeAffinity 使用示例示例 1强制 Pod 调度到指定节点池场景生产中有一批 web 专用节点只希望 web 服务运行到这些节点上。1. 给 node01 打标签kubectl labelnodenode01workloadweb--overwrite查看kubectl getnodenode01 --show-labels2. 创建 Deployment保存为web-required-demo.yamlapiVersion:apps/v1kind:Deploymentmetadata:name:web-required-demospec:replicas:2selector:matchLabels:app:web-required-demotemplate:metadata:labels:app:web-required-demospec:affinity:nodeAffinity:requiredDuringSchedulingIgnoredDuringExecution:nodeSelectorTerms:-matchExpressions:-key:workloadoperator:Invalues:-webcontainers:-name:pauseimage:registry.aliyuncs.com/google_containers/pause:3.9部署kubectl apply-fweb-required-demo.yaml查看 Pod 调度位置kubectl get pods-owide-lappweb-required-demo预期Pod 会调度到带有 workloadweb 标签的节点。如果集群里只有node01有这个标签Pod 就会调度到node01。3. 验证 required 是硬限制删除node01的workload标签kubectl labelnodenode01 workload-重新创建一个新 Podkubectl delete pod-lappweb-required-demo查看kubectl get pods-owide-lappweb-required-demo如果没有任何节点带workloadweb新 Pod 会Pending。查看 Pending 原因kubectl describe podpod-name常见事件类似node(s) didnt match Pods node affinity/selector示例 2优先调度到高性能节点资源不足时允许兜底场景希望业务优先运行在高性能节点上。 但是高性能节点资源不够时也允许调度到普通节点。1. 给 node01 打高性能标签kubectl labelnodenode01 node-performancehigh--overwrite查看kubectl getnodenode01 --show-labels2. 创建 Deployment保存为web-preferred-demo.yamlapiVersion:apps/v1kind:Deploymentmetadata:name:web-preferred-demospec:replicas:3selector:matchLabels:app:web-preferred-demotemplate:metadata:labels:app:web-preferred-demospec:affinity:nodeAffinity:preferredDuringSchedulingIgnoredDuringExecution:-weight:100preference:matchExpressions:-key:node-performanceoperator:Invalues:-highcontainers:-name:pauseimage:registry.aliyuncs.com/google_containers/pause:3.9部署kubectl apply-fweb-preferred-demo.yaml查看 Pod 调度位置kubectl get pods-owide-lappweb-preferred-demo预期调度器会优先选择 node-performancehigh 的节点。 如果该节点资源不足Pod 仍可以调度到其他节点。3. 验证 preferred 是软限制删除高性能标签kubectl labelnodenode01 node-performance-重新创建 Podkubectl delete pod-lappweb-preferred-demo查看kubectl get pods-owide-lappweb-preferred-demo预期Pod 不会 Pending仍然可以调度到其他 Ready 节点。这就是preferred和required的核心区别。七、案例1. 专用业务节点池需求把订单服务固定运行在订单节点池。节点标签kubectl labelnodenode01workloadorder--overwritePod 配置affinity:nodeAffinity:requiredDuringSchedulingIgnoredDuringExecution:nodeSelectorTerms:-matchExpressions:-key:workloadoperator:Invalues:-order适用场景核心业务隔离 专用节点池 特殊硬件节点 固定机型节点2. 优先同可用区调度需求服务优先调度到 shanghai 可用区减少跨区访问。节点标签kubectl labelnodenode01zoneshanghai--overwritePod 配置affinity:nodeAffinity:preferredDuringSchedulingIgnoredDuringExecution:-weight:100preference:matchExpressions:-key:zoneoperator:Invalues:-shanghai适用场景同机房优先 同可用区优先 降低网络延迟 但不希望资源不足时直接 Pending3. 避免调度到特殊节点需求普通业务不要调度到 GPU 节点。节点标签kubectl labelnodenode01 node-typegpu--overwritePod 配置affinity:nodeAffinity:requiredDuringSchedulingIgnoredDuringExecution:nodeSelectorTerms:-matchExpressions:-key:node-typeoperator:NotInvalues:-gpu说明NotIn 会匹配没有 node-type 标签的节点或者 node-type 不是 gpu 的节点。更严格的专用节点隔离可以配合taint/toleration使用。