1. 引言

在管理 Kubernetes 集群时,理解 Pod 的调度机制是至关重要的。Taint(污点) 是实现节点调度控制的关键机制之一。它能“排斥”不符合容忍(Toleration)条件的 Pod,从而实现更精细的调度控制。

本文将介绍如何通过 kubectl 命令设置、查看和移除节点上的 Taint,帮助你更好地掌握 Kubernetes 的节点管理能力。我们会从基础命令讲起,逐步深入到高级查询与自动化脚本的使用。


2. 理解 Kubernetes Taint

Taint 是节点上的一个属性,用于阻止某些 Pod 被调度到该节点上,除非这些 Pod 明确设置了对应的 Toleration。

一个 Taint 通常由三个部分组成:

  • Key(键):用于标识这个 Taint 的名称。
  • Value(值):可选,用于进一步描述该 Taint。
  • Effect(效果):定义了调度器在遇到未容忍的 Pod 时应采取的行为。

Effect 的三种类型:

Effect 含义说明
NoSchedule 不允许调度新 Pod 到该节点(已有 Pod 不受影响)
PreferNoSchedule 尽量避免调度新 Pod 到该节点,但不强制
NoExecute 不仅不允许新 Pod 调度,还会驱逐已经在该节点上运行但未容忍的 Pod

✅ 示例:设置 Taint

$ kubectl taint nodes node1 app=blue:NoSchedule
node/node1 tainted

上述命令为节点 node1 添加了一个 Taint,表示只有设置了对应 Toleration 的 Pod 才能被调度到该节点。


3. Taint 的典型应用场景

3.1. 专用节点调度

在某些场景中,我们希望某些节点仅用于特定用途,比如 GPU 计算、数据库服务等。通过 Taint 可以有效隔离这些节点:

$ kubectl taint nodes node-gpu gpu=exclusive:NoSchedule

这样,只有设置了 gpu=exclusive Toleration 的 Pod 才能调度到 node-gpu 节点。

3.2. 节点维护与升级

在节点维护期间,我们可以通过 Taint 控制节点的可用性:

  • **使用 NoSchedule**:防止新 Pod 调度进来,已有 Pod 保持运行。
  • **使用 NoExecute**:驱逐已有未容忍 Pod,彻底清空节点。
# 维护期间防止新 Pod 调度
$ kubectl taint nodes node1 maintenance:NoSchedule

# 硬件更换时驱逐所有 Pod
$ kubectl taint nodes node1 hardware:NoExecute

3.3. 紧急隔离节点

当节点发生安全事件或严重故障时,快速隔离节点可以防止影响扩散:

$ kubectl taint nodes node1 emergency:NoExecute

这样可以立即驱逐未容忍的 Pod,防止故障扩散。


4. 使用 kubectl 查看节点 Taint

4.1. 基础查看命令

使用 kubectl describe nodes 可以快速查看节点的 Taint 信息:

$ kubectl describe nodes node1
...
Taints: app=blue:NoSchedule
...

⚠️ 注意:该命令输出信息较多,适合临时查看,不适合自动化处理。


5. 高级 kubectl 查询技巧

5.1. JSON + JSONPath 查询

适合脚本处理,提取节点和 Taint 信息:

$ kubectl get nodes -o jsonpath="{range .items[*]}{.metadata.name}:{' '}{range .spec.taints[*]}{.key}={.value}:{.effect},{' '}{end}{'\n'}{end}"

输出示例:

node1: app=blue:NoSchedule,
node2: gpu=exclusive:NoSchedule,
node3:

5.2. 使用 jq 格式化输出

$ kubectl get nodes -o=json | jq -r '.items[] | .metadata.name + "\t" + (if .spec.taints then (.spec.taints | map(.key + "=" + (.value // "") + ":" + .effect) | join(", ")) else "No taints" end)'

输出示例:

node1   app=blue:NoSchedule, gpu=exclusive:PreferNoSchedule
node2   No taints
node3   storage=high:NoExecute

5.3. 查看所有节点的 Taint 键

$ kubectl get nodes -o=jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.spec.taints[*].key}{"\n"}{end}'

输出示例:

node1    app
node2    gpu
node3

5.4. 按特定 Taint 过滤节点

$ kubectl get nodes -o go-template='{{range $item := .items}}{{with $nodename := $item.metadata.name}}{{range $taint := $item.spec.taints}}{{if and (eq $taint.key "node-role.kubernetes.io/master") (eq $taint.effect "NoSchedule")}}{{printf "%s\n" $nodename}}{{end}}{{end}}{{end}}{{end}}'

输出示例:

master-node

5.5. 自定义列输出(适合审计)

$ kubectl get nodes -o custom-columns=NAME:.metadata.name,ARCH:.status.nodeInfo.architecture,KERNEL:.status.nodeInfo.kernelVersion,TAINTS:.spec.taints

输出示例:

NAME        ARCH       KERNEL         TAINTS
node1       amd64      4.19.0-6-amd64 [{"key":"app","value":"blue","effect":"NoSchedule"}]
node2       amd64      4.19.0-6-amd64 [{"key":"gpu","value":"exclusive","effect":"NoSchedule"}]
node3       amd64      4.19.0-6-amd64 []

5.6. 使用 Go 模板自定义输出

$ kubectl get nodes -o go-template='{{range .items}}{{.metadata.name}}{{"\t"}}{{range .spec.taints}}{{.key}}={{.value}}:{{.effect}}{{"\t"}}{{end}}{{"\n"}}{{end}}'

输出示例:

master-11   node-role.kubernetes.io/master=NoSchedule
master-12   node-role.kubernetes.io/master=NoSchedule
master-13   node-role.kubernetes.io/master=NoSchedule

6. 多租户集群中的 Taint 平衡

在多租户 Kubernetes 集群中,使用 Taint 可以实现租户间的资源隔离:

$ kubectl get nodes -o custom-columns='NAME:.metadata.name,TAINTS:.spec.taints,ALLOCATABLE_CPU:.status.allocatable.cpu,ALLOCATABLE_MEM:.status.allocatable.memory'

输出示例:

NAME        TAINTS                                            ALLOCATABLE_CPU   ALLOCATABLE_MEM
node1       [{"key":"tenantA","effect":"NoSchedule"}]         8                 32Gi
node2       [{"key":"tenantB","effect":"NoSchedule"}]         16                64Gi
node3       []                                                4                 16Gi

通过这种方式,我们可以清晰地看到每个节点的资源分配与隔离策略,便于进行资源调度和审计。


7. 自动化调整 Taint

以下是一个 Bash 脚本示例,根据节点 CPU 使用率自动添加或移除 Taint:

#!/bin/bash

NODE_NAME="node1"

CPU_USAGE=$(kubectl top node $NODE_NAME --no-headers | awk '{print $2}' | sed 's/%//')

if [ $CPU_USAGE -gt 90 ]; then
    kubectl taint nodes $NODE_NAME high_cpu_usage:NoSchedule --overwrite
else
    kubectl taint nodes $NODE_NAME high_cpu_usage:NoSchedule-
fi

✅ 使用方式:

chmod +x taint-nodes.sh
./taint-nodes.sh

✅ 自动执行(通过 cron):

*/5 * * * * /home/user/taint-nodes.sh >> /var/log/taint-nodes.log 2>&1

8. 移除 Taint

要移除一个节点上的 Taint,使用 - 表示删除:

# 移除带 Effect 的 Taint
$ kubectl taint nodes node1 key1=value1:NoSchedule-

# 仅移除 Key(忽略 Value 和 Effect)
$ kubectl taint nodes node1 key1-

⚠️ 注意:移除 Taint 后,未设置 Toleration 的 Pod 也可以被调度到该节点。


9. 总结

本文介绍了 Kubernetes 中 Taint 的设置、查看与移除方法,并通过多个 kubectl 命令演示了从基础到高级的使用技巧。掌握这些内容,可以帮助你在生产环境中更好地控制 Pod 的调度行为,实现资源隔离、节点维护和自动化管理。

关键点回顾:

  • Taint 是节点调度控制的重要机制
  • Effect 有三种类型:NoSchedulePreferNoScheduleNoExecute
  • 可通过 kubectl taint 设置和移除 Taint
  • 使用 kubectl describejsonpathjqgo-template 等方式灵活查看 Taint
  • 可结合脚本实现自动化调度控制

掌握这些技能,能显著提升你在 Kubernetes 集群管理中的效率与灵活性。


原始标题:How to Set, List, and Remove Taints on Kubernetes Nodes