kubernetes 节点调度nodeSelector和nodeAffinity(40)

2023年 7月 16日 53.3k 0

之前的scheduler,默认的default scheduler分三部实现调度过程,首先是预选,从所有节点当中选择基本符合选择条件的节点,而后在众多基本符合选择条件的节点中通过优选函数,对这些节点加以比较。并且从最高得分当中随机选择一个作为运行pod的节点。这就是scheduler负责的功用。

高级调度机制

节点调度

在某些调度参加中,可通过自己的预设来影响预选,优选的过程,从而使得调度的操作符合期望。如,一个pod应该固定的被运行在某个节点,就可以使用预设的方式来影响调度来达到预期的目的。

此类的影响方式有4种,这4种都可成为高级调度设置机制

1,节点选择器,如nodeSelector,nodename

2,节点亲和性调度,nodeAffinity

对于nodename来讲,我们期望将pod调度到某一个特定的节点之上,就可以在nodename属性当中直接给定node的名称,而后对应的这个pod,一定只能会调度到这个node节点之上。

如果有一类节点都符合调用的属性条件,并且我们期望调度到这类节点上,就可以使用nodeSelector,可以给一部分节点打上特有的标签,在pod配置当中使用nodeSelector匹配这些标签,节点能适配这些标签的就是pod可运行的节点之一。而这种方式也会非常大的缩小预选范围

1,nodeSelector

我们测试下nodeSelector的效果,如下图

nodeselector.png

linuxea.node-3.com节点之上,添加标签zone=linuxea.zone

[root@linuxea schedule]#  kubectl label nodes linuxea.node-3.com zone=linuxea.zone
node/linuxea.node-3.com labeled
[root@linuxea schedule]# kubectl get nodes --show-labels|grep zone
linuxea.node-3.com     Ready     <none>    39d       v1.11.2   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/hostname=linuxea.node-3.com,zone=linuxea.zone

而后绑定到linuxea.zone标签的节点之上

[root@linuxea schedule]# cat pods.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: linuxea-pods-1026
  namespace: default
  labels:
    app: linuxea.com
spec:
  containers:
  - name: pods-1026
    image: marksugar/nginx:1.14.a
    ports:
    - name: http
      containerPort: 80
  nodeSelector:
    zone: linuxea.zone
[root@linuxea schedule]# kubectl apply -f pods.yaml 
pod/linuxea-pods-1026 created
[root@linuxea schedule]# kubectl get pods  -o wide
NAME                 READY   STATUS    RESTARTS     AGE       IP    NODE    
linuxea-pods-1026   1/1      Running   0    2h   172.16.5.12    linuxea.node-3.com

此时linuxea-pods-1026名称的pod就运行在node3之上。因为只有node3才有 zone: linuxea.zone标签

  • 如果nodeSelector定义的标签在节点内不存在就会挂起。nodeSelector是签约束,如果不满足条件,在预选时候就会停止。

此刻将nodeSelector的标签修改成 zone: linuxea.zone.cn zone: linuxea.zone.cn是不存在的。

  nodeSelector:
    zone: linuxea.zone.cn

那么标签 zone: linuxea.zone.cn不存在在节点上,这个pod就会Pending。因为pod中nodeSelector的标签不存在。

[root@linuxea schedule]# kubectl apply -f pods.yaml 
pod/linuxea-pods-1026 created
[root@linuxea schedule]# kubectl get pods
NAME                READY     STATUS    RESTARTS   AGE
linuxea-pods-1026   0/1       Pending   0          3s

将node1.linuxea.com打上zone: linuxea.zone.cn标签,就会将linuxea-pods-1026调度到node1上

[root@linuxea schedule]# kubectl label nodes linuxea.node-1.com zone=linuxea.zone.cn
node/linuxea.node-1.com labeled
[root@linuxea schedule]# kubectl get pods -o wide
NAME                READY  STATUS    RESTARTS   AGE  IP             NODE              
linuxea-pods-1026   1/1    Running   0          46s  172.16.3.2     linuxea.node-1.com

2,nodeAffinity

pod.spec.affinity中就有affinity,在affinitynodeAffinity(节点亲和性),podAffinity(pod亲和性),podAntiAffinity(pod反亲和性)

nodeAffinity中有两项如下:

requiredDuringSchedulingIgnoredDuringExecution

requiredDuringSchedulingIgnoredDuringExecution是硬亲和性,也就是说必须满足条件。与nodeSelector相似,如果不满足亲和定义的条件,就一定不会运行,那么就会pending状态

preferredDuringSchedulingIgnoredDuringExecution

preferredDuringSchedulingIgnoredDuringExecution倾向性。优先运行满足节点亲和性高的节点上。尽量满足条件,如果不能够尽量的满足条件,那也可以找其他节点运行。当然,能够运行在亲和性高,满足条件多的节点是最好不过了。

preferredDuringSchedulingIgnoredDuringExecution下嵌套:

  • preference 倾向节点
  • weight 倾向权重

requiredDuringSchedulingIgnoredDuringExecution下的nodeSelectorTerms定义对象列表,并且嵌套节点选择器Terms。在nodeSelectorTerms之下嵌套

matchExpressions:匹配表达式

matchFields:匹配字段

  • matchFields下需要定义key,检查label key,操作符operator(等值或者不等值选择,以及集合的标签,如果使用exists,或者doesnotexist的时候values是不能有值的),values只需要给定值即可
  • matchExpressions 定义表达式基于标签选择。

开始测试requiredDuringSchedulingIgnoredDuringExecution

nodeaffinity.png

其中定义affinity.nodeAffinity.requiredDuringSchedulingIgnoredDuringExecution.nodeSelectorTerms.matchExpressions,定义key是zone,operator操作符是In,values是www.linuxea.com,而后在添加weight ,如上图yaml

  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
          - key: zone
            operator: In
            values:
            - www.linuxea.com

如下:

[root@linuxea schedule]# cat pods_nodeAffinity.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: linuxea-nodeaffinity
  namespace: default
  labels:
    app: linuxea.com
spec:
  containers:
  - name: pods-1026
    image: marksugar/nginx:1.14.a
    ports:
    - name: http
      containerPort: 80
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
          - key: zone
            operator: In
            values:
            - www.linuxea.com

apply

[root@linuxea schedule]# kubectl apply -f pods_nodeAffinity.yaml 
pod/linuxea-nodeaffinity created

此刻状态是Pending,因为目前并没有zone标签,且值是等值的www.linuxea.com的node

[root@linuxea schedule]# kubectl get pods -o wide
NAME                   READY     STATUS    RESTARTS   AGE       IP             NODE                 NOMINATED NODE
linuxea-nodeaffinity   0/1       Pending   0          9s        <none>         <none>               <none>

并且定义的是requiredDuringSchedulingIgnoredDuringExecution硬亲和性,在上述中,我们知道硬亲和性的话,如果不存在,就不会选中。所以被Pending

preferredDuringSchedulingIgnoredDuringExecution

那么这样以来就无法绑定了,我们尝试使用倾向性绑定,这和硬绑定requiredDuringSchedulingIgnoredDuringExecution不同,配置preference和weight即可,如下:

  affinity:
    nodeAffinity:
      preferredDuringSchedulingIgnoredDuringExecution:
      - preference:
          matchExpressions:
          - key: zone
            operator: In
            values:
            - www.linuxea.com
        weight: 60

如下:

[root@linuxea schedule]# cat pods_nodeAffinity-2.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: linuxea-nodeaffinity
  namespace: default
  labels:
    app: linuxea.com
spec:
  containers:
  - name: pods-1026
    image: marksugar/nginx:1.14.a
    ports:
    - name: http
      containerPort: 80
  affinity:
    nodeAffinity:
      preferredDuringSchedulingIgnoredDuringExecution:
      - preference:
          matchExpressions:
          - key: zone
            operator: In
            values:
            - www.linuxea.com
        weight: 60

apply

[root@linuxea schedule]# kubectl apply -f pods_nodeAffinity-2.yaml 
pod/linuxea-nodeaffinity created

而后调度到node2节点。

[root@linuxea schedule]# kubectl get pods -o wide
NAME                   READY     STATUS    RESTARTS   AGE       IP             NODE                 NOMINATED NODE
linuxea-nodeaffinity   1/1       Running   0          6s        172.16.4.9     linuxea.node-2.com   <none>
[root@linuxea schedule]# kubectl describe pods linuxea-nodeaffinity|tail -6
  Type    Reason     Age   From                         Message
  ----    ------     ----  ----                         -------
  Normal  Scheduled  6m    default-scheduler            Successfully assigned default/linuxea-nodeaffinity to linuxea.node-2.com
  Normal  Pulled     6m    kubelet, linuxea.node-2.com  Container image "marksugar/nginx:1.14.a" already present on machine
  Normal  Created    6m    kubelet, linuxea.node-2.com  Created container
  Normal  Started    6m    kubelet, linuxea.node-2.com  Started container

但是我们知道,node2肯定是不符合硬性条件的。但是仅仅尽量满足而已。如果此时在其他节点打上一个符合的标签,如果使用preferred仍然会调度到符合条件的节点上。如果使用required则只会调度到符合的节点,而不会尽量满足调用,而是硬性满足,没有则pending。这就是两种节点亲和,前者硬性亲和,后者软亲和。

相关文章

LeaferJS 1.0 重磅发布:强悍的前端 Canvas 渲染引擎
10分钟搞定支持通配符的永久有效免费HTTPS证书
300 多个 Microsoft Excel 快捷方式
一步步配置基于kubeadmin的kubevip高可用
istio全链路传递cookie和header灰度
REST Web 服务版本控制

发布评论