调度
基本概述
kube-scheduler 是kubernetes 集群的默认调度器,该调度器将Pod绑定在对应的node上,之后对应的node上的kubelet才能够创建和运行Pod。
对每个新建的Pod或者未被调度的Pod,kube-scheduler 会选择一个最优的node去运行这个Pod。Pod内的每个容器以及自身都有不通的资源需求。因此,Pod在被调度之前,会根据特定的资源调度需求,对集群中的Node进行一次过滤。
调度器会在集群中过滤后的可调度节点,根据一些列函数进行打分,最终选择出得分最高的node。之后,调度器将这个调度通知给kube-apiserver,进行绑定。
亲和性
原则
- 同时指定了nodeSelector和nodeAffinity,必须同时满足两个条件
- 如果nodeAffinity指定了多个nodeSelectorTerms,满足一个即可
- 如果在nodeSelectorTerms中有多个matchExpressions,则一个节点必须满足全部才可以加
- 如果修改或删除了Pod所调度到的节点的标签,Pod不会被删除
- 软策略中的weight属性代表权重,范围1-100。如果存在多个软策略的话,权重越大越亲和。对于反亲和规则而言,权重越大越不亲和
应用的运行对于kubernetes在亲和性上有一些要求,可以概况为以下几个方面:
- Pod固定调度的某些节点上
- Pod不会调度到某些节点上
- Pod的多个副本调度到相同节点上
- Pod的多个副本调度不同节点上
调度到某些节点上
方式一、nodeSelector
在对于Pod的定义中通过nodeSelector指定label,Pod将会只调度到具有该标签的node上。
1 | apiVersion: v1 |
上述例子中,Pod将会只调度到包含disktype=ssd的node上。
方式二、nodeName
1 | apiVersion: v1 |
上述例子中,将会只调度到主机名为web-server的node上。
方式三、亲和性
NodeAffinity 亲和性调度,用来取代nodeSelector的策略,支持IN,NOTLn,exists,doesNotExit,GT,Lt。
又分为两类:
- soft,表示调度的时候,无法满足节点的时候会选择非nodeSelector匹配的节点。PreferredDuringSchedulingIgnoreDuringExecution 优先满足制定规则,并不强求
- hard,表示调度的时候,必须满足亲和性设置。requiredDuringSchedulingIgnoredDuringExecution 必须调度到满足条件的节点,如不满足,则一直重试。
也可以分为三类:
- 亲和节点 NodeAffinity
- 亲和Pod podAffinity
- 不亲和Pod podAntiAffinity
示例:
1 | apiVersion: apps/v1 |
上述示例中,terms满足一个条件就行(或的关系),但是match的条件必须全部满足(且的关系)。
调度到不同的节点
调度到不同的节点,在亲和性中的应用需要使用到topolgyKey。toplogyKey 对应的值是node上的一个标签的名称,比如节点zone=A 标签,其他节点有zone=B 标签。
1 | KIND: StatefulSet |
1 | kubectl explain --api-version=apps/v1 sts.spec.template.spec.affinity.podAffinity.requiredDuringSchedulingIgnoredDuringExecution.topologyKey |
topology 就是拓扑的意思,指的是一个拓扑域,一个范围的概念,比如一个node、一个机柜、一个机房,实际对应的是node的标签。而这里的topologyKey对应的是node上标签的Key。那么怎么样才算属于一个拓扑域呢?
如果使用k8s.io/hostname
,则表示拓扑域为node范围,那么k8s.io/hostname
对应的值不一样的就是不同的拓扑域。比如Pod1在k8s.io/hostname=n1
的node上,Pod2在k8s.io/hostname=n2
的node上,Pod3在k8s.io/hostname=n1
的node上。那么Pod1和Pod3在一个拓扑域,Pod2 则和其他两个Pod不在同一个拓扑域。因此,概况来说,拥有相同标签的key,就可以认定为在同一个拓扑域。
原则上,topologyKey可以是任何合法的标签key,但是有一些限制:
- topologyKey不可以为空
- 对于
requiredDuringSchedulingIgnoredDuringExecution
的 Pod 反亲和性,引入 LimitPodHardAntiAffinityTopology 准入控制器来限制 topologyKey 只能是 kubernetes.io/hostname。如果要使用自定义拓扑域,则可以修改准入控制器,或者直接禁用它。 - 对于 preferredDuringSchedulingIgnoredDuringExecution 的 Pod 反亲和性,空的 topologyKey 表示所有拓扑域。除上述情况外,topologyKey 可以是任何合法的标签 key。
此外,还有一些官网文档中提示的拓扑域可以使用:
- topology.kubernetes.io/region
- topology.kubernetes.io/zone
示例:
1 | apiVersion: apps/v1 |
上述示例中指定创建了label为app=eureka-pod
的statefulSet,并且指定副本数量为3。根据反亲和性规则,以kubernetes.io/hostname
为key的拓扑域,将不会调度到node上已经运行了label为app=eureka-pod
的Pod,这样就会将3个副本分别部署在不同hostname的node上。
验证:
1 | ~# kubectl get pods -o wide |grep eureka |
由于示例中只有两个node,因此有一个Pod处于pending状态,但是其他的两个节点均被分配了Pod。
亲和性的进阶应用:
1 | spec: |
上述例子中,根据反亲和性和亲和性规则,每个节点上都会有eureka-pod的Pod,和gateway-pod的Pod。