
目录
一般情况下,我们部署的pod是通过的自动调度策略来选择节点的,默认情况下调度器考虑的是资源足够,并且负载尽量平衡,但是有的时候需要能够更加细粒度的去控制Pod的调度,比如我们内部的一些服务gitlab 之类的也是跑在kubernetes集群上的,我们就不希望对外的的一些服务和内部的服务跑在同一节点上了,担心内部服务对外部服务产生影响;但是有的时候我们的服务之间交流比较频繁,有希望能够将这两个服务的pod调度到同一节点上,这就需要用到kubernetes李面的一个概念:亲和性和反亲和性。
亲和性有分为节点亲和性(nodeAffinity和nodeAntiAffinity)和pod亲和性(podAffinity和podAntiAffinity)
- 针对亲和性来讲,in代表我要调度到有这个标签的位置
- 针对反亲和性来讲,in代表我不要调度到有这个标签的位置
preferredDuringSchedulingIgnoredDuringExecution 软亲和
软策略:意思就是尽量不要讲pod调度到匹配到的节点,但是如果没有不匹配的节点的话,也可以调度到匹配到的节点。
requiredDuringSchedulingIgnoredDuringExecution 硬亲和
硬策略:意思就是必须调度到满足条件的节点上,否则就会pending。
不管是使用那种方式,最终还是要依赖label标签
- kubectl get pods -n company ai-action-statistic-gray-86465f9c4b-hdfk4 -oyaml | grep nodeSelector -B 5 -A 5
- uid: ed47f094-f70a-45ed-b7dd-d46f2d01986f
- spec:
- affinity:
- nodeAffinity:
- requiredDuringSchedulingIgnoredDuringExecution: #硬策略
- nodeSelectorTerms:
- - matchExpressions:
- - key: node-role.kubernetes.io/gray
- operator: In
- values:
- - gray
- preferredDuringSchedulingIgnoredDuringExecution: #软策略
- - weight: 1
- preference:
- matchExpressions:
- - key: pc-app
- operator: NotIn
- values:
- - luna
-
K8S 每个节点上都可以应用一个或者多个taint,这表示对于那些不能容忍这些taint 的pod,是不会被该节点接受的,如果将taleration应用于pod上,则表示这些pod可以(但不要求)被调到具有相应taint的节点上。

使用kubectl、taint命令可以给某个node节点设置污点。node被设置上污点之后就和pod之间存在了一种相斥的关系,可以让node拒绝pod的调度执行,甚至将node已经存在的pod驱逐出去。
每个污点的组成如下:
key=value:effect
每个污点有一个key和value作为污点的标签,其中value可以为空,effect描述污点的作用。
污点有三种策略
PreferNoSchedule:NoSchedule的软策略版本,表示尽量不调度到污点节点上去。
NoExecute:该选项意味着一旦Taint生效,如该节点内正在运行的Pod没有对应容忍(Tolerate)设置,则会直接被逐出。
NoSchedule:表示k8s将不会将Pod调度到具有该污点的Node上
使用kubectl设置和去除污点的命令示例如下:
- # 设置污点
- kubectl taint nodes node1 key1=value1:NoSchedule
- # 去除污点
- kubectl taint nodes node1 key1:NoSchedule-
接下来看一个具体的例子,使用kubeadm部署和初始化的Kubernetes集群,master节点被设置了一个node-role.kubernetes.io/master:NoSchedule的污点,可以使用kubectl describe node 命令查看。这个污点表示默认情况下master节点将不会调度运行Pod,即不运行工作负载。对于使用二进制手动部署的集群设置和移除这个污点的命令如下:
- kubectl taint nodes <node-name> node-role.kubernetes.io/master=:NoSchedule
- kubectl taint nodes <node-name> node-role.kubernetes.io/master:NoSchedule-
设置了污点的node将根据taint的effect,NoSchedule、PreferNoSchedule、NoExecute和Pod之间产生互斥的关系,Pod将在一定程度上不会被调度到Node上。 但我们可以在Pod上设置容忍(Toleration),意思是设置了容忍的Pod将可以容忍污点的存在,可以被调度到存在污点的Node上。
pod 的 Toleration 声明中的 key 和 effect 需要与 Taint 的设置保持一致,并且满足以下条件之一:
operator 的值为 Exists,这时无需指定 value
operator 的值为 Equal 并且 value 相等
如果不指定 operator,则默认值为 Equal。
另外还有如下两个特例:
空的 key 配合 Exists 操作符能够匹配所有的键和值
空的 effect 匹配所有的 effect
上面的例子中 effect 的取值为 NoSchedule,下面对 effect 的值作下简单说明:
NoSchedule:如果一个 pod 没有声明容忍这个 Taint,则系统不会把该 Pod 调度到有这个 Taint 的 node 上
PreferNoSchedule:NoSchedule 的软限制版本,如果一个 Pod 没有声明容忍这个Taint,则系统会尽量避免把这个 pod 调度到这一节点上去,但不是强制的。
NoExecute:定义 pod 的驱逐行为,以应对节点故障。
NoExecute 这个 Taint 效果对节点上正在运行的 pod 有以下影响:
没有设置 Toleration 的 Pod 会被立刻驱逐
配置了对应 Toleration 的 pod,如果没有为 tolerationSeconds 赋值,则会一直留在这一节点中
配置了对应 Toleration 的 pod 且指定了 tolerationSeconds 值,则会在指定时间后驱逐
- tolerations:
- - key: "key1"
- operator: "Equal"
- value: "value1"
- effect: "NoSchedule"
- tolerationSeconds: 3600
- - key: "key1"
- operator: "Equal"
- value: "value1"
- effect: "NoExecute"
- - key: "key2"
- operator: "Exists"
- effect: "NoSchedule"
下面看一下在Pod上设置容忍的两个特例:
示例1: 当不指定key值时,表示容忍所有的污点key:
- tolerations:
- - operator: "Exists"
示例2:当不指定effect值时,表示容忍所有的污点作用:
- tolerations:
- - key: "key"
- operator: "Exists"
注意,在节点故障情况下,为了保持现存的 pod 驱逐的限速设置,系统将会以限速的模式逐步给 node 设置 Taint,这就能防止在一些特定情况下(比如 master 暂时失联)造成的大量 pod 被驱逐的后果。这一功能兼容于 tolerationSeconds,允许 pod 定义节点故障时持续多久才被逐出。
**系统允许在同一个 node 上设置多个 taint,也可以在 pod 上设置多个 Toleration。**Kubernetes 调度器处理多个 Taint 和 Toleration 能够匹配的部分,剩下的没有忽略掉的 Taint 就是对 Pod 的效果了。下面是几种特殊情况:
- kubectltaint nodes node1 key1=value1:NoSchedule
- kubectl taint nodes node1 key1=value1:NoExecute
- kubectl taint nodes node1 key2=value2:NoSchedule