调度 基本概述 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 2 3 4 5 6 7 8 9 10 11 12 13 apiVersion: v1 kind: Pod metadata: name: nginx labels: env : test spec: containers: - name: nginx image: nginx imagePullPolicy: IfNotPresent nodeSelector: disktype: ssd
上述例子中,Pod将会只调度到包含disktype=ssd的node上。
方式二、nodeName 1 2 3 4 5 6 7 8 9 10 11 12 13 apiVersion: v1 kind: Deployment metadata: name: webpc spec: replicas: 1 template: metadata: labels: app: webpc spec: nodeName: web-server ...
上述例子中,将会只调度到主机名为web-server的node上。
方式三、亲和性 NodeAffinity 亲和性调度,用来取代nodeSelector的策略,支持IN,NOTLn,exists,doesNotExit,GT,Lt。
又分为两类:
soft,表示调度的时候,无法满足节点的时候会选择非nodeSelector匹配的节点。PreferredDuringSchedulingIgnoreDuringExecution 优先满足制定规则,并不强求 hard,表示调度的时候,必须满足亲和性设置。requiredDuringSchedulingIgnoredDuringExecution 必须调度到满足条件的节点,如不满足,则一直重试。 也可以分为三类:
亲和节点 NodeAffinity 亲和Pod podAffinity 不亲和Pod podAntiAffinity 示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 apiVersion: apps/v1 kind: StatefulSet metadata: name: eureka spec: serviceName: "eureka" selector: matchLabels: app: eureka-pod replicas: 3 template: metadata: labels: app: eureka-pod spec: affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: kubernetes.io/hostname operator: In values: - k8s-node-217 ~ eureka-0 1/1 Running 0 2d23h 10.200.128.142 uat-master <none> <none> eureka-1 1/1 Running 0 2d23h 10.200.128.141 uat-master <none> <none> eureka-2 0/1 ContainerCreating 0 1s <none> k8s-node-217 <none> <none>
上述示例中,terms满足一个条件就行(或的关系),但是match的条件必须全部满足(且的关系)。
调度到不同的节点 调度到不同的节点,在亲和性中的应用需要使用到topolgyKey。toplogyKey 对应的值是node上的一个标签的名称,比如节点zone=A 标签,其他节点有zone=B 标签。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 KIND: StatefulSet VERSION: apps/v1 RESOURCE: affinity <Object> DESCRIPTION: If specified, the pod's scheduling constraints Affinity is a group of affinity scheduling rules. FIELDS: nodeAffinity <Object> Describes node affinity scheduling rules for the pod. podAffinity <Object> Describes pod affinity scheduling rules (e.g. co-locate this pod in the same node, zone, etc. as some other pod(s)). podAntiAffinity <Object> Describes pod anti-affinity scheduling rules (e.g. avoid putting this pod in the same node, zone, etc. as some other pod(s)).
1 2 3 4 5 6 7 8 9 10 11 12 kubectl explain --api-version=apps/v1 sts.spec.template.spec.affinity.podAffinity.requiredDuringSchedulingIgnoredDuringExecution.topologyKey KIND: StatefulSet VERSION: apps/v1 FIELD: topologyKey <string> DESCRIPTION: This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching the labelSelector in the specified namespaces, where co-located is defined as running on a node whose value of the label with key topologyKey matches that of any node on which any of the selected pods is running. Empty topologyKey is not allowed.
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 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 apiVersion: apps/v1 kind: StatefulSet metadata: name: eureka spec: serviceName: "eureka" selector: matchLabels: app: eureka-pod replicas: 3 template: metadata: labels: app: eureka-pod spec: affinity: podAntiAffinity: requiredDuringSchedulingIgnoredDuringExecution: - topologyKey: kubernetes.io/hostname labelSelector: matchExpressions: - key: app operator: In values: - eureka-pod
上述示例中指定创建了label为app=eureka-pod
的statefulSet,并且指定副本数量为3。根据反亲和性规则,以kubernetes.io/hostname
为key的拓扑域,将不会调度到node上已经运行了label为app=eureka-pod
的Pod,这样就会将3个副本分别部署在不同hostname的node上。
验证:
1 2 3 4 ~ eureka-0 1/1 Running 0 5m47s 10.200.128.152 uat-master <none> <none> eureka-1 0/1 Pending 0 38s <none> <none> <none> <none> eureka-2 1/1 Running 0 108s 10.200.96.155 k8s-node-217 <none> <none>
由于示例中只有两个node,因此有一个Pod处于pending状态,但是其他的两个节点均被分配了Pod。
亲和性的进阶应用:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 spec: affinity: podAntiAffinity: requiredDuringSchedulingIgnoredDuringExecution: - topologyKey: kubernetes.io/hostname labelSelector: matchExpressions: - key: app operator: In values: - eureka-pod podAffinity: requiredDuringSchedulingIgnoredDuringExecution: - topologyKey: kubernetes.io/hostname labelSelector: matchExpressions: - key: app operator: In values: - geteway-pod
上述例子中,根据反亲和性和亲和性规则,每个节点上都会有eureka-pod的Pod,和gateway-pod的Pod。
参考 https://kubernetes.io/zh/docs/reference/labels-annotations-taints/