深度解析 Kubernetes 调度机制:从 kube-scheduler 原理到生产级配置

在 Kubernetes 集群管理中,调度器是决定集群资源利用率和服务性能的关键组件。本文将深入剖析 kube-scheduler 的核心工作原理、内部流转机制,并结合实际场景详解节点选择器、亲和性调度及污点容忍度的配置方法。

Kubernetes 调度核心原理

Kubernetes 集群的调度核心由 kube-scheduler 组件负责。其主要任务是根据 Pod 的资源需求、策略约束及集群当前的硬件状态,将新创建的 Pod 自动分配至最合适的 Node 节点上运行。这一过程高度灵活,支持基于资源限制、亲和性/反亲和性等维度的自定义配置。

Kube-scheduler 的工作机制

kube-scheduler 的调度流程主要包含以下五个核心步骤:

  1. 监听 API Server:调度器通过 Informer 机制持续监听 API Server,一旦发现有未绑定的 Pod 创建,即获取其详细元数据(如标签、资源请求)。
  2. 筛选可用节点:根据 Pod 的硬性约束条件(如 CPU/内存请求、特定节点标签),从集群中所有注册的 Node 中剔除不符合条件的节点。
  3. 计算分值:对筛选出的节点进行打分。调度算法会综合考量节点资源利用率、网络延迟等因素,计算每个节点的适配度分数。
  4. 选择节点:选择得分最高的节点作为最终调度目标。若多个节点分数相同,则随机选择。
  5. 更新 API Server:调度器将选定的 Node 信息写入 Pod 的 spec.nodeName 字段,随后通知对应节点上的 Kubelet 启动容器。

调度器内部流转全解

对于需要深入了解底层机制的工程师,理解 kube-scheduler 的内部数据流转至关重要。其内部处理流程基于 client-go 的 Informer 机制和优先级队列实现:

深度解析 Kubernetes 调度机制:从 kube-scheduler 原理到生产级配置
  1. 事件监听与缓存:Scheduler 注册 Informer handler 监听 API Server 的 Pod 和 Node 变更事件,并将数据同步至本地缓存。
  2. 队列调度:Informer 将事件更新至 Scheduling Queue(调度队列)。队列分为三种:
    • ActiveQ:维护基于 Pod 优先级的堆结构,调度循环每次从中取出优先级最高的 Pod。
    • UnschedulableQ:存储调度失败的 Pod。
    • PodBackoffQ:存储等待重试的 Pod。
  3. 调度循环:通过 NextPod 方法从 ActiveQ 获取待调度 Pod。
  4. 算法匹配:运行调度算法对 Node 和 Pod 进行匹配(Predicates)和打分(Priorities)。
  5. 异常处理:若调度失败,调用 Error 方法将 Pod 写入 UnschedulableQ。
  6. 退避机制:当不可调度时间超过 backoff 阈值,Pod 将转入 PodBackoffQ 等待重试。
  7. 异步绑定:调度器执行绑定操作时采用异步机制。它首先在缓存中创建一个 Assume Pod 模拟绑定结果(设置 NodeName),随后异步发送 Bind 请求给 API Server。在此过程中,Scheduler 会确保 Volume 已完成绑定,节点 Kubelet 接收到指令后即可在本地运行容器。

节点优选与打分策略

节点分值的计算并非固定不变,而是由可插拔的调度算法决定。默认情况下(DefaultPreemption 策略),打分主要依据以下维度:

  • 资源利用率:优先选择 CPU 和内存利用率较低的节点,以保持集群负载均衡。
  • Pod 分布:若节点上已运行大量 Pod,其得分会降低,以避免资源拥塞。
  • 亲和性与互斥性:根据 Pod 与节点的亲和性规则(如区域、标签)提高得分;根据互斥性规则降低得分。
  • 网络延迟:优先选择网络延迟较低的节点。
  • Pod 优先级:高优先级(如关键业务)的 Pod 会影响节点选择的权重。

工程师可以通过配置文件或命令行参数调整这些因素的权重,甚至开发自定义调度算法以满足特定业务需求。

核心调度策略概览

Kubernetes 提供了多种调度策略以适应不同的业务场景:

  • 默认调度策略 (DefaultPreemption):选择代价最小的节点。若资源不足,支持通过预选机制驱逐低优先级 Pod。
  • 带优先级的调度 (Priority):基于 PriorityClass 对 Pod 进行排序,确保高优先级业务优先获得资源。
  • 节点亲和性 (NodeAffinity):基于节点标签匹配目标节点。
  • Pod 亲和性/反亲和性 (PodAffinity/PodAntiAffinity):基于 Pod 标签决定 Pod 是部署在一起还是分散部署。
  • 资源限制调度 (ResourceLimits):优先选择可用资源最多的节点。

实战:精细化调度配置

节点选择器 NodeSelector

NodeSelector 是最简单的节点约束方式,通过标签匹配将 Pod 部署到指定节点。

配置示例:

apiVersion: v1
kind: Pod
metadata:
name: nginx-ssd
spec:
containers:
- name: nginx-ssd
  image: nginx:1.23.2
  imagePullPolicy: IfNotPresent
  ports:
  - containerPort: 80
nodeSelector:
  disktype: ssd

操作步骤:

  1. 应用配置:kubectl apply -f nodeselector.yaml
  2. 为节点打标:kubectl label node k8s02 disktype=ssd
  3. 验证调度:kubectl describe po nginx-ssd | grep -i node

节点亲和性 NodeAffinity

相比 NodeSelector,NodeAffinity 提供了更强大的匹配逻辑,支持硬匹配(必须满足)和软匹配(尽可能满足)。

关键字段说明:

  • requiredDuringSchedulingIgnoredDuringExecution:硬性要求,必须满足规则。
  • preferredDuringSchedulingIgnoredDuringExecution:软性偏好,满足则加分。
  • operator:支持 In, NotIn, Exists, DoesNotExist, Gt, Lt 等逻辑运算符。

配置示例:

apiVersion: v1
kind: Pod
metadata:
name: with-node-affinity
spec:
affinity:
  nodeAffinity:
    requiredDuringSchedulingIgnoredDuringExecution:
      nodeSelectorTerms:
      - matchExpressions:
        - key: env
          operator: In
          values:
          - test
          - dev
    preferredDuringSchedulingIgnoredDuringExecution:
    - weight: 1
      preference:
        matchExpressions:
        - key: project
          operator: In
          values:
          - linux
containers:
- name: with-node-affinity
  image: redis:6.0.6

匹配逻辑:

  1. 若同时存在 NodeSelector 和 NodeAffinity,两者需同时满足。
  2. 若指定多组 nodeSelectorTerms,满足其中一组即可。
  3. nodeSelectorTerms 中包含多组 matchExpressions,必须全部满足。

Pod 亲和性与反亲和性

Pod 亲和性用于控制 Pod 之间的部署拓扑关系,例如将通信频繁的服务部署在同一个节点或可用区。

1. Pod 亲和性

目标:将新 Pod 与目标 Pod 调度至同一拓扑域(如同一节点)。

apiVersion: v1
kind: Pod
metadata:
name: testpod02
spec:
affinity:
  podAffinity:
    requiredDuringSchedulingIgnoredDuringExecution:
    - labelSelector:
        matchExpressions:
        - key: app
          operator: In
          values:
          - myapp01  # 匹配已存在的 testpod01
      topologyKey: "kubernetes.io/hostname"  # 拓扑域定义为主机名
containers:
- name: testpod02
  image: redis:6.2

2. Pod 反亲和性

目标:确保新 Pod 不与目标 Pod 调度至同一拓扑域(常用于高可用部署,分散副本)。

apiVersion: v1
kind: Pod
metadata:
name: testpod02
spec:
affinity:
  podAntiAffinity:
    requiredDuringSchedulingIgnoredDuringExecution:
    - labelSelector:
        matchExpressions:
        - key: app
          operator: In
          values:
          - myapp01
      topologyKey: "kubernetes.io/hostname"
containers:
- name: testpod02
  image: redis:6.2

污点与容忍度

污点和容忍度是 Kubernetes 提供的节点排斥机制。污点作用于 Node,容忍度作用于 Pod。

1. 污点

污点用于阻止特定 Pod 调度到该节点,除非 Pod 定义了对应的容忍度。

Effect 类型:

  • NoSchedule:仅影响新 Pod 调度,不驱逐已有 Pod。
  • PreferNoSchedule:尽量不调度。
  • NoExecute:既不调度新 Pod,也会驱逐不满足容忍度的已有 Pod。

操作命令:

# 设置污点
kubectl taint node [node_name] key=value:[effect]

# 示例
kubectl taint node linux02 name=linux:NoSchedule

# 查看污点
kubectl describe node linux02 | grep Taints -A 10

# 删除污点
kubectl taint node [node_name] key:[effect]-

2. 容忍度

容忍度允许 Pod 忽略节点的特定污点。配置方式包括完全匹配、不完全匹配和大范围匹配。

完全匹配示例:

tolerations:
- key: "name"
operator: "Equal"
value: "linux"
effect: "NoSchedule"

大范围匹配示例(匹配指定 key 的所有 effect):

tolerations:
- key: "name"
operator: "Exists"

匹配所有污点(慎用):

tolerations:
- operator: "Exists"

驱逐延缓时间设置:

针对 NoExecute 类型的污点,可以设置 tolerationSeconds 来延缓 Pod 的驱逐时间,给予业务优雅退出的机会。

tolerations:
- key: "key1"
operator: "Equal"
value: "value1"
effect: "NoExecute"
tolerationSeconds: 3600  # 保留 3600 秒后再驱逐

完整 Pod YAML 示例:

apiVersion: v1
kind: Pod
metadata:
name: ng
labels:
  env: dev
spec:
containers:
- name: ng
  image: nginx:1.21.0
tolerations:
- key: name
  operator: Exists
  effect: NoSchedule

通过掌握上述调度机制与配置策略,IT 工程师可以更加高效地管理 Kubernetes 集群资源,保障业务系统的稳定性与高性能。

给TA打赏
共{{data.count}}人
人已打赏
Kubernetes云原生

Kubernetes网络

2025-4-9 8:37:16

Kubernetes云原生

Kubernetes 存储

2025-4-9 8:38:38

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索