主题
192.168.122.31 集群 Master 打污点 / Worker 恢复普通副本调度手册
- 日期:2026-08-01
- 目标集群:API Server
192.168.122.31(Rancher/RKE 系集群) - 目标:
- 给所有 master(control-plane)节点打污点,普通业务副本(Pod)不再调度到 master;
- 移除 worker 节点上驱逐/排斥普通副本的污点,普通副本只落在 worker 上。
1. 背景与原理
- 污点(Taint)与容忍(Toleration):节点打了
NoSchedule污点后,只有带对应 toleration 的 Pod 才能调度上来;NoExecute污点会同时驱逐已运行的不容忍 Pod。 - master 节点默认应只跑系统组件(apiserver、etcd、controller-manager 等,这些组件自带 toleration),普通副本不应占用 master 资源。
- 若 worker 之前被打过污点(如维护时打的
node.kubernetes.io/unschedulable、自定义dedicated等),需要移除,否则普通副本无处可去。
2. 前置条件
bash
# 在有 kubectl 的机器上配置好该集群的 kubeconfig
export KUBECONFIG=~/.kube/192.168.122.31.yaml
kubectl get nodes -o wide确认能列出节点后再继续。
3. 查看现状
bash
# 查看所有节点角色
kubectl get nodes -o wide --show-labels | grep -E 'control-plane|master|worker'
# 查看所有节点现有污点(重点!)
kubectl get nodes -o json | \
jq -r '.items[] | "\(.metadata.name)\t\( [.spec.taints[]? | "\(.key)=\(.value // ""):\(.effect)"] | join(", ") )"'记录输出,后面操作完逐项对比。
4. Master 节点打污点
对每个 master 节点执行:
bash
MASTER_NODES=$(kubectl get nodes -l node-role.kubernetes.io/control-plane=true -o name)
# 老版本集群标签可能是 node-role.kubernetes.io/master=true,按实际调整
for n in $MASTER_NODES; do
kubectl taint nodes $n node-role.kubernetes.io/control-plane=true:NoSchedule --overwrite
done说明:
- 用
NoSchedule而不是NoExecute:只阻止新副本调度上来,不会立即驱逐 master 上已运行的普通 Pod,避免业务闪断。- 如需把 master 上已存在的普通副本赶走,见第 6 节。
--overwrite避免 key 已存在时报错。
5. 移除 Worker 节点的驱逐污点
5.1 移除指定污点(推荐,精准)
根据第 3 节查到的 worker 污点逐个移除,污点 key 后加 - 表示删除:
bash
# 示例:去掉维护期打的污点
kubectl taint nodes <worker-name> dedicated-
# 示例:去掉不可调度污点
kubectl taint nodes <worker-name> node.kubernetes.io/unschedulable-去掉污点时可带 effect 精确匹配,如 dedicated=true:NoSchedule-;不带 effect 则删除该 key 的所有 effect。
5.2 批量移除 worker 上所有自定义污点(谨慎)
bash
for n in $(kubectl get nodes -l '!node-role.kubernetes.io/control-plane' -o name); do
echo "== $n =="
kubectl get $n -o jsonpath='{.spec.taints}' ; echo
done
# 确认无误后再执行删除,切勿误删 longhorn/存储类专用污点注意:如果 worker 上有故意保留的污点(如存储节点专用
storage=true:NoSchedule),不要删,只删驱逐普通副本的那条。
6. (可选)驱逐 master 上已存在的普通副本
NoSchedule 不影响存量 Pod。若要把 master 上已运行的普通副本迁走:
bash
# 方式一:温和重启,由 Deployment 控制器把副本重新调度到 worker
kubectl get pods -A -o wide --field-selector spec.nodeName=<master-name> | grep -v -E 'kube-system|cattle-system'
# 对查出的普通业务 Pod 逐个 delete(确保是多副本!)
kubectl -n <ns> delete pod <pod-name>
# 方式二:临时加 NoExecute 污点强制驱逐,完成后改回 NoSchedule
kubectl taint nodes <master-name> node-role.kubernetes.io/control-plane=true:NoExecute --overwrite
# 确认普通副本全部迁走后:
kubectl taint nodes <master-name> node-role.kubernetes.io/control-plane=true:NoSchedule --overwriteDaemonSet 类型的系统组件一般自带 toleration,不受影响,无需处理。
7. 验证
bash
# ① 污点终态检查:master 有 NoSchedule 污点,worker 无驱逐污点
kubectl get nodes -o json | \
jq -r '.items[] | "\(.metadata.name)\t\( [.spec.taints[]? | "\(.key)=\(.value // ""):\(.effect)"] | join(", ") )"'
# ② 调度测试:起一个 3 副本测试 Deployment,应全部落在 worker
kubectl create deploy taint-test --image=nginx --replicas=3
kubectl get pods -o wide -l app=taint-test
# ③ 清理
kubectl delete deploy taint-test8. 回滚
bash
# 撤销 master 污点
kubectl taint nodes <master-name> node-role.kubernetes.io/control-plane:NoSchedule-
# 恢复 worker 污点(按需补回)
kubectl taint nodes <worker-name> <key>=<value>:<effect>