调度方式
- 定向调度
- 亲和性调度
- 污点与容忍
1. 定向调度
1.1 nodeName
nodeName 用于强制约束将Pod调度到指定Name的Node节点上。这种方式,其实是跳过Scheduler的调度逻辑,直接将Pod调度到指定名称的节点上。
1.2 nodeSelector
nodeSelector 用于将Pod调度到指定标签的Node节点上。它是通过k8s的label-selector机制实现的,在Pod创建之前,会由Scheduler使用MatchNodeSelector调度策略进行label匹配,找出目标node。然后将Pod调度到目标节点,该匹配是强制约束
apiVersion: v1
kind: Pod
metadata:
name: podsc
namespace: dev
spec:
#nodeName: 192.168.0.30
# nodeSelector:
# nodename: node20
containers:
- image: 192.168.0.200/public/nginx:v1
imagePullPolicy: Always
name: podsc
2.亲和性调度
2.1 nodeAffinity node亲和性
nodeAffinity 是以node为目标,解决Pod可以调度到那些node的问题。
注意:
a. 如果同时设置了nodeSelector和nodeAffinity那么必须要满足这两个条件才能调度到节点上。
b. 如果nodeAffinity指定了多个nodeSelectorTerms,那么只需要满足一个能够匹配成功即可调度。
c. 如果一个nodeSelectorTerms中有多个matchExpressions,则同一个节点必须要满足所有的才能匹配成功。
d. 如果一个pod所在的Node在Pod运行期间标签发生了改变,不再符合Pod的节点亲和性需求,则系统忽略此变化。因为已经经过scheduler调度。只有重新部署触发scheduler才能重新调度。
应用场景:
- 特殊资源使用:例如磁盘ssd,pod需要高IO性能。
- 特殊场景:重点业务需要部署在常年没有出现过故障的机器上等。
2.1.1 requiredDuringSchedulingIgnoredDuringExecution 硬限制,必须要node满足这些条件才能调度,否则就调度不上去, 不经过scheduler 这个也属于定向调度
apiVersion: v1
kind: Pod
metadata:
name: affinitytest
namespace: dev
spec:
containers:
- name: affinitytest
image: 192.168.0.200/public/nginx:v1
imagePullPolicy: Always
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: nodename
operator: In
values: ["node20", "node21"]
2.1.2 preferredDuringSchedulingIgnoredDuringExecution 软限制,非必要满足这些条件,需要经过scheduler,当不满足这些条件时则选择其他节点。
apiVersion: v1
kind: Pod
metadata:
name: affinitytest
namespace: dev
spec:
containers:
- name: affinitytest
image: 192.168.0.200/public/nginx:v1
imagePullPolicy: Always
affinity:
nodeAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 10
preference:
matchExpressions:
- key: nodename
operator: In
values: ["node24", "node23"] //没有这些标签的
2.2 podAffinity pod亲和性
podAffinity 是以pod为目标,解决pod可以和哪些已存在的pod部署在同一个拓扑域中的问题。
应用场景:
- Pod之间需要频繁交互,有必要使用亲和性让两个应用尽可能的靠近,这样可以减少因网络通信而带来的性能损耗。
- 高可用场景下,将同一个业务的pod将其自动放到部署了相同应用pod的机器上。
2.2.1 preferredDuringSchedulingIgnoredDuringExecution 软限制即不满足也可调度
# pod亲和度参照Pod
apiVersion: v1
kind: Pod
metadata:
name: test
namespace: dev
labels:
kk: vv
spec:
containers:
- name: test
image: 192.168.0.200/public/nginx:v1
# Pod亲和度使用软限制
apiVersion: v1
kind: Pod
metadata:
name: affinitytest
namespace: dev
spec:
containers:
- name: affinitytest
image: 192.168.0.200/public/nginx:v1
imagePullPolicy: Always
affinity:
podAffinity:
preferredDuringSchedulingIgnoredDuringExecution: #硬限制
- weight: 10
podAffinityTerm:
namespaces: #指定参照Pod的名称空间[]
- "dev"
topologyKey: kubernetes.io/hostname #指定匹配后的调度作用域
labelSelector:
matchExpressions:
- key: kk
operator: In
values:
- "vv"
- "bb"
2.2.2 requiredDuringSchedulingIgnoredDuringExecution 硬限制不满足则无法调度直接报错
# pod亲和度参照Pod
apiVersion: v1
kind: Pod
metadata:
name: test
namespace: dev
labels:
kk: vv
spec:
containers:
- name: test
image: 192.168.0.200/public/nginx:v1
# Pod亲和度使用硬限制
apiVersion: v1
kind: Pod
metadata:
name: affinitytest
namespace: dev
spec:
containers:
- name: affinitytest
image: 192.168.0.200/public/nginx:v1
imagePullPolicy: Always
affinity:
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: "kk"
operator: In
values:
- "yy"
- "xx"
namespaces:
- "dev"
topologyKey: kubernetes.io/hostname
2.3 podAntiAffinity pod反亲性
podAntiAffinity 是以pod为目标,解决pod不能和哪些已存在pod部署在同一个拓扑域中的问题
- 当应用采用多副本部署时,有必要采用反亲和性进行打散,可以有效提高服务的高可用性。
注意:反亲和硬限制情况下,如果没有 匹配到指定标签的pod 那么就会按照其他算法来进行分配。一般还会搭配其他调度算法进行调度。
2.3.1 Pod反亲和性requiredDuringSchedulingIgnoredDuringExecution硬限制
apiVersion: v1
kind: Pod
metadata:
name: affinitytest
namespace: dev
spec:
containers:
- name: affinitytest
image: 192.168.0.200/public/nginx:v1
imagePullPolicy: Always
affinity:
podAntiAffinity: #Pod反亲和性
requiredDuringSchedulingIgnoredDuringExecution: #硬限制
- labelSelector:
matchExpressions: #匹配kk的值在yy 或者 xx 中的标签
- key: "kk"
operator: In
values:
- "yy"
- "vv"
namespaces:
- "dev"
topologyKey: kubernetes.io/hostname #作用域主机打散
2.3.1 Pod反亲和性preferredDuringSchedulingIgnoredDuringExecution软限制
apiVersion: v1
kind: Pod
metadata:
name: affinitytest
namespace: dev
spec:
containers:
- name: affinitytest
image: 192.168.0.200/public/nginx:v1
imagePullPolicy: Always
affinity:
podAntiAffinity: #Pod反亲和性
preferredDuringSchedulingIgnoredDuringExecution: #硬限制
- labelSelector:
matchExpressions: #匹配kk的值在yy 或者 xx 中的标签
- key: "kk"
operator: In
values:
- "yy"
- "vv"
namespaces:
- "dev"
topologyKey: kubernetes.io/hostname #作用域主机打散
3.污点与容忍
3.1 污点
通过在Node上添加污点属性,决定是否允许Pod调度过来。
污点的格式为:key=value:effect
key和value是污点的标签,effect描述污点的作用,支持如下三个选项:
- PreferNoSchedule: Scheduler尽量避免把Pod调度到具有该污点的Node上,除非没有其他节点可调度。
- NoSchdule: Scheduler不会把Pod调度到具有该污点的Node上,但是不会影响当前Node上已经存在的Pod。
- NoExecute: Scheduler不会把Pod调度到具有该污点的Node上,同时也会将Node上已经存在的Pod隔离,除非是容忍程度为NoExecute。
注意:当节点打上污点设置为NoSchedule时通过指定节点(nodeName)任然可以设置运行到该节点,但是使用nodeSelector就不可以。
- 设置污点:
kubectl taint node NODENAME KEY=VALUE:EFFECT
- 去除污点
kubectl taint nodes NODENAME KEY:EFFECT-
- 去除所有污点
kubectl taint nodes NODENAME KEY-
3.2 容忍污点
当节点设置了污点时,如果允许Pod调度到该污点上时需要在pod中设置容忍污点。 pod.spec.toleroations
apiVersion: v1
kind: Pod
metadata:
name: test33
namespace: dev
labels:
kk: vv
spec:
nodeName: 192.168.0.21
containers:
- name: test33
image: 192.168.0.200/public/nginx:v1
tolerations: //容忍污点
- key: "tag" // 对应污点KEY,若为空则意味着匹配所有的键
operator: "Equal" // 匹配符,支持Equal和Exists(默认)
value: "tagtaint" // 对应污点值
effect: "NoExecute" // 对应污点的级别,空则匹配所有
#tolerationSeconds: //容忍时间,当effect为NoExecute时生效,表示pod在Node上停留的时间,当时间到期时将会从此节点转移走,若永远没有设置则永远不会被剔除
[root@master10 yaml]# kgpoowiden dev
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
test33 1/1 Running 0 9s 172.20.4.223 192.168.0.21 <none> <none>
[root@master10 yaml]# kdno 192.168.0.21 | grep Ta
Taints: tag=tagtaint:NoExecute
4.隔离与驱逐
- 通常在需要对Node进行停机维护时,一般需要进行对节点的隔离拒绝新的Pod调度到该节点上。
kubectl describe node NODENAME
程序也是通过对节点添加不可调度的污点来进行的隔离,使用的隔离程度为:NoSchedule,使用nodeName来进行指定调度,依然可以调度上去,可以避免资源不足导致新的Pod所有节点不可调度后导致节点Pending。
- 第二步即为对node节点上的Pod进行驱逐,drain会是一个平滑终止的过程,不会影响业务。
kubectl drain NODENAME --ignore-daemonsets --force
通常情况下需要忽略掉daemonset,此处还有一些没有被控制器控制的pod需要强制驱逐
- 查看当前节点上剩余的pod
[root@master10 yaml]# kgpoowideall | grep 0.20
default daemon1-4w2ng 1/1 Running 0 28m 172.20.3.156 192.168.0.20 <none> <none>
kube-system kube-flannel-ds-amd64-wngbj 1/1 Running 0 28m 192.168.0.20 192.168.0.20 <none> <none>
kube-system node-local-dns-7frgs 1/1 Running 8 41d 192.168.0.20 192.168.0.20 <none> <none>
monitoring node-exporter-52rqc 2/2 Running 16 41d 192.168.0.20 192.168.0.20 <none> <none>
- 确认没有后就可以进行维护或者将机器踢出集群后进行维护。维护完毕后取消隔离。
kubectl uncordon NODENAME
- 通过scalePod数量查看节点是否调度后完毕。