前面说的kubernetes的scheduler用来对pod做调度,整个调度过程通过执行一系列的复杂的算法,最终为每个Pod都计算出一个最佳的目标节点,这一过程是自动完成的,我们是不知道pod调度到哪台节点的,但是有时候我们需要把pod调度到特定的节点上,所以标签选择器(nodeSelector)就派上用场了。
kubectl label nodes k8s-node01 server=hahaha
# kubectl get node -l server=hahaha
NAME STATUS ROLES AGE VERSION
k8s-node03 Ready <none> 26d v1.15.1
apiVersion: apps/v1
kind: Deployment
metadata:
name: test-label
labels:
name: test-label
spec:
replicas: 1
strategy:
rollingUpdate:
maxSurge: 1
maxUnavailable: 1
type: RollingUpdate
selector:
matchLabels:
name: test-label
template:
metadata:
labels:
name: test-label
spec:
containers:
- name: test-label
image: alpha-harbor.ysmty.com/onair/xinhuawang-test-ab:v1.0.0
imagePullPolicy: IfNotPresent
resources:
limits:
cpu: 4
memory: 4096Mi
requests:
cpu: 500m
memory: 500Mi
nodeSelector:
server: hahaha
imagePullSecrets:
- name: mima-alpha
这里添加的nodeSelector
就是把pod调度到指定到节点上。
# kubectl get pod -o wide | grep test-label
test-label-58985d8db8-szqd4 1/1 Running 0 11s 172.17.135.158 k8s-node03 <none> <none>
注意:
如果给多个Node都定义了相同的标签,则Secheduler会根据调度算法从这组Node中挑选一个可用的Node进行Pod调度
nodeSelector
提供的是一种非常简单的方法来将 pod 约束到具有特定标签的节点上。NodeAffinity是用于替换NodeSelector的全新调度策略,这个调度策略多了更多的逻辑控制,可以更细粒度的去调度pod到节点上,关键的增强点是
目前有两种类型的节点亲和,分别为 requiredDuringSchedulingIgnoredDuringExecution
和 preferredDuringSchedulingIgnoredDuringExecution
。你可以视它们为“硬”和“软”,意思是,前者指定了将 pod 调度到一个节点上必须满足的规则(就像 nodeSelector
但使用更具表现力的语法),后者指定调度器将尝试执行但不能保证的规则。
“IgnoredDuringExecution” 类似于 nodeSelector
的工作原理,如果节点的标签在运行时发生变更,从而不再满足 pod 上的亲和规则,那么 pod 将仍然继续在该节点上运行。
真是粗又长啊!!
必须满足指定的规则才可以调度Pod到Node上,相当于硬限制
强调优先满足指定规则,调度器会尝试调度Pod到Node上,但并不强求,相当于软限制,多个优先级可以设置权重
在介绍示例之前,先补充一下NodeAffinity的表达式
DESCRIPTION:
In
NotIn
Exists
DoesNotExist
Gt
Lt
都是字面意思,没什么可解释的。
如上图,这个k8s集群,一共是三个node节点,其中设置了两个标签
apiVersion: apps/v1
kind: Deployment
metadata:
name: test-label
labels:
name: test-label
spec:
replicas: 1
strategy:
rollingUpdate:
maxSurge: 1
maxUnavailable: 1
type: RollingUpdate
selector:
matchLabels:
name: test-label
template:
metadata:
labels:
name: test-label
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: server
operator: NotIn
values:
- daobo
- hahaha
containers:
- name: test-label
image: alpha-harbor.ysmty.com/onair/xinhuawang-test-ab:v1.0.0
imagePullPolicy: IfNotPresent
resources:
limits:
cpu: 4
memory: 4096Mi
requests:
cpu: 500m
memory: 500Mi
imagePullSecrets:
- name: mima-alpha
为了满足示例场景,再创建一个标签,但是这次有些不同,我们需要再次在k8s-node03
上创建一个标签,k8s-node02
上还是没有标签。
# kubectl label nodes k8s-node03 fuck=lalala
node/k8s-node03 labeled
然后,我们看看硬限制的优先级是不是更高
apiVersion: apps/v1
kind: Deployment
metadata:
name: test-label
labels:
name: test-label
spec:
replicas: 1
strategy:
rollingUpdate:
maxSurge: 1
maxUnavailable: 1
type: RollingUpdate
selector:
matchLabels:
name: test-label
template:
metadata:
labels:
name: test-label
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: fuck
operator: In
values:
- lalala
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 1
preference:
matchExpressions:
- key: server
operator: NotIn
values:
- daobo
- hahaha
containers:
- name: test-label
image: alpha-harbor.yunshicloud.com/onair/xinhuawang-test-ab:v1.0.0
imagePullPolicy: IfNotPresent
resources:
limits:
cpu: 4
memory: 4096Mi
requests:
cpu: 500m
memory: 500Mi
imagePullSecrets:
- name: mima-alpha
这里我们通过软限制,限制了只要节点上带有server=daobo
或者server=hahaha
的标签,pod就不会调度到上面去,但是我们又设置了一个硬限制,只要节点的标签中带有fuck=lalala
的标签,pod就会调度到该pod上去。从这里可以看出硬限制只要是满足条件,就会调度到该节点上去。
以上就是通过节点的标签选择器和节点亲和性、反亲和性来控制pod的调度,通过NodeSelector
可以更加直观和简单的展现出调度结果,而通过NodeAffinity
则可以更加细粒度的去控制Pod调度到哪些node节点上。通过这些手段,我们可以控制一些pod,例如,有时候,有的pod需要共用同一个宿主机,有的pod需要分别调度到不同的节点上等等。