如何让node 去”选择”只有谁(pod)能部署到自身上面?看了下现有的Node SelectorsNode AffinityNode Taints, 经过比对,发现Node Taints 更适合这种情况,下面是分享一下具体的内容.

需求

前几天新建了几个namespace,其中包括有test环境,现在有个需求就是想要给这个test 命名空间加入一台专有主机。并且其它的pod调度不能被指派到上面去。使这个pod成为专属主机,只允许有特殊标志的pod被调度到上面去。

分析及确定方案

第一个想到的就是node selectors,先给node 设置label,然后让pod 去根据label选择要部署到哪台主机上. 给node 设置label:

kubectl label nodes node_name work_env=test

创建pod时, 在spec段落里,指定nodeselector的值,如下:

spec:
  containers: 
  - name: ...
    image: ...
  nodeSelector:
    work_env: test

这样虽然保证了pod一定会被调度到这个带有work_env=test label的主机上, 但是其它没有加label的pod也有可能被调度到该节点去。并且官方表示 node-selectors 在未来可能会被 node affinity 替代。

第二个就是 affinity,affinity 这块包含有node 的affinity,以及Inter-pod affinity,这俩对应的都有 anti-affinity,这些相比node selectors来说,更加的灵活,方便。前者是根据node 上的label 指定调度策略,后者是根据node 上已有pod的label 来指定调度策略。

当前有2种node affinity:

其中两者的区别在于一个是强制要求,一个是非强制的软要求。就像node selector 一样根据条件去调度. 但不同的是,判断的语法表达式很丰富。目前支持的操作有:In, NotIn, Exists, DoesNotExist, Gt, Lt. 看到官方介绍说,未来可能会增加新的选项:requiredDuringSchedulingRequiredDuringExecution,这个功能是当你的pod 在运行时,Node上的label发生了改变,将会驱逐该节点上与现有label不匹配的pod.

Note:目前affinity 还属于beta,但是已经可以使用.

以上两种看似都是根据pod 来选择node,那样的话,要在所有要部署的资源上指定相关的label调度策略。这样我觉得又有点稍微麻烦了。然后就发现还有一种方式可以满足,让node去选择pod。

第三个是 Taints and Tolerations, 通俗的来说,对应node是 污染(taints),对应pod是能容忍的(tolerations), 就像情侣一样,虽然他有缺点,但你能容忍,这样这两人就幸福的在一起生活了。😂

官方介绍:

Taints and tolerations are a flexible way to steer pods away from nodes or evict pods that shouldn’t be running. 并且官方给了几个适用的案例:

另外官方还说了从 kubernetes 1.6 版本引入了自动taint Node 的功能,这时所有不指定Tolerations的pod,即默认的pod将不会被调度到该Node上,以下是内置的:

下面我们就来看看第三种是如何设置的。

验证

第一步:我们要给不同作用的Node 设置不同label,这样方便后期管理。这也是做这些事情的前提。这里我们用了 taint 和 tolerations,下面是给主机设置taint:

kubectl taint node i-i3i8c9y9 dedicated=test:NoSchedule

其中 NoSchedule 意味着,如果没有符合dedicated=test 的污点的容忍,那么所有的pod都不会被调度到该Node 上面。

第二步:我们编辑test-taint-pod.yaml,在pod 的PodSpec 中指定tolerations,如下:

spec:
  containers:
  - name: test-taint
    image: ubuntu:latest
    command: ["sleep"]
    args: ["300"]
  tolerations:
    - key: "dedicated"
      operator: "Equal"
      value: "test"
      effect: "NoSchedule"

另外operator 也可以指定为 Exists ,如果使用了 Existsvalue 那行可以去掉。还有,如果operator 不指定的话,默认是Equal

第三步:创建测试pod

kubectl create -f test-taint-pod.yaml

# 然后检查一下
kubectl get po -o wide

通过检查,我们可以发现,设置了Toleration 的 pod总是被调到对应有taint 的Node上。

Tips: 这里是如何移除Node 上的taint操作

kubectl taint nodes i-i3i8c9y9 key:NoSchedule-

总结

回顾一下,有三种方式可以设置node 和pod 的调度关系。

参考

官方介绍Taints使用案例

Taints label

驱逐策略

Understanding and using the Kubernetes PodNodeSelector Admission Controller

operator-best-practices-advanced-scheduler