22. 资源的调度——污点与容忍
本章讲解知识点
- 前言
- Taints 和 Tolerations 概念
- 实验
- 污点的常用场景
<br>
1. 前言
假如我们有一种场景,我们希望某些节点是专用节点,比如 Kubernetes master 节点,就不希望业务应用 Pod 调度过来。或者防止一些非关键的 Pod 占用一些特殊的节点资源,如大页内存。这个时候我们就希望这些节点有一些“污点”,这样专用 Pod 能容忍这些污点,就可以实现调度,不能容忍的,不让其调度过来。为了实现这一场景,Kubernetes 涉及到污点与容忍(Taints 和 Tolerations)。
<br>
2. Taints 和 Tolerations 概念
NodeAffinity 是一种属性,用于让 Pod 被调度到特定的 Node 上,Taint 反过来则表示让 Node 拒绝 Pod 运行。一般情况下,标记为 Taint 的节点可能存在问题,如资源紧缺、安全漏洞等,因此不希望 Pod 被调度到这些节点上。但是有些情况下仍需要将 Pod 调度到 Taint 节点上,这时可以使用 Toleration 属性。需要注意的是,Taint 标记的节点仍然是有效的工作节点。
在默认情况下,在 Node 上设置一个或多个 Taint 之后,除非 Pod 明确声明能够容忍这些污点,否则无法在这些 Pod 上运行。可以用命令来设置 Node 的 Taint 信息:
kubectl taint node node1 key=value:NoSchedule
这个设置为 node1 加上了一个 Taint。该 Taint 的键为 key,值为 value,Taint 的效果是 NoSchedule。这意味着除非 Pod 明确声明可以容忍这个 Taint,否则不会被调度到 node1 上。除了 NoSchedule,还有 PreferNoSchedule 或 NoExecute,分别表示尽量不可调度和不可容忍(即立马将 Pod 驱逐)。
如果 Pod 需要调度到该带污点的节点,就需要加入 Toleration 的设置。举例如下:
tolerations: - key: "key" operator: Equal value: "value" effect: NoSchedule
或
tolerations: - key: "key" operator: Exists effect: NoSchedule
Pod 的 Toleration 声明中的 key 和 effect 需要与 Taint 的设置保持一致,并且满足:
- operator 的值是 Exists 时,无需指定 value
- operator 的值是 Equal 时并且 value 相等。
有两个特例:
- 空的 key 配合 Exists 操作符能够匹配所有键和值
- 空的 effect 匹配所有 effect
<br>
3. 实验
3.1 简单示例
比如我们之前的 my-first-deploy.yaml 中,就设置了 Toleration,以便于创建出来的 Pod 可以调度到 master 节点上,如果没有这个 Toleration,业务 Pod 一般是不允许调度到 master 上的:
apiVersion: apps/v1 kind: Deployment ... spec: containers: - name: my-first-container image: nginx:latest imagePullPolicy: IfNotPresent ports: - containerPort: 80 tolerations: - key: CriticalAddonsOnly operator: Exists - effect: NoSchedule key: node-role.kubernetes.io/master
我们再看看 master 节点的污点:
[root@master mtuser]# kubectl describe node master | grep -i taint Taints: node-role.kubernetes.io/master:NoSchedule
可以看到,master 节点打上的污点,key=node-role.kubernetes.io/master
,effect 是 NoSchedule,即不带 Toleration 的业务 Pod 不允许调度到 master 节点上。
NoSchedule、PreferNoSchedule 和 NoExecute 是 Taints 和 Tolerations 机制中用于描述节点污点和 Pod 容忍度效果的三种效果(Effect)类型。
具体来说,它们的含义如下:
- NoSchedule:表示该污点节点上不允许调度新的 Pod,已经运行在该节点上的 Pod 不受影响。
- PreferNoSchedule:表示调度程序尽可能地避免将新的 Pod 调度到该污点节点上,但可以容忍一定程度的 Pod 在该节点上运行。已经运行在该节点上的 Pod 不受影响。
- NoExecute:表示该污点节点上不允许运行新的 Pod,并且已经运行在该节点上的 Pod 将被立即终止并删除。
我们来做个实验,来验证一下上面的不同的 effect 效果:
我们重新定义 my-first-deploy.yaml,去掉 Toleration 定义,并且指定 Pod 调度到 master 节点上:
apiVersion: apps/v1 kind: Deployment metadata: name: my-first-deploy spec: replicas: 1 selector: matchLabels: app: my-first-deploy template: metadata: labels: app: my-first-deploy spec: containers: - name: my-first-container image: nginx:latest imagePullPolicy: IfNotPresent ports: - containerPort: 80 nodeSelector: app: my-first-deploy
这里我们指定了创建出来的 Pod 调度到带标签 app=my-first-deploy
的节点,我们创建应用:
[root@master mtuser]# kubectl create -f my-first-deploy.yaml deployment.apps/my-first-deploy created [root@master mtuser]# [root@master mtuser]# kubectl get pod NAME READY STATUS RESTARTS AGE my-first-deploy-97497d6db-slk8s 0/1 Pending 0 5s [root@master mtuser]# [root@master mtuser]# kubectl get node -l app=my-first-deploy No resources found.
我们发现 Pod 处于 Pending 状态,这是因为没有节点带有标签 app=my-first-deploy
。好,这时我们给 master 节点打上标签 app=my-first-deploy
。
[root@master mtuser]# kubectl label node master app=my-first-deploy node/master labeled [root@master mtuser]# kubectl get pod NAME READY STATUS RESTARTS AGE my-first-deploy-97497d6db-slk8s 0/1 Pending 0 101s [root@master mtuser]# [root@master mtuser]# kubectl get node -l app=my-first-deploy NAME STATUS ROLES AGE VERSION master Ready master 6d1h v1.15.5
我们打完标签后,发现 Pod 依然没有调度过去,这说明污点的优先级高于 nodeSelector 的。
然后我们去掉 master 的污点 kubectl taint node master node-role.kubernetes.io/master-
,key-
就代表去除:
[root@master mtuser]# kubectl describe node master | grep -i taint Taints: node-role.kubernetes.io/master:NoSchedule [root@master mtuser]# [root@master mtuser]# kubectl taint node master node-role.kubernetes.io/master- node/master untainted [root@master mtuser]# kubectl describe node master | grep -i taint Taints: <none> [root@master mtuser]# [root@master mtuser]# kubectl get pod -owide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES my-first-deploy-97497d6db-slk8s 1/1 Running 0 5m5s 10.244.0.23 master <none> <none>
这时我们就发现 Pod 成功调度到 master 节点了
然后这时,我们又重新打回去污点:
[root@master mtuser]# kubectl taint node master node-role.kubernetes.io/master=:NoSchedule node/master tainted [root@master mtuser]# kubectl get pod -owide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES my-first-deploy-97497d6db-slk8s 1/1 Running 0 8m35s 10.244.0.23 master <none> <none>
我们发现即使打上去了新的污点,但是 NoSchedule 只是影响需要调度过来的 Pod,但是已经成功调度的 Pod 并不会有影响。我们扩容一个 Pod 来验证一下:
[root@master
剩余60%内容,订阅专栏后可继续查看/也可单篇购买
本专刊适合于立志转行云计算的小白,有一定的编程、操作系统、计算机网络、数据结构、算法基础。 本专刊同时也适合于面向云计算(Docker + Kubernetes)求职的从业者。 本专刊囊括了云计算、VMWare、Docker、Kubernetes、Containerd等一系列知识点的讲解,并且最后总