K8s之Node亲和性调度

前言

前面介绍了定向调度,虽然很方便,但是也存在一些问题,不够灵活并且是硬限制,如果Node节点不存在,那么该Pod就运行不了,所以使用场景还是有所限制。

针对于上面问题,k8s就给我们提供了亲和性调度,它在NodeSelector上做了一些扩展,可以通过配置优先选择符合条件的Node节点,如果没有也可以调度到其它Node节点上,取代了定向调度的硬限制。随着亲和性调度越来越能够体现NodeSelector的功能,最终NodeSelector应该会被废弃

亲和性调度有两种分别是 节点亲和性 与 Pod亲和性。本文主要介绍节点亲和性,Pod亲和性后面更新

NodeAffinity

NodeAffinity表示Node亲和性调度,用于替换NodeSelector的全新调度策略

目前nodeAffinity有两种配置项

requiredDuringSchedulingIgnoredDuringExecution

必须满足指定的规则才能将Pod调度到节点,属于硬限制,调度完成之后就不再检查条件是否满足,与NodeSelector非常像只是语法不同,所以说NodeAffinity可以替代NodeSelector

通过 kubectl explain pods.spec.affinity.nodeAffinity.requiredDuringSchedulingIgnoredDuringExecution 可以查看配置项,具体如下

requiredDuringSchedulingIgnoredDuringExecution
  nodeSelectorTerms  #<[]Object> -required- 节点选择列表
  - matchFields   # <[]Object> 按节点字段列出的节点选择器要求列表  
  - matchExpressions   #<[]Object> 按节点标签列出的节点选择器要求列表(推荐)
    - key    # 标签名
      operator # 操作符 包括 In、NotIn、Exists、DoesNotExist、Gt、Lt
      values # 标签值

操作符代表的含义如下

In # label的值必须在某个节点列表中
NotIn # 与In相反
Exists # 某个label存在
DoesNotExist # 某个label不存在
Gt # label的值大于某个值
Lt # label的值小于某个值

后面讲的Pod亲和性具有互斥功能,Node亲和性虽然语法上没有互斥功能,但是通过 NotIn和DoesNotExist可以实现节点互斥的功能

通过kubectl label命令给node01打上北京机房的标签,给node02打上上海机房的标签

kubectl label nodes node01 area=bj
kubectl label nodes node02 area=shanghai

# 查看标签是否设置成功
kubectl get nodes --show-labels

编写 nginx-nodeAffinity-required.yaml 内容如下

apiVersion: v1
kind: Pod
metadata:
  name: nginx-node-affinity-required
spec:
  containers:
  - name: nginx
    image: nginx
    imagePullPolicy: IfNotPresent
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
          - key: area
            operator: In
            values: ['bj','changsha']

启动Pod,由于设置values: ['bj','changsha'],所以只有node01满足要求,观察Pod所在节点

# 启动
[root@master affinity]# kubectl create -f nginx-nodeAffinity-required.yaml
pod/nginx-node-affinity-required created

# 查看Pod详情,落在node01节点
[root@master affinity]# kubectl get pods -o wide
NAME                           READY   STATUS    RESTARTS   AGE   IP            NODE     NOMINATED NODE   READINESS GATES
nginx-node-affinity-required   1/1     Running   0          23s   10.244.1.71   node01   <none>           <none>

修改yaml为values: ['shanghai','changsha'],此时只有node02满足要求,启动Pod观察Pod所在节点

# 删除之前Pod
[root@master affinity]# kubectl delete -f nginx-nodeAffinity-required.yaml 
pod "nginx-node-affinity-required" deleted

# 启动
[root@master affinity]# kubectl create -f nginx-nodeAffinity-required.yaml
pod/nginx-node-affinity-required created

# 查看Pod详情,落在node02节点
[root@master affinity]# kubectl get pods -o wide
NAME                           READY   STATUS    RESTARTS   AGE   IP            NODE     NOMINATED NODE   READINESS GATES
nginx-node-affinity-required   1/1     Running   0          8s    10.244.2.24   node02   <none>           <none>

修改yaml为values: ['hangzhou','changsha'],此时没有节点满足要求,前面提到requiredDuringSchedulingIgnoredDuringExecution属于硬限制,所以Pod应该运行不起来,启动Pod,观察Pod状态

# 删除之前Pod
[root@master affinity]# kubectl delete -f nginx-nodeAffinity-required.yaml 
pod "nginx-node-affinity-required" deleted

# 启动
[root@master affinity]# kubectl create -f nginx-nodeAffinity-required.yaml
pod/nginx-node-affinity-required created

# 查看Pod详情,状态为Pending并没有运行成功
[root@master affinity]# kubectl get pods -o wide
NAME                           READY   STATUS    RESTARTS   AGE   IP       NODE     NOMINATED NODE   READINESS GATES
nginx-node-affinity-required   0/1     Pending   0          14s   <none>   <none>   <none>           <none>

# 查看启动过程事件,抛出异常
[root@master affinity]# kubectl describe  pod nginx-node-affinity-required|grep -A 100 Event
Events:
  Type     Reason            Age   From               Message
  ----     ------            ----  ----               -------
  Warning  FailedScheduling  44s   default-scheduler  0/3 nodes are available: 1 node(s) had taint {node-role.kubernetes.io/master: }, that the pod didn't tolerate, 2 node(s) didn't match Pod's node affinity/selector.
preferredDuringSchedulingIgnoredDuringExecution

优先满足指定规则,调度器会尝试调度Pod到指定Node,如果没有此节点,也不会强制要求,是一个软限制。如果有多个匹配规则,可以设置权重(weight)来定义执行的先后顺序。

通过 kubectl explain pods.spec.affinity.nodeAffinity.requiredDuringSchedulingIgnoredDuringExecution 可以查看配置项,具体如下

preferredDuringSchedulingIgnoredDuringExecution
- weight # 权重,范围1-100。
  preference # 一个节点选择器项,与相应的权重相关联
    matchFields #  <[]Object> 按节点字段列出的节点选择器要求列表
    matchExpressions  # <[]Object> 按节点标签列出的节点选择器要求列表(推荐)
      key # 标签
      operator # 操作符
      values # <[]string> 标签值

编写 nginx-nodeAffinity-preferred.yaml 内容如下,设置两个匹配规则,以权重定义执行顺序

apiVersion: v1
kind: Pod
metadata:
  name: nginx-node-affinity-preferred
spec:
  containers:
  - name: nginx
    image: nginx
    imagePullPolicy: IfNotPresent
  affinity:
    nodeAffinity:
      preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 1
        preference:
          matchExpressions:
          - key: area
            operator: In
            values: ['bj']
      - weight: 2
        preference:
          matchExpressions:
          - key: area
            operator: In
            values: ['shanghai']

启动Pod,由于设置有两个匹配规则,并且shanghai的优先级高于bj,所以应该要落在node02节点,观察Pod所在节点

# 启动
[root@master affinity]# kubectl create -f nginx-nodeAffinity-preferred.yaml
pod/nginx-node-affinity-preferred created

# 查看Pod详情,落在node02节点
[root@master affinity]# kubectl get pods -o wide
NAME                            READY   STATUS    RESTARTS   AGE   IP            NODE     NOMINATED NODE   READINESS GATES
nginx-node-affinity-preferred   1/1     Running   0          12s   10.244.2.25   node02   <none>           <none>

修改yaml将bj的权重设为3,再次启动Pod,观察Pod所在节点

# 删除之前Pod
[root@master affinity]# kubectl delete -f nginx-nodeAffinity-preferred.yaml
pod "nginx-node-affinity-preferred" deleted

# 启动
[root@master affinity]# kubectl create -f nginx-nodeAffinity-preferred.yaml
pod/nginx-node-affinity-preferred created

# 查看Pod详情,落在node01节点
[root@master affinity]# kubectl get pods -o wide
NAME                            READY   STATUS    RESTARTS   AGE   IP            NODE     NOMINATED NODE   READINESS GATES
nginx-node-affinity-preferred   1/1     Running   0          8s    10.244.1.72   node01   <none>           <none>

修改yaml如下,条件均不满足

apiVersion: v1
kind: Pod
metadata:
  name: nginx-node-affinity-preferred
spec:
  containers:
  - name: nginx
    image: nginx
    imagePullPolicy: IfNotPresent
  affinity:
    nodeAffinity:
      preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 1
        preference:
          matchExpressions:
          - key: area
            operator: In
            values: ['changsha']
      - weight: 2
        preference:
          matchExpressions:
          - key: area
            operator: In
            values: ['hangzhou']

启动Pod,上面提到,这种调度为软限制,如果没有找到符合条件的Node会退而求其次,选择一个资源充足的Pod进行调度

# 删除之前Pod
[root@master affinity]# kubectl delete -f nginx-nodeAffinity-preferred.yaml
pod "nginx-node-affinity-preferred" deleted

# 启动
[root@master affinity]# kubectl create -f nginx-nodeAffinity-preferred.yaml
pod/nginx-node-affinity-preferred created

# 调度到了node01几点
[root@master affinity]# kubectl get pods -o wide
NAME                            READY   STATUS    RESTARTS   AGE   IP            NODE     NOMINATED NODE   READINESS GATES
nginx-node-affinity-preferred   1/1     Running   0          4s    10.244.1.74   node01   <none>           <none>

问题

由于nodeSelector还未被废弃,那么同时设置nodeSelector与nodeAffinity,该如何调度

从上面给出的亲和性配置项可以知道nodeSelectorTerms为一个数组类型,可以设置多个matchExpressions,那么有多个matchExpressions该如何匹配

matchExpressions也是一个数组,可以设置多组key-value操作,这又该如何匹配

同时定义nodeSelector与nodeAffinity

编写 affinity-nodeselector.yaml 内容如下

apiVersion: v1
kind: Pod
metadata:
  name: affinity-nodeselector
spec:
  containers:
  - name: nginx
    image: nginx
    imagePullPolicy: IfNotPresent
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
          - key: area
            operator: In
            values: ['bj']
  nodeSelector:
    area: shanghai

启动Pod,由于两者都是硬限制,限制的条件不同应该无法调度。

# 启动Pod
[root@master affinity]# kubectl create -f affinity-nodeselector.yaml 
pod/affinity-nodeselector created

# 查看Pod状态,未启动成功
[root@master affinity]# kubectl get pods
NAME                    READY   STATUS    RESTARTS   AGE
affinity-nodeselector   0/1     Pending   0          9s

# 查看启动事件,看到了似曾相识的报错
[root@master affinity]# kubectl describe pod affinity-nodeselector | grep -A 100 Events
Events:
  Type     Reason            Age   From               Message
  ----     ------            ----  ----               -------
  Warning  FailedScheduling  34s   default-scheduler  0/3 nodes are available: 1 node(s) had taint {node-role.kubernetes.io/master: }, that the pod didn't tolerate, 2 node(s) didn't match Pod's node affinity/selector.

修改nodeSelector,将条件也设置为bj,启动成功

[root@master affinity]# kubectl get pods -o wide
NAME                    READY   STATUS    RESTARTS   AGE   IP            NODE     NOMINATED NODE   READINESS GATES
affinity-nodeselector   1/1     Running   0          7s    10.244.1.75   node01   <none>           <none>
nodeAffinity指定多个matchExpressions如何执行

编写 multiple-nodeselectorterms.yaml 内容如下

apiVersion: v1
kind: Pod
metadata:
  name: multiple-nodeselectorterms
spec:
  containers:
  - name: nginx
    image: nginx
    imagePullPolicy: IfNotPresent
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
          - key: area
            operator: In
            values: ['changsha']
        - matchExpressions:
          - key: area
            operator: In
            values: ['shanghai']

启动Pod,如果可以启动成功并且在node02节点,表示只要满足一个条件即可,如果启动不成功表示都要满足

# 启动
[root@master affinity]# kubectl create -f multiple-nodeselectorterms.yaml                
pod/multiple-nodeselectorterms created

# 观察Pod详情,启动成功,并且Pod落在node02节点
[root@master affinity]# kubectl get pods -o wide
NAME                         READY   STATUS    RESTARTS   AGE   IP            NODE     NOMINATED NODE   READINESS GATES
multiple-nodeselectorterms   1/1     Running   0          19s   10.244.2.26   node02   <none>           <none>
matchExpressions有多个匹配项

编写 multiple-matchexpressions.yaml 内容如下

apiVersion: v1
kind: Pod
metadata:
  name: multiple-matchexpressions
spec:
  containers:
  - name: nginx
    image: nginx
    imagePullPolicy: IfNotPresent
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
          - key: area
            operator: In
            values: ['changsha']
          - key: area
            operator: In
            values: ['shanghai']

启动Pod,如果可以启动成功并且在node02节点,表示只要满足一个条件即可,如果启动不成功表示都要满足

# 启动
[root@master affinity]# kubectl create -f multiple-matchexpressions.yaml
pod/multiple-matchexpressions created

# 观察Pod,启动失败
[root@master affinity]# kubectl get pods -o wide
NAME                        READY   STATUS    RESTARTS   AGE   IP       NODE     NOMINATED NODE   READINESS GATES
multiple-matchexpressions   0/1     Pending   0          11s   <none>   <none>   <none>           <none>

# 查看启动事件,还是熟悉的报错
[root@master affinity]# kubectl describe pod multiple-matchexpressions | grep -A 100 Events                     
Events:
  Type     Reason            Age   From               Message
  ----     ------            ----  ----               -------
  Warning  FailedScheduling  48s   default-scheduler  0/3 nodes are available: 1 node(s) had taint {node-role.kubernetes.io/master: }, that the pod didn't tolerate, 2 node(s) didn't match Pod's node affinity/selector.
总结

如果同时定义了nodeSelector与nodeAffinity,两个条件必须满足,才能调度到指定Pod上

如果有多个 matchExpressions ,那么只要满足一个即可

如果一个matchExpressions 下有多个匹配项,那么需要全部满足

节点亲和性就介绍到这里,后面介绍Pod亲和性调度与互斥调度。


欢迎关注,学习不迷路!

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,793评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,567评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,342评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,825评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,814评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,680评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,033评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,687评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,175评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,668评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,775评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,419评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,020评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,206评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,092评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,510评论 2 343

推荐阅读更多精彩内容