四大调度方式
- 自动调度:运行在哪个节点上完全由 Scheduler 经过一系列的算法计算得出
- 定向调度:NodeName、NodeSelector
- 亲和性调度:NodeAffinity、PodAffinity、PodAntiAffinity
- 污点(容忍)调度:Taints、Toleration
自动调试
完全交由 kube-scheduler 来决定 pod 调度到哪里,不受人为控制。
定向调度
NodeName
NodeName用于强制约束将Pod调度到指定的Name的Node节点上。这种方式,其实是直接跳过Scheduler的调度逻辑,直接将Pod调度到指定名称的节点。
使用实例:
apiVersion: v1
kind: Pod
metadata:
name: pod-nodename
namespace: dev
spec:
nodeName: kube-11 # 指定调度到 kube-11 节点上
containers:
- name: nginx
image: nginx:1.17.1
这种调度不够灵活,必须指定某 node 节点,若 node 异常会导致调度失败。
NodeSelector
NodeSelector 用于将 pod 调度到添加了指定标签的 node 节点上。它是通过 kubernetes 的 label-selector 机制实现的。
使用实例:
# 给 node 机器打上标签
k label no kube-11 node-type=cpu
apiVersion: v1
kind: Pod
metadata:
name: pod-nodeselector
namespace: dev
spec:
nodeSelector:
node-type: cpu # 指定调度到具有 node-type=cpu 标签的节点上
containers:
- name: nginx
image: nginx:1.17.1
相对于 nodeName 调度方式更加灵活一些,不再局限于某 node 节点。而是选择 node 上的标签进行调度。
亲和性调度
亲和性是一大调度特色,适应了大多数场景而且做到了非常灵活的调度。
关于亲和性(反亲和性)使用场景的说明:
-
亲和性:如果两个应用频繁交互,那就有必要利用亲和性让两个应用的尽可能的靠近,这样可以减少因网络通信而带来的性能损耗。
-
反亲和性:当应用的采用多副本部署时,有必要采用反亲和性让各个应用实例打散分布在各个node上,这样可以提高服务的高可用性。
亲和性又分硬限制与软限制:
requiredDuringSchedulingIgnoredDuringExecution
必须满足条件才能调度。preferredDuringSchedulingIgnoredDuringExecution
尽量满足条件,不满足也没关系。
NodeAffinity
以node为目标,解决pod可以调度到哪些node的问题
使用实例(硬限制):
- 硬限制,label 值必须存在才能调到成功,否则调度失败。
apiVersion: v1 kind: Pod metadata: name: pod-nodeaffinity-required namespace: dev spec: affinity: #亲和性设置 nodeAffinity: #设置node亲和性 requiredDuringSchedulingIgnoredDuringExecution: # 硬限制 nodeSelectorTerms: - matchExpressions: # 匹配 env 的值在["xxx","yyy"]中的标签 - key: node-type operator: In # 支持:In, NotIn, Exists, DoesNotExist, Gt, Lt values: ["cpu", "gpu"] containers: - name: nginx image: nginx:1.17.1 resources: {}
- 软限制,相比硬限制,会尽量调到存在 label 的机器上,不存在的 label 值也会被调度成功。
apiVersion: v1 kind: Pod metadata: name: pod-nodeaffinity-preferred namespace: dev spec: affinity: #亲和性设置 nodeAffinity: #设置node亲和性 preferredDuringSchedulingIgnoredDuringExecution: # 软限制 - weight: 1 # 权重 取值范围是 1 到 100,在调度器为 Pod 作出调度决定时,总分最高的节点的优先级也最高。 preference: # 优先调度,尽量调度 matchExpressions: # 匹配规则 - key: node-type # 存在 node label operator: In # 包括 values: # label 值,如果不存在则也会调度成功。 - net - gpu containers: - name: nginx image: nginx:1.17.1
PodAffinity
PodAffinity主要实现以运行的Pod为参照,实现让新创建的Pod跟参照pod在一个区域的功能。
使用实例:
- 硬限制,应用 label app=nginx 值必须存在才能调到成功,否则调度失败。
apiVersion: v1 kind: Pod metadata: name: pod-podaffinity-required namespace: dev spec: affinity: #亲和性设置 podAffinity: #设置pod亲和性 requiredDuringSchedulingIgnoredDuringExecution: # 硬限制 - labelSelector: # label 选择器 matchExpressions: # 匹配env的值在["xxx","yyy"]中的标签 - key: app # 某应用 app=nginx, app=kong operator: In values: ["nginx", "kong"] topologyKey: kubernetes.io/hostname containers: - name: nginx image: nginx:1.17.1
- 软限制,相比硬限制,会尽量调到存在应用 label app=nginx,不存在的应用 label app=nginx 值也会被调度成功。
apiVersion: v1 kind: Pod metadata: name: pod-podaffinity-preferred namespace: dev spec: affinity: #亲和性设置 podAffinity: #设置pod亲和性 preferredDuringSchedulingIgnoredDuringExecution: # 软限制 - weight: 100 # 权重,取值范围:0~100 podAffinityTerm: labelSelector: matchExpressions: - key: app operator: In values: - pod-nodeselector topologyKey: kubernetes.io/hostname containers: - name: nginx image: nginx:1.17.1
PodAntiAffinity
PodAntiAffinity主要实现以运行的Pod为参照,让新创建的Pod跟参照pod不在一个区域中的功能。
使用实例:
- 硬限制,应用 label app=pod-nodeselector 值必须存在才能调到成功,否则调度失败。
apiVersion: apps/v1 kind: Deployment metadata: name: deploy-podantiaffinity-required namespace: dev annotations: info: "pod 反亲和性之硬限制" spec: selector: matchLabels: app: deploy-podantiaffinity-required template: metadata: labels: app: deploy-podantiaffinity-required spec: affinity: podAntiAffinity: requiredDuringSchedulingIgnoredDuringExecution: - labelSelector: matchExpressions: - key: app operator: In values: - pod-nodeselector topologyKey: "kubernetes.io/hostname" containers: - name: client image: nginx:1.17.1
- 软限制,相比硬限制,会尽量调到存在应用 label app=store ,不存在的应用 label app=store 值也会被调度成功。
apiVersion: apps/v1 kind: Deployment metadata: name: deploy-podantiaffinity-preferred namespace: dev annotations: info: "pod 反亲和性之软限制" spec: selector: matchLabels: app: deploy-podantiaffinity-preferred template: metadata: labels: app: deploy-podantiaffinity-preferred spec: affinity: podAntiAffinity: preferredDuringSchedulingIgnoredDuringExecution: - weight: 100 podAffinityTerm: labelSelector: matchExpressions: - key: app operator: In values: - store topologyKey: "kubernetes.io/hostname" containers: - name: client image: nginx:1.17.1
污点(容忍)调度
前面的调度方式都是站在Pod的角度上,通过在Pod上添加属性,来确定Pod是否要调度到指定的Node上,其实我们也可以站在Node的角度上,通过在Node上添加污点属性,来决定是否允许Pod调度过来。
Node被设置上污点之后就和Pod之间存在了一种相斥的关系,进而拒绝Pod调度进来,甚至可以将已经存在的Pod驱逐出去。
污点的格式为:key=value:effect, key和value是污点的标签,effect描述污点的作用,支持如下三个选项:
- PreferNoSchedule:kubernetes将尽量避免把Pod调度到具有该污点的Node上,除非没有其他节点可调度
- NoSchedule:kubernetes将不会把Pod调度到具有该污点的Node上,但不会影响当前Node上已存在的Pod
- NoExecute:kubernetes将不会把Pod调度到具有该污点的Node上,同时也会将Node上已存在的Pod驱离
污点
使用kubectl设置和去除污点的命令示例如下:
# 设置污点
kubectl taint nodes node1 key=value:effect
# 去除污点
kubectl taint nodes node1 key:effect-
# 去除所有污点
kubectl taint nodes node1 key-
容忍
上面介绍了污点的作用,我们可以在node上添加污点用于拒绝pod调度上来,但是如果就是想将一个pod调度到一个有污点的node上去,这时候应该怎么做呢?这就要使用到容忍。
污点就是拒绝,容忍就是忽略,Node通过污点拒绝pod调度上去,Pod通过容忍忽略拒绝
apiVersion: v1
kind: Pod
metadata:
name: pod-toleration
namespace: dev
labels:
app: pod-toleration
spec:
tolerations: # 添加容忍
- key: "node-role.kubernetes.io/master" # 要容忍的污点的key
operator: "Exists" # 操作符 支持Equal和Exists
# value: "" # 容忍的污点的value
effect: "NoSchedule" # 添加容忍的规则,这里必须和标记的污点规则相同
# tolerationSeconds: 10 # 容忍时间, 当effect为NoExecute时生效,表示pod在Node上的停留时间。如果为0或负则立即驱逐。
containers:
- name: nginx
image: nginx:1.17.1