当前位置: 首页 > news >正文

Kubernetes Pod 调度策略:从基础到进阶

文章目录

  • 环境
  • Kubernetes 部署
  • Kubernetes Pod 调度策略
  • Kubernetes Pod 调度策略对照表
  • 调度流程经历阶段
  • 案例展示
    • 生成yaml文件
    • 默认调度
    • 节点选择器
      • 为节点添加标签
      • 编写 Deployment 配置文件
      • 应用资源并查看调度结果
    • Node Affinity(节点亲和性)
      • 为节点添加标签
      • 硬约束(Required)
      • 软约束(Preferred)
        • 先不设置标签
        • 设置标签
      • 运算符支持的类型
    • 污点与容忍(Taints & Tolerations)
      • 污点(Taint)
        • 添加污点的命令:
      • 容忍(Toleration)
        • 示例 YAML:
      • 三种 Effect 类型(效果)
      • 案例演示
        • 给所有节点打上污点
        • 没有容忍的 Pod(会调度失败)
        • 有容忍的 Pod(调度成功)
    • Pod Affinity(Pod 亲和性)与 Pod Anti-Affinity(反亲和性)
      • Pod Affinity(亲和性)
        • 示例:调度到和标签为 app=nginx 的 Pod 相同节点的 Pod 上(硬约束)
      • Pod Anti-Affinity(反亲和性)
        • 示例:调度到与标签为 app=nginx 的 Pod 不同节点上(软约束)
      • 拓扑域 TopologyKey 说明
  • 总结
    • ✅ 默认调度策略
    • ✅ NodeSelector
    • ✅ Node Affinity(节点亲和性)
    • ✅ Pod Affinity / Anti-Affinity(Pod 间亲和/反亲和)
    • ✅ Taints and Tolerations(污点与容忍)
    • ✅ 自定义调度器(Custom Scheduler)
    • 📌 建议使用场景总结


环境

[root@10-255-101-217 ~]# kubectl get nodes -o wide 
NAME             STATUS   ROLES                  AGE   VERSION   INTERNAL-IP      EXTERNAL-IP   OS-IMAGE                KERNEL-VERSION               CONTAINER-RUNTIME
10-255-101-152   Ready    <none>                 24h   v1.22.0   10.255.101.152   <none>        CentOS Linux 7 (Core)   4.18.9-1.el7.elrepo.x86_64   containerd://1.4.3
10-255-101-216   Ready    <none>                 24h   v1.22.0   10.255.101.216   <none>        CentOS Linux 7 (Core)   4.18.9-1.el7.elrepo.x86_64   containerd://1.4.3
10-255-101-217   Ready    control-plane,master   24h   v1.22.0   10.255.101.217   <none>        CentOS Linux 7 (Core)   4.18.9-1.el7.elrepo.x86_64   containerd://1.4.3
10-255-101-82    Ready    <none>                 24h   v1.22.0   10.255.101.82    <none>        CentOS Linux 7 (Core)   4.18.9-1.el7.elrepo.x86_64   containerd://1.4.3
[root@10-255-101-217 ~]# 

Kubernetes 部署

一台 Master 多节点玩转 Kubernetes:sealos 一键部署实践

下边的案例基于这个部署方式以及环境进行演示

Kubernetes Pod 调度策略

  • 默认调度(Default Scheduling)
    在没有额外配置的情况下,kube-scheduler 会根据 Pod 的资源请求(requests)和节点的可用资源(allocatable)进行自动调度。这是大多数常规应用场景的默认策略,适合无需精细控制资源分配的情况。

  • 节点选择器(NodeSelector)
    通过在 Pod 规格中设置 nodeSelector: { key: value },可以强制 Pod 仅被调度到具有指定标签的节点。这是一种硬性匹配策略,适用于将 Pod 部署到具有特定硬件、特定配置或专用节点的场景。

  • 节点亲和性(Node Affinity)
    节点亲和性允许用户基于节点的标签进行更复杂的软/硬约束。它包含两种类型:

    • requiredDuringSchedulingIgnoredDuringExecution(硬性约束):要求 Pod 只能被调度到满足条件的节点上。
    • preferredDuringSchedulingIgnoredDuringExecution(软性偏好):Pod 会尝试被调度到满足条件的节点上,但若无法满足条件,仍会被调度到其他节点。
      这种方法可以让调度策略更加灵活,特别是在需要对节点进行复杂匹配或按优先级排序时。
  • 污点与容忍(Taints & Tolerations)
    通过在节点上添加污点,防止不容忍的 Pod 被调度到该节点。Pod 需要配置 tolerations,以接受特定污点。这是一种细粒度的控制机制,广泛应用于专用节点的隔离、故障剔除、热点节点流量控制等场景。

  • Pod 亲和性与反亲和性(Pod Affinity & Anti-Affinity)

    • Pod Affinity:确保相关 Pod 部署在同一节点或拓扑域内,以提升性能或数据本地性。
    • Pod Anti-Affinity:确保相关 Pod 不部署在同一节点,适用于高可用性要求,避免单点故障。
      使用 Pod 亲和性和反亲和性可以精确控制 Pod 的分布策略,增强系统的弹性和容错性。
  • 自定义调度器与调度扩展(Custom Scheduler & Scheduler Extenders)
    如果 Kubernetes 的默认调度器无法满足特定需求,可以通过自定义调度器或扩展插件来实现个性化调度。例如,可以指定 schedulerName: <your-scheduler>,或使用调度扩展与外部系统进行集成,适用于特殊资源(如 GPU、Spot 实例)或复杂调度逻辑的场景。


Kubernetes Pod 调度策略对照表

策略中文名称策略英文术语简要描述适用场景配置方式(简化)
默认调度Default Schedulingkube-scheduler 根据资源需求和节点可用性自动分配 Pod无特殊调度需求的常规应用无需配置
节点选择器NodeSelector通过节点标签(Label)进行硬性匹配,Pod 只会被调度到指定标签的节点上将 Pod 部署到具备特定硬件或配置的节点nodeSelector: { key: value }
节点亲和性Node Affinity基于节点标签的软/硬约束,支持更灵活的偏好与必选规则对节点标签有复杂匹配需求,需在节点间进行偏好排序使用 affinity.nodeAffinity 配置
污点与容忍Taints & Tolerations节点通过污点阻止不容忍的 Pod 被调度,Pod 通过容忍接受污点专用节点隔离、故障节点剔除、热点节点流控等节点 taint + Pod tolerations
Pod 亲和性Pod Affinity控制 Pod 之间的协同部署,确保相关 Pod 被调度到同一节点或拓扑域中提高性能或数据本地性,相关服务部署在一起使用 affinity.podAffinity 配置
Pod 反亲和性Pod Anti-Affinity控制 Pod 之间的分散部署,避免相关 Pod 被调度到同一节点高可用场景下避免单点故障,确保 Pod 分布在不同节点上使用 affinity.podAntiAffinity 配置
自定义调度器(未进行实践,博文无案例)Custom Scheduler / Extenders使用插件或替换方案,支持 GPU、Spot 实例等特殊资源的定制调度逻辑企业级集群,需自定义调度算法或集成外部调度系统schedulerName: 自定义调度器名称

调度流程经历阶段

  1. PreFilter(预处理):收集 Pod 相关信息,检查必须满足的前置条件。
  2. Filter(过滤):通过各类 Filter 插件 排除不符合条件的节点,例如资源不足、NodeSelector、Node Affinity、Taints 等规则。
  3. PostFilter(后过滤,可选):当没有可行节点时触发,如抢占(Preemption)机制,尝试腾出资源。
  4. PreScore:为 Score 插件 准备共享状态。
  5. Score(打分):对剩余节点执行各类 Score 插件,根据算法(如资源均衡、拓扑感知等)对节点进行打分。
  6. NormalizeScore:将各插件打分归一化到 0–100。
  7. Reserve:暂时保留选中的节点,防止并发 Pod 冲突。
  8. Permit:最终审批,可用于等待或速率限制等场景。
  9. PreBindBind(绑定):将 Pod.spec.nodeName 设置为选定节点,完成调度。
  10. PostBind(绑定后,可选):信息收集或清理工作。

仅供参考
在这里插入图片描述


案例展示

生成yaml文件

kubectl create deployment test-nginx \--image=nginx \--replicas=2 \--port=80 \-n default\--dry-run=client \-o yaml \> nginx-deploy.yaml

各参数含义

参数作用说明
kubectl create deployment创建一个 Deployment 资源
test-nginxDeployment 的名称
--image=nginx指定容器镜像为 nginx
--replicas=2设置副本数为 2 个 Pod
--port=80指定容器对外暴露的端口(虽然这个参数不一定反映在 YAML 中)
-n default指定命名空间为 default
--dry-run=client客户端验证,不真正创建资源
-o yaml以 YAML 格式输出资源清单
> nginx-deploy.yaml将输出重定向到文件 nginx-deploy.yaml

生成的yaml文件

apiVersion: apps/v1
kind: Deployment
metadata:creationTimestamp: nulllabels:app: test-nginxname: test-nginxnamespace: default
spec:replicas: 2selector:matchLabels:app: test-nginxstrategy: {}template:metadata:creationTimestamp: nulllabels:app: test-nginxspec:containers:- image: nginxname: nginxports:- containerPort: 80resources: {}
status: {}

YAML 关键字段说明

字段路径含义说明
spec.replicas: 2定义 Deployment 期望运行 2 个 Pod 实例
spec.selector.matchLabels用于匹配 Pod 标签,Deployment 用于关联控制的 Pod
spec.template.metadata.labelsPod 模板的标签,与 selector 匹配
spec.template.spec.containers定义容器镜像、端口、资源等关键参数
ports.containerPort: 80定义容器对外开放的端口

默认调度

[root@10-255-101-217 ~]# kubectl get pods
No resources found in default namespace.
[root@10-255-101-217 ~]# kubectl apply -f nginx-deploy.yaml 
deployment.apps/test-nginx created
[root@10-255-101-217 ~]# kubectl get pods -o wide 
NAME                          READY   STATUS    RESTARTS   AGE   IP               NODE             NOMINATED NODE   READINESS GATES
test-nginx-6f5d5f6564-gbgc6   1/1     Running   0          13s   192.168.154.1    10-255-101-82    <none>           <none>
test-nginx-6f5d5f6564-jpbhl   1/1     Running   0          13s   192.168.154.65   10-255-101-152   <none>           <none>
[root@10-255-101-217 ~]# 

kube-scheduler 默认调度器会根据集群中各节点的资源使用情况(如 CPU、内存等),自动选择最合适的节点部署 Pod。上例中,两个 Pod 被均衡地调度到不同节点上,体现了默认调度的负载均衡策略。


节点选择器

使用 NodeSelector 指定节点调度

为节点添加标签

我们可以通过 kubectl label 命令给某个节点添加标签,方便后续在 Pod 调度时进行筛选。

kubectl label nodes 10-255-101-82 disktype=ssd

此命令为节点 10-255-101-82 添加了一个标签:disktype=ssd


编写 Deployment 配置文件

创建名为 ssd.yaml 的 Deployment 文件,指定 nodeSelector 字段:

apiVersion: apps/v1
kind: Deployment
metadata:name: test-nginx-nodeselectornamespace: defaultlabels:app: test-nginx
spec:replicas: 2selector:matchLabels:app: test-nginxtemplate:metadata:labels:app: test-nginxspec:nodeSelector:disktype: ssdcontainers:- name: nginximage: nginxports:- containerPort: 80
status: {}

spec.template.spec.nodeSelector 中声明节点标签 disktype: ssd,表示仅在拥有该标签的节点上运行 Pod。


应用资源并查看调度结果

kubectl apply -f ssd.yaml

查看 Pod 分布情况:

kubectl get pods -o wide
NAME                                       READY   STATUS    RESTARTS   AGE   IP               NODE             NOMINATED NODE   READINESS GATES
test-nginx-6f5d5f6564-gbgc6                1/1     Running   0          18m   192.168.154.1    10-255-101-82    <none>           <none>
test-nginx-6f5d5f6564-jpbhl                1/1     Running   0          18m   192.168.154.65   10-255-101-152   <none>           <none>
test-nginx-nodeselector-7cfb54fc6b-9grcj   1/1     Running   0          5s    192.168.154.3    10-255-101-82    <none>           <none>
test-nginx-nodeselector-7cfb54fc6b-q5m72   1/1     Running   0          5s    192.168.154.2    10-255-101-82    <none>           <none>

从结果可以看到,test-nginx-nodeselector 这两个 Pod 均调度到了节点 10-255-101-82 上,符合我们通过 NodeSelector 限定的调度条件。


Node Affinity(节点亲和性)

为节点添加标签

我们可以通过 kubectl label 命令给某个节点添加标签,方便后续在 Pod 调度时进行筛选。

kubectl label nodes 10-255-101-152 10-255-101-216 nodeaffinity=test

此命令为节点 10-255-101-152 10-255-101-216 添加了一个标签:nodeaffinity=test

在 Kubernetes 中,Node Affinity(节点亲和性) 是一种调度策略,用于控制 Pod 应该调度到哪些具有特定标签的节点上。它是对传统 nodeSelector 的增强版,提供了更灵活、更强大的表达能力。

Node Affinity 分为两种:

  • 硬约束requiredDuringSchedulingIgnoredDuringExecution
    必须匹配,否则无法调度。
  • 软约束preferredDuringSchedulingIgnoredDuringExecution
    尽量匹配,不匹配也能调度。

硬约束(Required)

apiVersion: apps/v1
kind: Deployment
metadata:name: nginx-hard-affinitynamespace: default
spec:replicas: 2selector:matchLabels:app: nginxtemplate:metadata:labels:app: nginxspec:affinity:nodeAffinity:requiredDuringSchedulingIgnoredDuringExecution:nodeSelectorTerms:- matchExpressions:- key: nodeaffinityoperator: Invalues:- testcontainers:- name: nginximage: nginxports:- containerPort: 80

含义

  • Pod 只能被调度到那些带有 nodeaffinity=test 标签的节点上。
  • 如果没有满足条件的节点,Pod 不会被创建,调度器也不会“妥协”。
  • 用于强制性约束,适用于:必须部署到某类节点,例如有 GPU、有 SSD 的节点。

字段说明

字段说明
requiredDuringSchedulingIgnoredDuringExecution硬约束:调度时必须满足,执行时不再检查
nodeSelectorTerms多个条件之间是“或”(OR)关系
matchExpressions条件表达式数组,内部是“与”(AND)关系
key节点的标签键,例如 disktype
operator条件运算符,如 In、NotIn、Exists 等
values标签值列表

在这里插入图片描述


软约束(Preferred)

只是多了 weight

先不设置标签
apiVersion: apps/v1
kind: Deployment
metadata:name: nginx-soft-affinitynamespace: default
spec:replicas: 2selector:matchLabels:app: nginxtemplate:metadata:labels:app: nginxspec:affinity:nodeAffinity:preferredDuringSchedulingIgnoredDuringExecution:- weight: 100preference:matchExpressions:- key: kkkoperator: Invalues:- vvvcontainers:- name: nginximage: nginxports:- containerPort: 80

含义

  • Pod 优先调度到带有 kkk=vvv 标签的节点上,如果没有这样的节点,也可以调度到别的节点。
  • 属于“加分项”或者“倾向性偏好”。
  • 可以设置多个条件,调度器会根据 weight 评估权重。

字段说明

字段说明
preferredDuringSchedulingIgnoredDuringExecution软约束,调度时尽量满足,执行时不检查
weight权重值(1-100),用于排序优先级
preference匹配条件,与 required 内部结构相同

在这里插入图片描述
截屏查看都到216了

设置标签
kubectl label nodes 10-255-101-152 kkk=vvv

在这里插入图片描述

运算符支持的类型

运算符含义
In键的值必须在列表中
NotIn键的值不能在列表中
Exists键存在即可,不关心值
DoesNotExist键不存在
Gt键的值大于指定值(整数)
Lt键的值小于指定值(整数)

污点与容忍(Taints & Tolerations)

在 Kubernetes 中,污点(Taint) 是给节点“贴标签”,表示这个节点不希望被调度 Pod;而 容忍(Toleration) 是对 Pod 设置“通行证”,告诉调度器:我可以接受这个污点,允许调度到这个节点。

🚧 说白了,就是节点用 Taint 拒绝普通 Pod,而 Pod 用 Toleration 表示“我不怕”,可以进去。


污点(Taint)

添加污点的命令:
kubectl taint nodes <节点名> key=value:effect

例子:

kubectl taint nodes node1 disktype=ssd:NoSchedule

这表示 node1 节点上有个污点,键为 disktype,值为 ssd调度器将不再把普通 Pod 安排到这个节点上。


容忍(Toleration)

Pod 通过 tolerations 字段声明可以容忍哪些污点。

示例 YAML:
apiVersion: v1
kind: Pod
metadata:name: toleration-pod
spec:tolerations:- key: "disktype"operator: "Equal"value: "ssd"effect: "NoSchedule"containers:- name: nginximage: nginx

📌 含义:

  • 这个 Pod 可以调度到被 disktype=ssd:NoSchedule 污染的节点
  • 如果节点没有这个污点,Pod 也能正常调度。

三种 Effect 类型(效果)

Effect 类型含义说明
NoSchedule不允许没有容忍的 Pod 被调度
PreferNoSchedule尽量不调度,没有强制性
NoExecute不仅不调度,还会驱逐正在运行但不容忍的 Pod

案例演示

给所有节点打上污点
kubectl taint nodes 10-255-101-152 10-255-101-216 10-255-101-82 key1=value1:NoSchedule
没有容忍的 Pod(会调度失败)
apiVersion: apps/v1
kind: Deployment
metadata:name: pod-without-tolerationnamespace: default
spec:replicas: 2selector:matchLabels:app: nginxtemplate:metadata:labels:app: nginxspec:containers:- name: nginximage: nginxports:- containerPort: 80

这个 Pod 不会调度成功,因为它无法容忍污点。
在这里插入图片描述


有容忍的 Pod(调度成功)
apiVersion: apps/v1
kind: Deployment
metadata:name: pod-with-tolerationnamespace: default
spec:replicas: 2selector:matchLabels:app: nginxtemplate:metadata:labels:app: nginxspec:tolerations:- key: "key1"operator: "Equal"value: "value1"effect: "NoSchedule"containers:- name: nginximage: nginxports:- containerPort: 80

字段解析

字段说明
key与节点上污点的键匹配。这个例子中是 key1
operator表示比较方式,这里是 Equal,意思是 key=key1value=value1
value必须与节点污点的值相同。
effect表示容忍哪种类型的污点效果,这里是 NoSchedule,表示可以调度到原本不允许的节点上。

在这里插入图片描述


Pod Affinity(Pod 亲和性)与 Pod Anti-Affinity(反亲和性)

Pod 亲和性用于指定一个 Pod 应该调度到和哪些 Pod 同节点或同拓扑域的节点上;而反亲和性则用于指定 不应该调度到和某些 Pod 同节点上的节点上。这在某些实际场景中非常有用,比如将应用组件部署在一起或故意分散部署。

Pod Affinity 和 Node Affinity 类似,也分为:

  • 硬约束requiredDuringSchedulingIgnoredDuringExecution
  • 软约束preferredDuringSchedulingIgnoredDuringExecution

在这里插入图片描述

Pod Affinity(亲和性)

示例:调度到和标签为 app=nginx 的 Pod 相同节点的 Pod 上(硬约束)
apiVersion: apps/v1
kind: Deployment
metadata:name: nginx-pod-affinitynamespace: default
spec:replicas: 2selector:matchLabels:app: nginx-affinitytemplate:metadata:labels:app: nginx-affinityspec:affinity:podAffinity:requiredDuringSchedulingIgnoredDuringExecution:- labelSelector:matchExpressions:- key: appoperator: Invalues:- nginxtopologyKey: kubernetes.io/hostnamecontainers:- name: nginximage: nginxports:- containerPort: 80

说明:

  • labelSelector:匹配目标 Pod 的标签
  • topologyKey:指定拓扑域,一般用 kubernetes.io/hostname 表示同一节点

在这里插入图片描述


Pod Anti-Affinity(反亲和性)

示例:调度到与标签为 app=nginx 的 Pod 不同节点上(软约束)
apiVersion: apps/v1
kind: Deployment
metadata:name: nginx-pod-antiaffinitynamespace: default
spec:replicas: 2selector:matchLabels:app: nginx-antiaffinitytemplate:metadata:labels:app: nginx-antiaffinityspec:affinity:podAntiAffinity:preferredDuringSchedulingIgnoredDuringExecution:- weight: 100podAffinityTerm:labelSelector:matchExpressions:- key: appoperator: Invalues:- nginxtopologyKey: kubernetes.io/hostnamecontainers:- name: nginximage: nginxports:- containerPort: 80

这个配置表示:“尽量避免和已有的 nginx Pod 被调度到同一节点”。

在这里插入图片描述


拓扑域 TopologyKey 说明

拓扑键含义说明
kubernetes.io/hostname节点级别,同一 Node
topology.kubernetes.io/zone同一可用区(适用于云平台)
topology.kubernetes.io/region同一区域(适用于云平台)

总结

在 Kubernetes 中,Pod 的调度策略直接关系到集群资源的利用率和业务运行的稳定性。通过本篇博文,我们从多个维度深入了解了 Pod 的调度机制:

✅ 默认调度策略

Kubernetes 默认调度器会基于资源可用性、亲和性、污点容忍等信息,为 Pod 自动选择最合适的节点。这种方式适合大多数通用业务场景。

✅ NodeSelector

最简单的调度约束方式,通过指定 nodeSelector 键值对,将 Pod 调度到拥有对应标签的节点上,配置简单,逻辑清晰。

✅ Node Affinity(节点亲和性)

提供了更强大、灵活的调度表达能力,支持软约束(preferred)和硬约束(required)两种模式,并支持多种匹配运算符如 InExistsGt 等,更适合复杂调度场景。

✅ Pod Affinity / Anti-Affinity(Pod 间亲和/反亲和)

允许调度决策考虑其他 Pod 的位置关系。例如可以将某些 Pod 调度到相同或不同节点,以实现高可用、节点隔离、业务分层部署等目的,是构建微服务间拓扑结构的重要手段。

✅ Taints and Tolerations(污点与容忍)

用于限制某些节点只接受特定 Pod,反向实现“节点选择”的效果,常用于控制特殊硬件资源节点的使用,例如 GPU 节点、安全节点等。

✅ 自定义调度器(Custom Scheduler)

当内置调度逻辑无法满足需求时,可通过编写并部署自定义调度器,灵活实现业务定制的调度策略,具备最高的自由度和扩展性。


📌 建议使用场景总结

需求类型推荐策略
简单节点筛选nodeSelector
灵活的节点规则匹配nodeAffinity
根据其他 Pod 的位置调度podAffinity / podAntiAffinity
限制 Pod 访问某些节点taints and tolerations
实现复杂定制调度逻辑自定义调度器(Custom Scheduler)

Kubernetes 的调度机制具有极高的可扩展性和可编程性,在实际生产中,合理地选择调度策略不仅能提高资源利用效率,更能保障服务的高可用性与运行稳定性。

如果你掌握了这些策略,也就掌握了 Kubernetes 调度的灵魂。


相关文章:

  • 每天学一个 Linux 命令(22):pwd
  • 有哪些好用的仓库管理系统
  • [工具]Java xml 转 Json
  • 招商信诺原点安全:一体化数据安全管理解决方案荣获“鑫智奖”!
  • ios精灵脚本辅助软件,有根和无根roothide越狱区别
  • 【技术派后端篇】技术派通用敏感词替换:原理、实现与应用
  • Benewake(北醒) TF-NOVA 在通过TTL-USB转接板更改配置教程
  • 手撕数据结构算法OJ——栈和队列
  • 数据结构|基数排序及八个排序总结
  • 1187. 【动态规划】竞赛总分
  • IDEA MyBatisCodeHelper Pro插件高版本解密
  • Linux网络编程——五种I/O模式
  • STM32F429 的时钟系统,从AHB到APB1和APB2再到外设
  • JavaScript 核心特性完全指南
  • STL常用算法
  • 分布式锁下的Redisson:解锁新姿势,与Curator的华山论剑
  • 插入排序和希尔排序
  • Java中的函数式编程详解
  • Docker搭建MySQL 5.7一主两从主从复制架构
  • OpenAI 34页最佳构建Agent实践
  • 新消费观察 | 重点深耕,外资科技企业继续看好中国发展
  • 嘉兴乌镇一化工公司仓库火灾后,当地召开火灾警示现场会
  • 工信部:计划出台机械、汽车、电力装备等三个行业新一轮稳增长工作方案
  • 喝水呛咳?帕金森患者的吞咽障碍看这一篇就够了
  • 助力外贸拓内销,上海16家电商平台与近80家外贸企业现场对接
  • 中国驻德国大使馆公使曾颖如,调任广州医科大学党委书记