【Kubernetes】Pod 之 Scheduler

105 阅读4分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第8天,点击查看活动详情

一、kube-scheduler 职责及调度流程

Master 节点上的核心服务之一 Scheduler 服务(也就是 kube-scheduler 进程)负责实现 Pod 的调度,整个调度的过程通过执行一系列复杂的算法,最终为每个 Pod 都计算出一个最佳的目标节点。

kube-scheduler 通过监听 kube-apiserver,获取未调度的 Pod 列表,通过调度算法计算出分配给 PodNode,并将 Node 信息与 Pod 进行绑定(Bind),结果存储在 etcd 中。而根据调度结果执行 Pod 的创建操作是由 Node 上的 kubelet 执行的。

**kube-scheduler 职责及调度流程 **主要分为:

  • 集群高可用
  • 调度资源监听
  • 调度节点分配

1. 集群高可用

kube-scheduler 可以设置 leader-elect 启动参数,这样会通过 etcd 进行节点选主。 kube-schedulerkube-controller-manager 都使用了一主多从的高可用方案。

简单理解的话是这样的: kube-scheduler 启动时,会在 etcd 中创建 endpointendpoint 的信息中记录了当前的 leader 节点信息,以及上次更新时间。 leader 节点会定期更新 endpoint 的信息,维护自己的 leader 身份,每个从节点的服务都会定期检查 endpoint 的信息,如果 endpoint 的信息在规定的时间范围内没有更新,从节点将会尝试更新自己的 leader 节点。

2. 调度资源监听

通过 Watch 机制监听 kube-apiserver 上资源(podnode)的变化。

kube-apiserver 给其他组件(kubectlkube-controller-managerkube-scheduler等)提供了一套 Watch 机制用于监控各种资源的变化。

类似于消息中间件的 发布-订阅模式(push)。

步骤:

  1. kube-apiserver初始化时,建立对 etcd 的连接并watch etcd
  2. kube-scheduler客户端调用watch api时,kube-apiserver内部会建立一个watchserver
  3. watchserver会从etcd中获取资源的watch eventwatch event经过加工过滤后就会发送给客户端,watch api本质上是一个GET请求。

通常有两种实现模式:

  1. 通过websocket协议发送
  2. 通过Transfer-Encoding=chunked方式建立长连接

3. 调度节点分配

调度节点分配分为两个环节:预选(Predicates)与优选 (Priorites)。调度资源监听也是为了这个环节提供数据输入。

  • 预选:遍历所有目标 Node,根据配置的预选策略 Predicates Policies 过滤掉不符合策略的 Node,剩下符合要求的候选节点。

预选的输出将会作为优选的输入。预选策略默认使用的是 DefaultProvider 中定义的 default predicates policies 集合。

  • 优选:根据配置的优选策略 Priorites Policies,为前一步过滤后的 Node 进行打分排名,得分最高的 Node 将作为最适合的 Node,该 Pod 将绑定(Bind)到最适合的 Node 上。

如果打分排名后,有多个 Node 并列得分最高,kube-scheduler 会从中随机选取一个 Node 作为目标 Node。优选策略默认使用的是 DefaultProvider 中定义的 default priorites policies 集合。

kube-scheduler 调度节点分配需要考虑的问题较多,有:

  • 公平:如何保证每个 Node 都能够分配资源
  • 资源高效利用:集群所有资源能够被最大化使用
  • 效率:调度性能高,能够尽快对大批量的 Pod 完成调度工作
  • 灵活:允许用户自定义调度逻辑



二、常用参数

kube-scheduler 在启动的时候也可以指定一些参数,列表如下:

参数含义默认值
--adress监听地址"0.0.0.0"
--port调度器监听的端口10251
--algorithm-provider提供调度算法的对象"DefaultProvider"
--masterAPI Server 的 HTTP 地址/
--profiling是否开启 profiling,开启后可以在 host:port/debug/pprof 访问 profile 信息true
--scheduler-name调度器名称,用来唯一确定该调度器"default-shcheduler"
--kube-api-burst和 API Server 通信时的最大 burst 值100
--kube-api-qps和 API Server 通信时的 QPS 值50
--log_dir日志保存的目录/
--policy-config-filejson 配置文件,用来指定调度器的 Predicates 和 Priorites 策略/

​ ​

关于自定义策略的 JSON 文件的格式示例如下:

{
  "kind": "Policy",
  "apiVersion": "v1",
  "predicates":
    [
      { "name": "PodFitsHostPorts" },
      { "name": "PodFitsResources" },
      { "name": "NoDiskConflict" },
      { "name": "NoVolumeZoneConflict" },
      { "name": "MatchNodeSelector" },
      { "name": "HostName" },
    ],
  "priorities":
    [
      { "name": "LeastRequestedPriority", "weight": 1 },
      { "name": "BalancedResourceAllocation", "weight": 1 },
      { "name": "ServiceSpreadingPriority", "weight": 1 },
      { "name": "EqualPriority", "weight": 1 },
    ],
  "hardPodAffinitySymmetricWeight": 10,
  "alwaysCheckAllPredicates": false,
}