# 9.3pod的调度

kubernetes是如何找到满足pod要求的节点的呢？

## kubernetes调度pod的步骤

后期补充

* 预选策略的主要工作：剩余的内存、CPU满足要求、对端口的检查，端口不能冲突、挂载的volume是否匹配，nodeSelector的规则必须匹配、节点必须是ready的
*   优选策略的主要工作：对上一步筛选出来的node进行评分，评分的标准如下：

    整体的CPU、内存平衡性；node上是否存在需要运行的镜像；同一个deploy下的pod是否已经调度了；亲和性、方亲和、污点等

## 示例

## 节点准备

节点标签如下：

dh-nerbu-20.120-docker.cn

**app=ingress**,beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/hostname=dh-nerbu-20.120-docker.cn

dh-nerbu-20.121-docker.cn

beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,**disktype=ssh**,kubernetes.io/hostname=dh-nerbu-20.121-docker.cn

## 配置节点亲和性

预选策略（Predicate）排除不满足要求的结点

```yaml
affinity:
  nodeAffinity:
    requiredDuringSchedulingIgnoredDuringExecution:
      nodeSelectorTerms:
      - matchExpressions:
        - key: beta.kubernetes.io/arch
          operator: In
          values:
          - amd64
```

> 注意：requiredDuringSchedulingIgnoredDuringExecution表示必须满足的条件，若不满足，pod将无法被调度
>
> 需要关注点
>
> * key：节点label的名字
> * operator：可选择：In、NotIn、Exist

优选策略（priority）对上一步筛选出来的node进行评分，选择最高分的node作为pod的部署节点

```yaml
affinity:
  nodeAffinity:
    preferredDuringSchedulingIgnoredDuringExecurtion:
    - weight: 1
      preference:
        matchExpressions:
        - key: disktype
          operator: NotIn
          values:
          - ssd
```

> 注意：对于优选策略，若找不到符合优选策略的节点，pod也将被调度。

## 配置pod的亲和性

在一定的区域范围内和其他pod的亲和关系，比如想和某些pod运行在一起，不想和某些pod运行在一起

```yaml
affinity:
  podAffinity:
    requiredDuringSchedulingIgnoredDuringExecution:
    - labelSelector:
        matchExpressions:
        - key: app
          operator: In
          values:
          - web-demo
        topologkey: kubernetes.io/hostname
    preferredDuringSchedulingIgnoredDuringExecurtion:
    - weight: 100
      podAffinityTerm:
        labelSelector:
          matchExpressions:
          - key: app
            operator: In
            values:
              - web-demo-node
        topologykey: kubernetes.io/hostname
```

> 提示：当亲和性配置为自身时，代表同一个deploy的不同pod将跑在同一节点上
>
> topologyKey：限定了范围，我们的节点上都存在kubernetes.io/hostname，故该设置代表存在label为kubernetes.io/hostname的节点。

pod的反亲和性调度

```yaml
affinity:
  podAntiAffinity:
    requiredDuringSchedulingIgnoredDuringExecution:
    - labelSelector:
        matchExpressions:
        - key: app
          operator: In
          values:
          - web-demo
        topologkey: kubernetes.io/hostname
```

> 提示：当反亲和的value指定为自己时，代表同一个deploy的不同pod将跑在不同的节点上

## 污点和污点容忍性

在node上设置污点，以达到拒绝某些pod运行在该node上，除非某些pod申明了能够容忍这些污点，否则pod将无法运行在打了污点的node上。

```bash
$ kubectl taint nodes NODE_NAME TAINT_NAME=TAINT_VALUE：EFFECT
$ kubectl taint nodes 10.12.1.121-node gpu=true：NoSchedule
```

污点达到的效果

NoSchedule:调度器不会把pod调度到该节点

preveNoSchedule：最好不要把pod调度到 该节点上

Noexcute：除了新创建的pod不能调度到该节点外，已经存在该节点上的未设置容忍的pod将被驱逐，未设置容忍时间，pod将立即将驱逐，设置了容忍时间，到达容忍时间后，pod才被驱逐

pod设置污点容忍

```yaml
spec:
  tolerations:
  - key: "gpu"    # 污点的key
    operator: "Equal"
    value: "true"  # 污点的value
    effect: "NoSchedule"  # 必须配置，且必须与污点的effect一致
```

> 注意：effect必须要配置上，且必须要与node打污点时使用的effect一致
>
> 注意：设置了污点容忍的pod也可以运行在没设置污点的节点上
>
> operator可设置：Equal（相等）、Exist（污点key存在就可以生效，与value无关）
