在K8S中,Pod的调度机制是什么?

在 Kubernetes 中,Pod 调度(Scheduling) 是指将新创建的 Pod 分配到集群中合适节点(Node)上的过程。这个过程由核心组件 kube-scheduler 负责,其目标是找到一个满足 Pod 资源需求和约束条件的最佳节点。调度机制是一个复杂但高度可配置的过程,主要包含以下核心步骤和机制:


一、调度流程的核心步骤

  1. 过滤(Filtering) / 预选(Predicates)

    • 目的: 从集群的所有节点中筛选出符合条件的候选节点
    • 机制: kube-scheduler 依据 Pod 的 spec(如资源请求 requests、节点选择器 nodeSelector、亲和性/反亲和性 affinity/anti-affinity、污点容忍 tolerations 等)和节点的状态(如可用资源、污点 taints、标签 labels、条件 conditions 等),运行一系列预定义的过滤策略(Predicate Policies)
    • 结果: 得到一个候选节点列表。如果列表为空,Pod 将保持 Pending 状态(直到条件满足或超时)。
    • 常见过滤策略示例:
      • PodFitsResources:节点剩余资源(CPU、内存)是否满足 Pod 的 requests
      • PodFitsHostPorts:节点上请求的 hostPort 是否可用。
      • MatchNodeSelector:节点的 labels 是否匹配 Pod 的 nodeSelectornodeAffinity
      • CheckNodeMemoryPressure / CheckNodeDiskPressure / CheckNodePIDPressure:节点是否处于内存、磁盘或 PID 压力状态(避免调度到不健康节点)。
      • CheckVolumeBinding:请求的 PVC 是否能绑定(适用于延迟绑定的存储)。
      • NoDiskConflict(已弃用,通常由 CSI 处理):卷是否冲突(如 AWS EBS 同一卷不能挂载到多个节点)。
      • PodToleratesNodeTaints:Pod 的 tolerations 是否能容忍节点的 taints
  2. 评分(Scoring) / 优选(Priorities)

    • 目的: 对通过过滤的候选节点进行优先级排序,选出最优节点
    • 机制: 对每个候选节点运行一系列评分策略(Priority Policies)。每个策略为节点打一个分数(通常是 0-10 分)。kube-scheduler 将所有策略的分数按权重(可配置)加权求和,得到节点的最终得分。
    • 结果: 选择得分最高的节点。如果有多个节点得分相同,则随机选择一个。
    • 常见评分策略示例:
      • LeastRequestedPriority:优先选择资源(CPU、内存)利用率最低的节点((空闲资源量 / 总资源量) * 10)。鼓励负载均衡。
      • BalancedResourceAllocation:优先选择 CPU 和内存利用率最平衡的节点(避免一个资源用尽而另一个空闲)。计算 (1 - |CPU利用率 - 内存利用率|) * 10
      • ImageLocalityPriority:优先选择已缓存 Pod 所需镜像的节点(减少镜像拉取时间)。
      • NodeAffinityPriority / InterPodAffinityPriority:优先选择满足 nodeAffinitypodAffinity/anti-affinity 规则更强的节点。
      • TaintTolerationPriority:优先选择 Pod 能容忍的污点数更少的节点(倾向于“更干净”的节点)。
      • SelectorSpreadPriority:优先选择运行相同 Service 或 StatefulSet 的同标签 Pod 数量最少的节点(分散部署,提高容错性)。
  3. 绑定(Binding)

    • 目的: 将 Pod 正式绑定到选出的最优节点上。
    • 机制: kube-scheduler 向 API Server 发送一个 Bind 请求,将 Pod 的 spec.nodeName 字段设置为选定的节点名称。
    • 结果: 该节点的 kubelet 组件监听到 API Server 上 Pod 的绑定信息后,启动容器,执行 Pod 的生命周期管理。

二、影响调度的关键 Pod 配置

Pod 的 spec 中定义了影响调度的核心约束:

  1. 资源请求(spec.containers[].resources.requests

    • 必须项: 声明 Pod 对 CPU 和内存的最小需求。kube-scheduler 使用此值过滤掉资源不足的节点。
    • 示例: requests: { cpu: "500m", memory: "512Mi" }
  2. 节点选择器(spec.nodeSelector

    • 简单约束: 要求节点必须拥有特定标签(Key-Value)
    • 示例: nodeSelector: { disktype: ssd, gpu: "true" }
  3. 节点亲和性与反亲和性(spec.affinity.nodeAffinity

    • 高级约束: 提供更精细、更灵活的节点选择规则。
    • 类型:
      • requiredDuringSchedulingIgnoredDuringExecution硬性要求,调度时必须满足。
      • preferredDuringSchedulingIgnoredDuringExecution软性偏好,调度时尽量满足(有加分)。
    • 操作符: In, NotIn, Exists, DoesNotExist, Gt, Lt
    • 示例:
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
            - matchExpressions:
              - key: topology.kubernetes.io/zone
                operator: In
                values: [zone-a, zone-b]
          preferredDuringSchedulingIgnoredDuringExecution:
          - weight: 1
            preference:
              matchExpressions:
              - key: instance-type
                operator: In
                values: [c5.2xlarge]
      
  4. Pod 亲和性与反亲和性(spec.affinity.podAffinity/podAntiAffinity

    • 基于 Pod 的约束: 根据其他 Pod 的标签决定调度位置。
    • 用途:
      • podAffinity:将 Pod 集中部署(如相同可用区提升性能)。
      • podAntiAffinity:将 Pod 分散部署(避免单点故障,提高容错)。
    • 关键概念: topologyKey(如 kubernetes.io/hostname, topology.kubernetes.io/zone)定义分散/集中的范围(主机级、机架级、区域级)。
    • 示例(反亲和性):
      affinity:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchExpressions:
              - key: app
                operator: In
                values: [my-webapp]
            topologyKey: kubernetes.io/hostname # 确保同一个 app 的 Pod 不调度到同一台主机
      
  5. 污点与容忍度(spec.tolerations

    • 节点排斥机制: 节点通过设置 污点(Taint)kubectl taint nodes node1 key=value:NoSchedule)来拒绝不匹配的 Pod。
    • Pod 声明容忍: Pod 通过 容忍度(Toleration) 声明可以接受哪些污点。
    • 效果(Effect):
      • NoSchedule:绝不调度(硬排斥)。
      • PreferNoSchedule:尽量不调度(软排斥)。
      • NoExecute:不仅不调度,还会驱逐节点上已有但不容忍此污点的 Pod。
    • 示例:
      tolerations:
      - key: "dedicated"
        operator: "Equal"
        value: "gpu-team"
        effect: "NoSchedule" # 允许调度到带有污点 `dedicated=gpu-team:NoSchedule` 的 GPU 节点
      

三、高级调度机制

  1. 调度器框架(Scheduler Framework) (Kubernetes v1.15+)

    • 可插拔架构: 将调度流程(过滤、评分、绑定等)拆分为多个扩展点(Extension Points)
    • 自定义插件: 开发者可以编写插件,在特定扩展点注入自定义逻辑(如自定义过滤规则、评分算法、绑定后操作)。
    • 灵活性: 替代了旧式的 Policy 文件,是未来调度的方向。
  2. 动态调度器(Multiple Schedulers)

    • 自定义调度器: 用户可以部署自定义的调度器(实现 kube-scheduler 接口)。
    • Pod 指定调度器: 在 Pod 的 spec.schedulerName 中指定使用哪个调度器(默认是 default-scheduler)。
    • 场景: 为特殊负载(如 AI 训练、批处理)设计定制调度策略。
  3. 调度器性能调优

    • 并行度(--parallelism): 控制同时调度的 Pod 数量。
    • 百分比节点采样(--percentageOfNodesToScore): 大规模集群中,只对一部分节点打分以提升性能(默认 50%,最小值 5%)。
    • 缓存: 缓存节点信息,减少对 API Server 的查询压力。

四、调度失败排查(Pod 处于 Pending 状态)

  1. 查看事件: kubectl describe pod <pod-name> 查看 Events 部分,通常有调度器失败原因(如 Insufficient cpu/memory, 0/ nodes available)。
  2. 检查资源请求: 确认节点是否有足够资源(kubectl describe node <node-name>)。
  3. 检查约束匹配:
    • 节点标签是否满足 nodeSelectornodeAffinity
    • Pod 的 tolerations 是否匹配节点的 taints
    • podAffinity/anti-affinity 规则是否冲突(如要求分散但集群节点不足)?
  4. 存储卷: PVC 是否绑定成功(kubectl get pvc)?
  5. 调度器日志: 查看 kube-scheduler 日志(需调整日志级别 -v=4 或更高)获取详细决策信息。

总结

Kubernetes Pod 调度机制的核心是 kube-scheduler过滤 -> 评分 -> 绑定 三步流程,其决策基于:

  • Pod 的需求: 资源请求 (requests)、节点选择器 (nodeSelector)、亲和性/反亲和性 (affinity)、污点容忍 (tolerations)。
  • 节点的状态: 可用资源、污点 (taints)、标签 (labels)、健康状况。
  • 调度策略: 内置的过滤 (Predicates) 和评分 (Priorities) 策略(可通过框架扩展)。

理解并合理配置这些约束(尤其是亲和性、反亲和性和污点容忍)是优化应用部署(高可用、性能、成本)的关键。对于复杂场景,可借助调度器框架自定义调度器实现更精细的控制。

posted @ 2025-08-13 20:21  天道酬勤zjh  阅读(18)  评论(0)    收藏  举报