kubernetes.png 调度 是指将 Pod 放置到合适的 Node 上,然后对应 Node 上的 Kubelet 才能够运行这些 pod。

调度概览

调度器通过 kubernetes 的监测(Watch)机制来发现集群中新创建且尚未被调度到 Node 上的 Pod。 调度器会将发现的每一个未调度的 Pod 调度到一个合适的 Node 上来运行。 调度器会依据下文的调度原则来做出调度选择。

kube-scheduler调度流程

kube-scheduler 给一个 pod 做调度选择包含两个步骤:

  1. 过滤
  2. 打分

过滤阶段会将所有满足 Pod 调度需求的 Node 选出来。

打分阶段,调度器会为 Pod 从所有可调度节点打分选取一个最合适的 Node。

NodeSelector定向调度

NodeSelector:是一个供用户将 Pod 与 Node 进行绑定的字段.

apiVersion: v1
kind: Pod
...
spec:
 nodeSelector:
   disktype: ssd

指明Pod永远只能运行在携带“disktype: ssd”标签的节点上;否则会调度失败

Kubernetes内置的节点标签

除了你给Node(节点)添加标签外,Kubernetes也会给Node预设义一些标签,包括:

Labels:             beta.kubernetes.io/arch=amd64
                    beta.kubernetes.io/os=linux
                    edgenode=true
                    kubernetes.io/arch=amd64
                    kubernetes.io/hostname=ycloud
                    kubernetes.io/os=linux
                    node-role.kubernetes.io/control-plane=
                    node-role.kubernetes.io/master=
                    node.kubernetes.io/exclude-from-external-load-balancers=

注意:这些标签的值是特定于云提供商的,不保证是可靠的。例如,kubernetes.io/hostname的值可能与某些环境中的节点名称相同,而在其他环境中就不同了。

nodeName调度

nodeName是最简单的节点选择约束方式,我常常用它来将pod直接指定到某台节点上,进行测试。

<!--注意:如果它不为空,则调度程序不会在调度这个pod了,并且在命名节点上运行的kubelet尝试运行该pod。因此,如果在PodSpec中提供nodeName,则它将优先于其他的约束。-->

apiVersion: v1
kind: Pod
...
spec:
 nodeName: ycloud

该pod将运行在名为ycloud的节点上了

Node Affinity

用节点亲和性把 Pods 分配到节点

依据强制的节点亲和性调度 Pod

下面清单描述了一个 Pod,它有一个节点亲和性配置 requiredDuringSchedulingIgnoredDuringExecutiondisktype=ssd。 这意味着 pod 只会被调度到具有 disktype=ssd 标签的节点上。

apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
          - key: disktype
            operator: In
            values:
            - ssd            
  containers:
  - name: nginx
    image: nginx
    imagePullPolicy: IfNotPresent

使用首选的节点亲和性调度 Pod

本清单描述了一个Pod,它有一个节点亲和性设置 preferredDuringSchedulingIgnoredDuringExecutiondisktype: ssd。 这意味着 pod 将首选具有 disktype=ssd 标签的节点。

apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  affinity:
    nodeAffinity:
      preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 1
        preference:
          matchExpressions:
          - key: disktype
            operator: In
            values:
            - ssd          
  containers:
  - name: nginx
    image: nginx
    imagePullPolicy: IfNotPresent

Taint和Toleration(污点和容忍)

节点亲和性是pod的一种属性(优先选择或硬性要求),它使 pod 被优先分配到一类特定的节点上。而Taint则相反,它使节点能够排斥一类特定的 pod。

使用kubectl taint给节点增加一个污点

[root@ycloud ~]# kubectl taint nodes ycloud app=test:NoSchedule
node/ycloud tainted
若要移除这个污点
[root@ycloud ~]# kubectl taint nodes ycloud app=test:NoSchedule-
node/ycloud untainted

你可以在 Pod 规约中为 Pod 设置容忍度。 下面两个容忍度均与上面例子中使用 kubectl taint 命令创建的污点相匹配, 因此如果一个 Pod 拥有其中的任何一个容忍度,都能够被调度到 node

tolerations:
- key: "app"
  operator: "Equal"
  value: "test"
  effect: "NoSchedule"
tolerations:
- key: "app"
  operator: "Exists"
  effect: "NoSchedule"

例子:

apiVersion: v1
kind: Pod
metadata:
  name: nginx
  labels:
    env: test
spec:
  containers:
  - name: nginx
    image: nginx
    imagePullPolicy: IfNotPresent
  tolerations:
  - key: "app"
    operator: "Exists"
    effect: "NoSchedule"

operator 的默认值是 Equal

一个容忍度和一个污点相“匹配”是指它们有一样的键名和效果,并且:

  • 如果 operatorExists (此时容忍度不能指定 value),或者
  • 如果 operatorEqual ,则它们的 value 应该相等

参考文献

https://kubernetes.io/zh-cn/docs/concepts/scheduling-eviction/kube-scheduler/

https://kuboard.cn/learning/k8s-advanced/schedule/#filtering