学习目标:掌握调度器原理,能够根据要求把pod定义到想要的节点运行

一、简介:

  A、Scheduler是作为单独的程序运行的,启动之后会一直坚挺API Server,获取Pod.Spec.NodeName为空的pod,对每个pod都会创建一个binding,表明该pod应该放在哪个节点上。

二、调度过程

  A、调度分为几个部分,首先是过滤掉不满足条件的节点,这个过程成为predicate。然后对通过的节点按照优先级排序,这个是priority;最后从中选择优先级最高的节点。如果中间任何一步骤有错,就直接返回错误。

    1. predicate算法:

      a. PodFitsResources:节点上剩余的资源是否大于pod请求的资源。

      b. PodFitsHost:如果pod指定了NodeName,检查节点名称和NodeName是否匹配

      c. PodFitsHostPorts:节点上已经使用的port是否和pod申请的port冲突

      d. PodSelectorMatches:过滤掉和pod指定的label不匹配的节点。

      e. NoDiskConflict:已经mount的volume和pod指定的volume不冲突,除非它们都是只读

    2. 如果在predicate过程中没有合适的节点,pod会一直处于pending状态,不断重试调度,直到有节点满足条件。经过这个步骤,如果有多个节点满足要求,就继续priority过程:按照优先级大小对节点排序,优先级由一系列键值对组成,键是该优先级的名称,值是它的权重(该项的重要性)。这些优先级选项包括:

      a. LeastRequestedPriority:通过计算CPU和Memory的使用率来决定权重,使用率越低权重越高。换句话说,这个优先级指标倾向于资源使用比例更低的节点。

      b. BalancedResourceAllocation:节点上CPU和Memory使用率越接近,权重越高。这个应该和上面的一起使用,不应该单独使用。

      c. ImageLocalityPriority:倾向于已经有要使用镜像的节点,镜像总大小值越大,权重越高。

      通过算法对所有的优先级项目和权重进行计算,得出最终结果。

三、调度亲和性

  A、节点亲和性

    1. pod.spec.nodeAffinity

    

a. preferredDuringSchedulingIgnoredDuringExecution:软策略
        apiVersion: v1
        kind: Pod
        metadata:
            name: preferred-node-affinity-pod
            labels:
                app: preferred-node-affinity-pod
        spec:
            containers:
              - name: node-affinity-container
                  image: hub.atguigu.com/library/myapp:v1
            affinity:
                nodeAffinity:
                    preferredDuringSchedulingIgnoredDuringExecution:
                      - weight: 1
                          preference:
                            matchExpressions:
                              - key: kubernetes.io/hostname
                                  operator: In
                                  values:
                                    - k8s-node02      b. requiredDuringSchedulingIgnoredDuringExecution:硬策略
        apiVersion: v1
        kind: Pod
        metadata:
            name: node-affinity-pod
            labels:
                app: node-affinity-pod
        spec:
            containers:
              - name: node-affinity-container
                  image: hub.atguigu.com/library/myapp:v1          affinity:
                nodeAffinity:
                    requiredDuringSchedulingIgnoredDuringExecution:
                        nodeSelectorTerms:
                          - matchExpressions:
                              - key: kubernetes.io/hostname
                                  operator: NotIn
                                  values:
                                  - k8s-node02

    3. 键值运算关系

      a. In:label的值在某个列表中

      b. NotIn:label的值不在某个列表中

      c. Gt:label的值大于某个值

      d. Lt:label的值小于某个值

      e. Exists:某个label存在

      f. DoesNotExist:某个label不存在

    4. 注意:如果nodeSelectorTerms下面有多个选项的话,满足任何一个条件就可以了;如果matchExperssions有多个选项的话,则必须同时满足这些条件才能正常调度 

  B、Pod亲和性

    1. pod.spec.affinity.podAffinity/podAntiAffinity(在一个拓扑域/不在一个拓扑域)

    

a. preferredDuringSchedulingIgnoredDuringExecution:软策略
        apiVersion: v1
        kind: Pod
        metadata:
            name: preferred-pod-affinity-pod
            labels:
                app: preferred-pod-affinity-pod
        spec:
            containers:
              - name: preferred-pod-affinity-container
                  image: hub.atguigu.com/library/myapp:v1
                  imagePullPolicy: IfNotPresent
            affinity:
                podAffinity:
                    preferredDuringSchedulingIgnoredDuringExecution:
                      - weight: 1
                          podAffinityTerm:
                            labelSelector:
                                matchExpressions:
                                  - key: app
                                      operator: In
                                      values:
                                      - test-pod1
                            topologyKey: kubernetes.io/hostname      b. requiredDuringSchedulingIgnoreDuringExecution:硬策略
        apiVersion: v1
        kind: Pod
        metadata:
            name: required-pod-affinity-pod
            labels:
                app: required-pod-affinity-pod
        spec:
            containers:
              - name: required-pod-affinity-container
                  image: hub.atguigu.com/library/myapp:v1
            affinity:
                podAntiAffinity:
                    requiredDuringSchedulingIgnoredDuringExecution:
                      - labelSelector:
                            matchExpressions:
                              - key: app
                                  operator: In
                                  values:
                                  - test-pod1
                          topologyKey: kubernetes.io/hostname

    2. 拓扑域(选择的标签相同的一组node就是一个拓扑域)

四、Taint和Toleration(污点和容忍)

  A、节点亲和性,是pod的一种属性(偏好或硬性要求),它使pod被吸引到一类特定的节点。Taint则相反,它使节点能够排斥一类特定的pod。taint和toleration互相配合,可以用来避免pod被分配到不合适的节点上。每个节点上都可以应用一个或多个taint,这表示对于那些不能容忍这些taint的pod,是不会被该节点接受的。如果将toleration应用于pod上,则表示这些pod可以(但不要求)被调度到具有匹配taint的节点上

  B、Taint(污点)

    1. 污点的组成

      a. 使用kubectl taint命令可以给某个node节点设置污点,node被设置上污点之后就和pod之间存在了一种互斥的关系,可以让node拒绝pod的调度执行,甚至将已经存在的pod驱逐出去

      b. 组成:key=value:effect,每个污点有一个key和value作为污点的标签,其中value可以为空,effect描述污点的作用。当前taint effect有以下三种:

        1) NoSchedule:表示k8s将不会将pod调度至具有该污点的node上

        2)PreferNoSchedule:表示k8s将尽量避免将pod调度至该pod上

        3)NoExecute:表示k8s将不会将pod调度到具有该污点的node上,同时会将Node上已经存在的Pod驱逐出去

    2. 污点的设置、查看和去除

      a. 设置污点

        kubectl taint nodes node1 key1=value1:NoSchedule

      b. 查看污点

        kubectl describe node node-name(查找Taints字段)

      c. 去除污点

        kubectl taint nodes node1 key1:NoSchedule-

  C、容忍

    1. 设置了污点的node将根据taint的effect:NoSchedule、PreferNoSchedule、NoExecute和pod之间产生互斥关系,Pod将在一定程度上不会被调度到Node上。但我们可以在pod上设置容忍(toleration),意思是设置了容忍的pod将可以容忍污点的存在,可以被调度到存在污点的ode上。

    2. 例子

     

apiVersion: v1
      kind: Pod
      metadata:
          name: test-pod1
          labels:
              app: test-pod1
      spec:
          containers:
            - name: test-pod1-container
                image: hub.atguigu.com/library/myapp:v1
          tolerations:
            - key: "app"
                operator: "Equal"
                value: "test-pod1"
                effect: "NoExecute"
                tolerationSeconds: 120

      其中key、value、effect要与node上设置的taint保持一致

      operato的值为Exists会忽略value值

      tolerationSeconds用于描述当pod需要被驱逐时还可以在pod上继续保留运行的时间

    3. 当不指定key时,表示容忍所有的污点key:

      toleration:

        - operator: "Exists"

    4. 当不指定effect值时,表示容忍所有的污点作用

      toleration:

        - key: "key"

          operator: "Exists"

    5. 有多个master时,为了防止资源浪费,可以如下设置

      kubectl taint odes Node-Name node-role.kubernetes.io/master=:PreferNoSchedule

五、指定调度节点

  A、Pod.spec.nodeName将pod直接调度到指定的node节点上,会跳过schedule的调度策略,该匹配是最强匹配

  

apiVersion: extensions/v1beta1
    kind: Deployment
    metadata:
        name: node-name-schedule-deployment
    spec:
        replicas: 7
        template:
            metadata:
                name: node-name-schedule-pod
                labels:
                    app: node-name-schedule-label
            spec:
                nodeName: k8s-node01
                containers:
                  - name: node-name-schedule-container
                      image: hub.atguigu.com/library/myapp:v1
                      ports:
                      - containerPort: 80

  B、Pod.spec.nodeSelector:通过kubernetes的label-selector机制选择节点,由调度器调度策略匹配label,而后调度pod到目标节点,该匹配规则属于强制约束

    

apiVersion: extensions/v1beta1
    kind: Deployment
    metadata:
        name: node-selector-deployment
    spec:
        replicas: 2
        template:
            metadata:
                name: node-selector-pod
                labels:
                    app: node-selector-pod-label
            spec:
                nodeSelector:
                    disk: ssd
                containers:
                  - name: node-selector-container
                      image: hub.atguigu.com/library/myapp:v1
                      ports:
                      - containerPort: 80