kubernetes高级资源之污点和容忍
一、介绍
# Kubernetes 高级资源:污点(Taints)和容忍(Tolerations)
## 污点(Taints)的作用
污点是节点(Node)的一个属性,它允许节点排斥一组特定的Pod。主要作用包括:
1. **节点专用**:确保某些节点只运行特定类型的Pod
- 例如:保留带有GPU的节点只运行机器学习工作负载
2. **节点隔离**:
- 维护节点时,可以给节点添加污点以防止新Pod被调度到该节点
- 隔离问题节点,防止Pod被调度到不健康的节点上
3. **特殊硬件保留**:
- 为具有特殊硬件(如SSD、GPU)的节点添加污点
- 只有声明了相应容忍的Pod才能使用这些特殊资源
4. **多租户隔离**:
- 在不同团队或项目间划分集群资源
## 容忍(Tolerations)的作用
容忍是Pod的一个属性,它允许(但不强制要求)Pod被调度到带有匹配污点的节点上。主要作用包括:
1. **访问专用节点**:
- 允许特定Pod调度到带有污点的专用节点上
- 例如:只有机器学习工作负载能使用GPU节点
2. **应对节点维护**:
- 关键Pod可以容忍"NoSchedule"污点,确保在节点维护期间仍能运行
3. **处理节点问题**:
- 关键系统Pod可以容忍"NoExecute"污点,即使节点出现问题也不被驱逐
4. **多租户资源共享**:
- 允许高优先级工作负载使用为其他团队保留的资源
## 污点效果类型
1. **NoSchedule**:
- 不会调度不容忍此污点的Pod到该节点
- 已运行的Pod不受影响
2. **PreferNoSchedule**:
- 尽量不调度不容忍此污点的Pod到该节点
- 如果没有其他可用节点,仍可能调度
3. **NoExecute**:
- 不会调度不容忍此污点的Pod到该节点
- 已运行但不容忍此污点的Pod会被驱逐
## 使用示例
为节点添加污点:
```bash
kubectl taint nodes node1 key=value:NoSchedule
```
Pod中的容忍配置:
```yaml
tolerations:
- key: "key"
operator: "Equal"
value: "value"
effect: "NoSchedule"
```
污点和容忍机制共同工作,为Kubernetes集群提供了精细的Pod调度控制能力,是生产环境中实现资源隔离和优先级调度的重要工具。
二、实战部署
[root@master ~]# kubectl taint node node1 cjr=yyj:NoSchedule
node/node1 tainted
[root@master ~]# kubectl get node
NAME STATUS ROLES AGE VERSION
master Ready control-plane 120m v1.31.3
node1 Ready <none> 119m v1.31.3
node2 Ready <none> 119m v1.31.3
[root@master ~]# kubectl describe node node1 | grep Taint
Taints: cjr=yyj:NoSchedule
[root@master ~]# kubectl apply -f tomcat.tar.gz
error: error parsing tomcat.tar.gz: invalid Yaml document separator: %s ping statistics ---
[root@master ~]# kubectl apply -f pod-taint.yaml
pod/taint-pod created
[root@master ~]# kubectl get pod -owide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
myapp3 1/1 Running 0 40m 10.244.166.145 node1 <none> <none>
myapp4 1/1 Running 0 40m 10.244.166.146 node1 <none> <none>
taint-pod 1/1 Running 0 4s 10.244.104.9 node2 <none> <none>
[root@master ~]# cat pod-taint.yaml
apiVersion: v1
kind: Pod
metadata:
name: taint-pod
namespace: default
labels:
tomcat: tomcat-pod
spec:
containers:
- name: taint-pod
ports:
- containerPort: 8080
image: tomcat:8.5-jre8-alpine
imagePullPolicy: IfNotPresent
[root@master ~]# kubectl taint node node2 c=y:NoExecute
node/node2 tainted
[root@master ~]# kubectl get pod -owide -w
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
myapp3 1/1 Running 0 41m 10.244.166.145 node1 <none> <none>
myapp4 1/1 Running 0 41m 10.244.166.146 node1 <none> <none>
taint-pod 1/1 Running 0 6s 10.244.104.10 node2 <none> <none>
taint-pod 1/1 Running 0 102s 10.244.104.10 node2 <none> <none>
taint-pod 1/1 Terminating 0 102s 10.244.104.10 node2 <none> <none>
taint-pod 1/1 Terminating 0 102s 10.244.104.10 node2 <none> <none>
taint-pod 1/1 Terminating 0 102s 10.244.104.10 node2 <none> <none>
taint-pod 0/1 Error 0 102s 10.244.104.10 node2 <none> <none>
taint-pod 0/1 Error 0 103s 10.244.104.10 node2 <none> <none>
taint-pod 0/1 Error 0 103s 10.244.104.10 node2 <none> <none>
[root@node1 ~]# kubectl describe node node1 | grep Taints
Taints: cjr=yyj:NoSchedule
[root@node1 ~]# kubectl describe node node2 | grep Taints
Taints: cjr=yyj:NoExecute
[root@master ~]# vi pod-taint.yaml
apiVersion: v1
kind: Pod
metadata:
name: taint-pod
namespace: default
labels:
tomcat: tomcat-pod
spec:
containers:
- name: taint-pod
ports:
- containerPort: 8080
image: tomcat:8.5-jre8-alpine
imagePullPolicy: IfNotPresent
tolerations:
- effect: NoSchedule
key:
value:
operator: Exists
[root@master ~]# kubectl get pod -owide -w
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
myapp3 1/1 Running 0 61m 10.244.166.145 node1 <none> <none>
myapp4 1/1 Running 0 61m 10.244.166.146 node1 <none> <none>
taint-pod 1/1 Running 0 10s 10.244.166.150 node1 <none> <none>
[root@master ~]# vi pod-taint.yaml
apiVersion: v1
kind: Pod
metadata:
name: taint-pod
namespace: default
labels:
tomcat: tomcat-pod
spec:
containers:
- name: taint-pod
ports:
- containerPort: 8080
image: tomcat:8.5-jre8-alpine
imagePullPolicy: IfNotPresent
tolerations:
- effect: NoExecute
key: cjr
value: yyj
operator: Equal
root@master ~]# kubectl get pod -owide -w
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
myapp3 1/1 Running 0 62m 10.244.166.145 node1 <none> <none>
myapp4 1/1 Running 0 62m 10.244.166.146 node1 <none> <none>
taint-pod 1/1 Running 0 12s 10.244.104.12 node2 <none> <none>
三、总结
# Kubernetes污点(Taints)和容忍(Tolerations)实验总结
## 实验过程回顾
1. **初始节点状态**:
- 集群有3个节点:master(control-plane)、node1和node2
- 初始状态下节点没有污点
2. **添加污点**:
- 给node1添加`NoSchedule`污点:`cjr=yyj:NoSchedule`
- 给node2添加`NoExecute`污点:`c=y:NoExecute`
3. **Pod调度行为观察**:
- 未配置容忍的Pod无法调度到node1(NoSchedule效果)
- 已运行在node2的Pod被立即驱逐(NoExecute效果)
4. **添加容忍测试**:
- 首先添加通用容忍(`operator: Exists`),Pod可调度到node1
- 然后添加精确匹配的容忍(`key: cjr, value: yyj, operator: Equal`),Pod可调度到node2
## 关键结论
1. **污点效果差异**:
- `NoSchedule`:只影响新Pod调度,不影响已运行Pod
- `NoExecute`:既影响新Pod调度,也会驱逐已运行的不容忍Pod
2. **容忍配置方式**:
- **宽松容忍**:使用`operator: Exists`可容忍任意污点(不指定key/value)
- **精确匹配**:使用`operator: Equal`并指定key/value可针对特定污点
3. **调度优先级**:
- 当Pod同时满足节点选择条件和容忍条件时才会被调度
- 容忍只是"允许"而非"强制"调度到污点节点
4. **生产环境建议**:
- 对关键系统组件(如DaemonSet)配置适当的容忍
- 谨慎使用`NoExecute`,可能导致服务中断
- 为专用节点设计清晰的污点命名规范
## 示例配置解析
```yaml
# 精确匹配容忍配置示例
tolerations:
- key: "cjr"
operator: "Equal"
value: "yyj"
effect: "NoExecute"
# 宽松容忍配置示例
tolerations:
- operator: "Exists"
effect: "NoSchedule"
```
通过本次实验,清晰演示了污点和容忍如何协同工作控制Pod调度,这是Kubernetes高级调度策略的重要组成部分。