前言

Kubernetes 作为现代容器编排系统的核心,其调度机制是集群资源管理与应用高可用的基石。调度器(Scheduler)负责将 Pod 合理、高效地分配到集群中的节点上,不仅影响资源利用率,也直接关系到服务的稳定性和性能。
本文系统梳理了 Kubernetes 调度器的核心工作机制、调度策略、节点亲和与反亲和、污点与容忍等关键概念,并提供了节点维护与常见故障排查的实用命令,旨在帮助开发者和运维人员深入理解并灵活运用调度策略,构建稳定、高效的 Kubernetes 集群环境。

1 Kubernetes 组件协作机制

Kubernetes 通过 List-Watch 机制使各个组件协作、数据同步,从而实现解耦与实时一致性。

关键组件关系

组件 职责
kubectl / API 客户端 向 APIServer 发起资源创建或管理请求
APIServer 负责 API 调用、权限校验、存储交互,是集群控制的核心入口
etcd 存储集群所有状态信息
Controller Manager 维持副本数、执行自愈逻辑(扩容、重建等)
Scheduler 调度器,将未分配节点的 Pod 分配到合适的 Node
kubelet 节点代理,负责 Pod 生命周期管理和容器运行状态上报

2 Scheduler工作过程

2.1 核心任务

未绑定 Node 的 Pod 分配到合适的节点

2.2 调度特性

  • 公平性:节点间资源分配均衡
  • 高效性:集群所有资源最大化被使用
  • 效 率:调度的性能要好,能够尽快地对大批量的 pod 完成调度工作
  • 灵活性:允许自定义策略(调度策略、插件)

2.3 调度流程

2.3.1 过滤阶段(Predicate)

常见过滤算法:

算法名 功能描述
PodFitsResources 检查节点剩余资源是否满足 Pod 需求
PodFitsHost 检查 NodeName 是否匹配
PodFitsHostPorts 检查端口冲突
PodSelectorMatches label 匹配
NoDiskConflict Volume 挂载冲突检测
2.3.2 优选阶段(Priorities)

常见算法:

优先级项 描述
LeastRequestedPriority 资源使用率越低,权重越高
BalancedResourceAllocation CPU 与内存使用率越接近越好(这个一般和上面的一起使用,不单独使用)
ImageLocalityPriority 优先节点上已有目标镜像的节点

3 调度节点的方式

3.1 强制绑定与标签匹配

3.1.1 nodeName(强制绑定)

将 Pod 直接调度到指定的 Node 节点上,会跳过 Scheduler 的调度策略,该匹配规则是强制匹配

apiVersion: apps/v1  
kind: Deployment  
metadata:
  name: myapp
spec:
  replicas: 3
  selector:
    matchLabels:
      app: myapp
  template:
    metadata:
      labels:
        app: myapp
    spec:
      nodeName: node01				# 将 pod 强制绑定到 node01 上	
      containers:
      - name: myapp
        image: soscscs/myapp:v1
        ports:
        - containerPort: 80
3.1.2 nodeSelector(标签匹配)

通过 kubernetes 的 label-selector 机制选择节点,由调度器调度策略匹配 label,然后调度 Pod 到目标节点,该匹配规则属于强制约束

apiVersion: apps/v1
kind: Deployment  
metadata:
  name: myapp1
spec:
  replicas: 3
  selector:
    matchLabels:
      app: myapp1
  template:
    metadata:
      labels:
        app: myapp1
    spec:
      nodeSelector:
	    yjs: a					# 节点标签键值对,用于筛选符合条件的节点
      containers:
      - name: myapp1
        image: soscscs/myapp:v1
        ports:
        - containerPort: 80 
3.1.3 管理 Node 标签的命令
kubectl label nodes node01 yjs=a
kubectl get nodes --show-labels

# 指定标签查询 node 节点
kubectl get node -l yjs=a  

# 修改一个 label 的值,需要加上 --overwrite 参数
kubectl label nodes node02 yjs=b --overwrite

# 删除一个 label,只需在命令行最后指定 label 的 key 名并与一个减号相连即可
kubectl label nodes node02 yjs-

3.2 亲和性策略

调度策略 匹配标签 操作符 拓扑域支持 调度目标
nodeAffinity(节点亲和性) 主机 In, NotIn, Exists,DoesNotExist, Gt, Lt 指定主机
podAffinity(pod 亲和性) Pod In, NotIn, Exists,DoesNotExist 与指定 Pod 同域
podAntiAffinity(pod 反亲和性) Pod In, NotIn, Exists,DoesNotExist 与指定 Pod 不同域
3.2.1 节点亲和性(NodeAffinity)

核心概念:将具有 pod 的值添加到具有 label 的 node 节点上

3.2.1.1 操作符含义
操作符 含义 示例
In label 的值在列表中 env In (dev, test) → 选出 env=devenv=test 的 Pod
NotIn label 的值不在列表中 env NotIn (prod) → 除了生产环境都选上
Gt label 的值大于某个数 version Gt 3 → 选出 version=4,5,6… 的 Pod
Lt label 的值小于某个数 version Lt 3 → 选出 version=1,2 的 Pod
Exists label 存在即可 Exists zone → 只要有 zone 这个标签
DoesNotExist label 不存在 DoesNotExist debug → 没有 debug 标签的 Pod

简单理解

In / NotIn 看“名单”,
Gt / Lt 看“数值”,
Exists / DoesNotExist 看“有没有”。


3.2.1.2 硬策略
  • 硬策略(强制性策略)必须满足的条件。如果不满足,Pod 会一直处于 Pending 状态,不会被调度。规则是“硬性”的
apiVersion: v1
kind: Pod
metadata:
  name: affinity
  labels:
    app: node-affinity-pod
spec:
  containers:
  - name: with-node-affinity
    image: soscscs/myapp:v1
  affinity:									# 亲和性配置
    nodeAffinity:							# 节点亲和性配置
      requiredDuringSchedulingIgnoredDuringExecution:		# 硬策略:调度期间必须满足,运行期间忽略
        nodeSelectorTerms:
        - matchExpressions:
          - key: kubernetes.io/hostname    	# 指定node的标签
            operator: NotIn 				# 不在指定的值列表中
            values:# 即不选择node02节点
            - node02
3.2.1.3 软策略
  • 软策略(偏好性策略)应该满足的条件。调度器会尝试寻找满足这些条件的节点,但如果实在找不到,也会选择一个不满足条件的节点将 Pod 调度上去。规则是“软性”的,带有权重,weight 数值越小,优先级越高
apiVersion: v1
kind: Pod
metadata:
  name: affinity
  labels:
    app: node-affinity-pod
spec:
  containers:
  - name: with-node-affinity
    image: soscscs/myapp:v1
  affinity:
    nodeAffinity:
      preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 1   					#如果有多个软策略选项的话,数值越小,优先级越高
        preference:
          matchExpressions:
          - key: kubernetes.io/hostname
            operator: In				 # 偏好的值列表
            values:						 # 即优先选择node02
            - node02
3.2.2 pod的亲和性与反亲和性

定义了 Pod 之间的**“吸引”“排斥”**关系

  • Pod 亲和性: “ 将我调度到有 ‘朋友’ Pod 的节点(或区域)上 ”
  • Pod 反亲和性: “ 不要将我调度到有 ‘敌人’ Pod 的节点(或区域)上 ”
3.2.2.1 pod 的亲和性
apiVersion: v1
kind: Pod
metadata:
  name: myapp02  # Pod名称
  labels:
    app: myapp02  # 给Pod打上标签 app=myapp02
spec:
  containers:
  - name: myapp02  				# 容器名称
    image: soscscs/myapp:v1  	# 容器镜像
  affinity:  					# 亲和性配置
    podAffinity:  				# Pod亲和性 - 表示这个Pod希望和某些Pod部署在一起
      requiredDuringSchedulingIgnoredDuringExecution:  # 硬策略:调度期间必须满足,运行期间忽略
      - labelSelector:  		# 标签选择器,用于选择目标Pod
          matchExpressions:  	# 匹配表达式
          - key: app  			# 要匹配的标签键
            operator: In  		# 操作符:在指定的值列表中
            values:  			# 要匹配的标签值列表
            - myapp05  			# 具体值:app=myapp01
        topologyKey: yjs  		# 拓扑域键:使用自定义标签 "yjs"
------------------------------------------------------------------------------------------------------------
# 这是一个硬策略,必须将 myapp02 放到有运行 myapp05 且带有 yjs 标签的节点上
3.2.2.2 pod 的反亲和性
apiVersion: v1
kind: Pod
metadata:
  name: myapp10  # Pod名称
  labels:
    app: myapp10  # 给Pod打上标签 app=myapp10
spec:
  containers:
  - name: myapp10  				# 容器名称
    image: soscscs/myapp:v1  	# 容器镜像
  affinity:  					# 亲和性配置
    podAntiAffinity:  			# Pod反亲和性 - 表示这个Pod希望避开某些Pod
      preferredDuringSchedulingIgnoredDuringExecution:  # 软策略:调度期间优先考虑,运行期间忽略
      - weight: 100  			# 权重值(1-100),在有多个偏好规则时决定优先级
        podAffinityTerm:  		# 反亲和性规则的具体定义
          labelSelector:  		# 标签选择器,用于选择要避开的Pod
            matchExpressions:  	# 匹配表达式
            - key: app  		# 要匹配的标签键
              operator: In  	# 操作符:在指定的值列表中
              values:  			# 要匹配的标签值列表
              - myapp02  		# 具体值:app=myapp01
          topologyKey: kubernetes.io/hostname  # 拓扑域键:节点主机名
------------------------------------------------------------------------------------------------------------
# 这是一个软策略,尽量避免将 myapp10 放到有运行 myapp02 的节点上

3.2 污点和容忍

3.2.1 核心概念
  • 污点:应用于节点上的一个标记。它表示该节点只允许带有**“容忍”**配置的 Pod 被调度上来
  • 容忍:应用于 Pod 上的一个配置。它表示这个 Pod 能够**“容忍”某些污点**,从而可以被调度到拥有对应污点的节点上。
3.2.2 污点 (Taint)

污点是一个三元组,格式为:key=value:effect

  • key:污点的键(可选值,但通常都会设置)

  • value:污点的值(可以为空)

  • effect:污点的效果(必须)。有以下三种效果:

    类型 描述
    NoSchedule 不调度到此节点
    PreferNoSchedule 尽量避免调度具有该污点的 Node 上
    NoExecute 不调度 + 驱逐已存在 Pod
#设置污点
kubectl taint node node01 key1=value1:NoSchedule

#节点说明中,查找 Taints 字段
kubectl describe node node-name | grep -i taints

#去除污点
kubectl taint node node01 key1:NoSchedule-
3.2.3 容忍 (Tolerations)

3.2.3.1 完全匹配(Equal)

tolerations:
- key: "gpu"
  operator: "Equal"  		# 操作符,Equal 表示完全匹配
  value: "true"      		# 必须匹配 value
  effect: "NoSchedule"

这个 Pod 能容忍键为 gpu、值为 true、效果为 NoSchedule 的污点

3.2.3.2 存在即匹配(Exists)

tolerations:
- key: "gpu"        		# 只要存在 key 为 “gpu” 的污点...
  operator: "Exists" 		# ...就容忍,不关心 value 是什么
  effect: "NoSchedule"
  tolerationSeconds: 60  	# 当污点被添加后,还能在此节点上运行 60 秒

这个 Pod 能容忍任何效果为 NoSchedule 且键为 gpu 的污点,无论其值是什么

3.2.3.3 容忍 NoExecute 并设置容忍时间

tolerations:
- key: "node.kubernetes.io/unreachable"
  operator: "Exists"
  effect: "NoExecute"
  tolerationSeconds: 60  # 当污点被添加后,还能在此节点上运行 60 秒

Pod 可以容忍一段时间,给节点一个恢复的机会,超过 tolerationSeconds 后才会被驱逐。

4 节点维护操作***

🧱 cordon & drain

命令 功能
kubectl cordon <node> 标记为不可调度
kubectl drain <node> --ignore-daemonsets --delete-local-data --force 驱逐 Pod
kubectl uncordon <node> 恢复可调度状态

drain 等价于 “cordon + 驱逐”。

在 Kubernetes 中,驱逐(Eviction)是指将运行中的 Pod 从一个节点上迁移到另一个节点的过程,同时释放原节点上的资源以供其他使用。驱逐通常发生在以下情况:

  • 需要将 Pod 迁移到其他节点以维护节点或进行软硬件升级。
  • 某个节点的资源不足以容纳新的 Pod,需要将旧的 Pod 驱逐以释放资源。

Kubernetes 可以使用自动驱逐机制来管理 Pod 的迁移。它可以基于节点负载、Pod 优先级等条件来自动选择需要驱逐的 Pod,并将它们迁移到其他节点上。在执行驱逐时,Kubernetes 会首先将 SIGTERM 信号发送给 Pod,然后等待一段时间,让 Pod 自行终止。如果自我终止未成功,则 Kubernetes 会强制终止 Pod 并进行清理工作。

驱逐是 Kubernetes 集群中必不可少的机制之一,它可以确保系统的高冗余性和高可用性,并优化集群中的资源利用率。

5 故障排查命令

操作 命令
查看事件 kubectl describe pod <POD>
查看日志 kubectl logs <POD> [-c 容器名]
进入容器 kubectl exec -it <POD> bash
查看集群状态 kubectl cluster-info
查看节点状态 kubectl get nodes
查看 kubelet 日志 journalctl -xefu kubelet

6 总结

Kubernetes 调度是一个多层次、可扩展的决策过程,涵盖了从基础资源匹配到高级调度策略的完整链路。通过:

  • 基础调度机制(如 nodeName、nodeSelector)实现简单绑定;

  • 亲和性与反亲和性 实现 Pod 与节点、Pod 与 Pod 之间的精细化调度;

  • 污点与容忍 控制节点与 Pod 的互斥与兼容关系;

  • 节点维护操作(cordon / drain / uncordon)保障集群运维过程中的服务连续性;

  • 完备的故障排查命令 帮助快速定位调度与运行问题。

掌握这些调度机制与操作,能够显著提升集群的资源利用率、服务质量与运维效率,为构建生产级 Kubernetes 平台奠定坚实基础。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐