如何让node 去”选择”只有谁(pod)能部署到自身上面?看了下现有的Node Selectors
、Node Affinity
、Node 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:
- requiredDuringSchedulingIgnoredDuringExecution
- preferredDuringSchedulingIgnoredDuringExecution
其中两者的区别在于一个是强制要求,一个是非强制的软要求。就像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. 并且官方给了几个适用的案例:
- 专用Node
- 具有特殊硬件配置的Node
- 基于taint对pod进行驱逐
另外官方还说了从 kubernetes 1.6 版本引入了自动taint Node 的功能,这时所有不指定Tolerations的pod,即默认的pod将不会被调度到该Node上,以下是内置的:
- node.kubernetes.io/not-ready: 节点尚未就绪
- node.kubernetes.io/unreachable: 节点不可达,和master活着api控制器失去通信,或其它问题导致无法连接
- node.kubernetes.io/out-of-disk: 磁盘不足
- node.kubernetes.io/memory-pressure: 内存有压力 < 100Mi
- node.kubernetes.io/disk-pressure: 磁盘有压力 < 10%
- node.kubernetes.io/network-unavailable: 节点的网络不可用
- node.kubernetes.io/unschedulable: 节点不可调度
- node.cloudprovider.kubernetes.io/uninitialized: 当使用“外部”云提供程序启动kubelet时,会在节点上设置此taint以将其标记为不可用
下面我们就来看看第三种是如何设置的。
验证
第一步:我们要给不同作用的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 ,如果使用了 Exists ,value
那行可以去掉。还有,如果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 的调度关系。
- Node Selectors: 符合Pod指定带有label的主机,将会被调度。但无法避免其它Pod在上面。将优先分配给定义了匹配Node selectors的pod。
- Affinty: Node 亲和性,有Node selectors 的所有功能,语法更灵活。但一样,也无法避免其它Pod。
- Taint & Toleration: 只有设置了 Toleration 的主机才可以被调度到上面去。主要用途是设置为专用主机,或其它专有用途的主机。
参考
Understanding and using the Kubernetes PodNodeSelector Admission Controller