《蹲坑学kubernetes》之9-3:kube-scheduler原理详解

一、kube-scheduler的作用

kube-scheduler是一个调度器,负责调度Pod到集群内的Node节点上。监听kube-apiserver上Node和Pod变化情况。查询Node节点上未分配的Pod,根据调度策略为这些Pod分配Node节点。

《蹲坑学kubernetes》之9-3:kube-scheduler原理详解

图1:kube-scheduler调度过程

在调度过程中需要考虑:

  • 公平调度
  • 资源合理和高效利用
  • 服务质量(QoS)
  • 灵活性
  • 可扩展性和高可用性
  • 内部负载干扰

二、kube-scheduler工作原理

《蹲坑学kubernetes》之9-3:kube-scheduler原理详解

图2:kube-scheduler调度原理

kube-scheduler调度分为两个阶段:predicate 和 priority

predicate:过滤不符合条件的节点

priority:优先级排序,选择优先级最高的节点

1、predicates 策略:

PodFitsPorts:同 PodFitsHostPorts

PodFitsHostPorts:检查是否有 Host Ports 冲突

PodFitsResources:检查 Node 的资源是否充足

(包括允许的 Pod 数量、CPU、内存、GPU 个数以及其他的 OpaqueIntResources )

HostName:检查 pod.Spec.NodeName 是否与候选节点一致

MatchNodeSelector:检查候选节点的 pod.Spec.NodeSelector 是否匹配

NoVolumeZoneConflict:

检查 volume zone 是否冲突

MaxEBSVolumeCount:检查 AWS EBS Volume 数量是否过多(默认不超过 39)

MaxGCEPDVolumeCount:检查 GCE PD Volume 数量是否过多(默认不超过 16)

MaxAzureDiskVolumeCount:检查 Azure Disk Volume 数量是否过多(默认不超过 16)

MatchInterPodAffinity:检查是否匹配 Pod 的亲和性要求

NoDiskConflict:检查是否存在 Volume 冲突,仅限于 GCE PD、AWS EBS、Ceph RBD 以及 ISCSI

GeneralPredicates:分为 noncriticalPredicates 和 EssentialPredicates。

( noncriticalPredicates 中包含 PodFitsResources)

( EssentialPredicates 中包含 PodFitsHost,PodFitsHostPorts 和 PodSelectorMatches )

PodToleratesNodeTaints:检查 Pod 是否容忍 Node Taints

CheckNodeMemoryPressure:检查 Pod 是否可以调度到 MemoryPressure 的节点上

CheckNodeDiskPressure:检查 Pod 是否可以调度到 DiskPressure 的节点上

NoVolumeNodeConflict:检查节点是否满足 Pod 所引用的 Volume 的条件

2、priorities 策略:

SelectorSpreadPriority:优先减少节点上属于同一个 Service 或 Replication Controller 的 Pod 数量

InterPodAffinityPriority:优先将 Pod 调度到相同的拓扑上(如同一个节点、Rack、Zone 等)

LeastRequestedPriority:优先调度到请求资源少的节点上

BalancedResourceAllocation:优先平衡各节点的资源使用

NodePreferAvoidPodsPriority:alpha.kubernetes.io/preferAvoidPods 字段判断, 权重为 10000,避免其他优先级策略的影响

NodeAffinityPriority:优先调度到匹配 NodeAffinity 的节点上

TaintTolerationPriority:优先调度到匹配 TaintToleration 的节点上

ServiceSpreadingPriority:尽量将同一个 service 的 Pod 分布到不同节点上,已经被 SelectorSpreadPriority 替代 [默认未使用]

EqualPriority:将所有节点的优先级设置为 1[默认未使用]

ImageLocalityPriority:尽量将使用大镜像的容器调度到已经下拉了该镜像的节点上 [默认未使用]

MostRequestedPriority:尽量调度到已经使用过的 Node 上,特别适用于 cluster-autoscaler[默认未使用]

3、自定义策略

kube-scheduler还支持使用--policy-config-file指定一个调度策略文件来自定义调度策略,如下图所示:

《蹲坑学kubernetes》之9-3:kube-scheduler原理详解

图3:kube-scheduler调度策略

三、指定Node节点调度

有三种方式指定 Pod 只运行在指定的 Node 节点上

1、nodeSelector:只调度到匹配指定 label 的 Node 上

首先给 Node 打上标签:

kubectl label nodes k8s-node-1 disktype=ssd

然后在 daemonset 中指定 nodeSelector 为 disktype=ssd

2、nodeAffinity:功能更丰富的 Node 选择器,比如支持集合操作。

nodeAffinity 目前支持两种:requiredDuringSchedulingIgnoredDuringExecution 和 preferredDuringSchedulingIgnoredDuringExecution,分别代表必须满足条件和优选条件。比如下面的例子代表调度到包含标签 kubernetes.io/e2e-az-name 并且值为 e2e-az1 或 e2e-az2 的 Node 上,并且优选还带有标签 another-node-label-key=another-node-label-value 的 Node。

3、podAffinity:调度到满足条件的 Pod 所在的 Node 上

podAffinity基于Pod的标签来选择Node,仅调度到满足条件Pod所在的Node上,支持podAffinity和podAntiAffinity。

三、设置污点(Taints)和容忍(tolerations)

Taints 和 tolerations 用于保证 Pod 不被调度到不合适的 Node 上,其中 Taint 应用于 Node 上,而 toleration 则应用于 Pod 上。目前支持的 taint 类型:

NoSchedule:新的Pod不调度到该Node 上,不影响正在运行的Pod

PreferNoSchedule:soft版的NoSchedule,尽量不调度到该 Node 上

NoExecute:新的Pod不调度到该 Node 上,并且删除(evict)已在运行的Pod。Pod可以增加一个时间(tolerationSeconds),

然而,当Pod的Tolerations匹配Node的所有Taints的时候可以调度到该Node上;当Pod是已经运行的时候,也不会被删除(evicted)。另外对于NoExecute,如果Pod增加了一个tolerationSeconds,则会在该时间之后才删除Pod。

例: node1上应用以下几个taint:

<code>[root@k8s-master ~]# kubectl taint nodes k8s-master key1=value1:NoSchedule
[root@k8s-master ~]# kubectl taint nodes k8s-master key1=value1:NoExecute
[root@k8s-master ~]# kubectl taint nodes k8s-master key2=value2:NoSchedule/<code>


四、优先级调度与多调度器

1、优先级调度

从 v1.8 开始,kube-scheduler 支持定义 Pod 的优先级,从而保证高优先级的 Pod 优先调度。并从 v1.11 开始默认开启。在指定 Pod 的优先级之前需要先定义一个 PriorityClass。value为32位整数的优先级,值越大,优先级越高。

2、多调度器

如果默认的调度器不满足要求,还可以部署自定义的调度器。并且,在整个集群中还可以同时运行多个调度器实例,通过 podSpec.schedulerName 来选择使用哪一个调度器(默认使用内置的调度器)。


分享到:


相關文章: