Schedule 总结
kube-scheduler 是 kubernetes 集群的默认调度器,官方允许用户根据自己的需求编写特定的调度器来替换 kube-scheduler。kube-scheduler 通过以下 2 个步骤来实现对 Pod 的调度:
- 过滤,根据 Pod 定义的条件,如"required"强制限制节点 label 匹配,以及限制 Pod 必须满足某些条件,对于
podAffinity
可以有多个labelSelector
等条件,对于nodeAffinity
只能是一个,但是可用多个matchExpressions
等条件 - 打分,根据 Pod 定义的
nodeAffinity
与podAffinity
,以及nodeAntiAffinity
,podAntiAffinity
等"preferred"偏好条件,以及weight
打分(weight 数值越高,Pod 越有可能被调度到对应条件的节点上)
可用的过滤条件
- 节点标签:如
kubernetes.io/hostname
,kubernetes.io/os
- 节点隔离/限制:如
NodeRestriction
插件使用的带有node-restriction.kubernetes.io
前缀的标签 .spec.affinity.nodeAffinity
.spec.affinity.podAffinity
与.spec.afffinity.podAntiAffinity
,以及.spec.affinity.podAffinity.[].topologyKey
集群用来标识域的节点标签键namespaceSelector
(v1.29 alpha).spec.nodeName
有一些局限性,这个条件不稳定- 如节点不存在,Pod 无法运行,在某些情况下可能被自动删除
- 在云环境中的节点名称并总不是可预测与稳定的
- 当然节点没有对应的资源运行该 Pod,仍然会失败,这个条件在非
.spec.nodeName
情况都满足,只不过非.spec.nodeName
条件 Pod 部署不一定会失败,有可能是处于pending
可选的方式
requiredDuringSchedulingIgnoredDuringExecution
硬性条件,强制限制preferredDuringSchedulingIgnoredDuringExecution
软性条件,偏好限制,有更好,没有也可以,该方式是一个数组,可以提供weight
(越大越优先)来加强或减弱某个条件
可用的选项
nodeAffinity
nodeSelectorTerms
podAffinity
与podAntiAffinity
matchLabelKeys
mismatchLabelKeys
topologyKey
labelSelector
- …
可用的操作符
操作符 | 行为 | 适用对象 |
---|---|---|
In | 标签值匹配提供的字符串集 | nodeAffinity , podAffinity , podAntiAffinity |
NotIn | 标签值不匹配提供的字符串集 | nodeAffinity , podAffinity , podAntiAffinity |
Exists | 存在具有此键的标签 | nodeAffinity , podAffinity , podAntiAffinity |
DoesNotExist | 不存在具有此键的标签 | nodeAffinity , podAffinity , podAntiAffinity |
Gt | 标签的值 > 该数 | nodeAffinity |
Lt | 标签的值 < 该数 | nodeAffinity |
调度方案
-
逐个调度方案中设置
nodeAffinity
,需要在调度适配器启用NodeAffinity 插件apiVersion: kubescheduler.config.k8s.io/v1beta3 kind: KubeSchedulerConfiguration profiles: - schedulerName: default-scheduler - schedulerName: foo-scheduler pluginConfig: - name: NodeAffinity args: addedAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: scheduler-profile operator: In values: - foo
Pod 调度就绪状态 (v1.27 beta)
通过指定.spec.schedulingGates
可以控制 Pod 何时准备好被考虑调度。如果 Pod 已经就绪,可以将对应的字段清空,然后对 Pod 执行更新操作。如果指定了该字段,有以下情况允许,更新对应字段:
- 如果设置了该字段,在没有
.spec.nodeSelector
的情况下,可以允许更新此字段 - 如果
spec.affinity.nodeAffinity
为 nil,则允许设置任意值 - 如果
NodeSelectorTerms
之前没有设置,则现在允许设置;如果之前已经设置了,那么仅允许添加对应的条目,不允许更新之前已经存在的条目 - 对于
preferredDuringSchedulingIgnoredDuringExecution
,所有更新现在都允许
可以使用scheduler_pending_pods{queue="gated"}
查看调度的具体指标情况。需结合一些指标组件,如metric-server
。
Pod 拓扑分布域
分布域是一个类似组的概念对集群中的节点进行分组,按区域划分,使整个大的集群有一定的抗风险与自愈能力。.spec.topologySpreadConstraints
定义了对集群可用区使用的调度规则,使用该功能最重要的要求是如果集群自动为节点打的标签无法满足需求,用户需要自定义标签的时候,需要保证集群所有的 key 的一致性,否则调度结果可能会匪夷所思,排查也会很困难。
---
apiVersion: v1
kind: Pod
metadata:
name: example-pod
spec:
# 配置一个拓扑分布约束
topologySpreadConstraints: # 多个条目之间是逻辑与关系,默认无特别说明都是逻辑与
- maxSkew: <integer>
minDomains: <integer> # 可选;自从 v1.25 开始成为 Beta
topologyKey: <string>
whenUnsatisfiable: <string>
labelSelector: <object>
matchLabelKeys: <list> # 可选;自从 v1.27 开始成为 Beta
nodeAffinityPolicy: [Honor|Ignore] # 可选;自从 v1.26 开始成为 Beta
nodeTaintsPolicy: [Honor|Ignore] # 可选;自从 v1.26 开始成为 Beta
...
maxSkew
描述这些 Pod 可能被不均匀分布的程度,具体受制于whenUnsatisfiable: DoNotSchedule
描述可用区分布 Pod 数量最小值的差值whenUnsatisfiable: ScheduleAnyway
该调度器会更为偏向能够降低偏差值的拓扑域
minDomains
表示符合条件的域的最小数量topologyKey
节点标签 keywhenUnsatisfiable
:DoNotSchedule
(default),ScheduleAnyway
labelSelector
用于查找匹配的 PodmatchLabelKeys
用于选择需要计算分布方式的 Pod 集合,matchLabelKeys
和labelSelector
不允许有相同的 keynodeAffinityPolicy
:Honor
,Ignore
nodeTaintsPolicy
:Honor
,Ignore
隐式约定
- 只有与新来的 Pod 具有相同命名空间的 Pod 才能作为匹配候选者
- 调度器会忽略没有任何
topologySpreadConstraints[*].topologyKey
的节点,意味着这些节点上的 Pod 不会影响maxSkew
的计算 topologySpreadConstraints[*].labelSelector
与 Pod 自身的标签不匹配,将不会改善集群的不平衡程度
集群级别的默认约束
apiVersion: kubescheduler.config.k8s.io/v1beta3
kind: KubeSchedulerConfiguration
profiles:
- schedulerName: default-scheduler
pluginConfig:
- name: PodTopologySpread
args:
defaultConstraints:
- maxSkew: 1
topologyKey: topology.kubernetes.io/zone
whenUnsatisfiable: ScheduleAnyway
defaultingType: List
为集群设置默认的拓扑约束,可以在以下条件满足时被应用到 Pod 上:
- Pod 没有在其
.spec.topologySpreadConstraints
中定义任何约束 - Pod 隶属于某个 Service、ReplicaSet、StatefulSet 或 ReplicationController
内置的默认约束 (v1.24 stable)
defaultConstraints: # 可以被用户覆写
- maxSkew: 3
topologyKey: "kubernetes.io/hostname"
whenUnsatisfiable: ScheduleAnyway
- maxSkew: 5
topologyKey: "topology.kubernetes.io/zone"
whenUnsatisfiable: ScheduleAnyway
已知的局限 (截止 v1.29.3)
- 当缩减某个控制器控制的 Pod 时,现阶段的方案无法保证 Pod 分布均衡
- 具有污点的节点上匹配的 Pod 也会被统计
- 任何情况下至少保证每个拓扑域(节点组)中至少有一个可用节点,否则调度可能会异常