节点是 Kubernetes 集群的计算地基——Pod 可以随时重建,节点一旦失联,其上的工作负载全部受影响。但很多团队把节点当作"跑 Pod 的黑盒子":不设计节点池、不管理污点、维护节点时直接重启,导致调度混乱、故障扩散、排障困难。本指南从节点池设计到生命周期管理再到自动化运维,建立一套可治理、可维护、可自愈的节点体系。
目录
- 1. 节点池设计:先想清楚节点如何分组
- 2. 标签、污点与容忍:调度控制的三板斧
- 3. 节点生命周期管理:cordon/drain/uncordon
- 4. 节点健康检测与问题自愈
- 5. 节点自动扩缩容:Cluster Autoscaler 与 Karpenter
- 6. 节点维护窗口与重启策略
- 7. 节点运维自动化与可观测性
- 8. 常见坑与最佳实践
- 9. 总结
1. 节点池设计:先想清楚节点如何分组
1.1 什么是节点池(Node Pool)
节点池是具有相同配置的一组节点:相同的机器规格、镜像、标签、污点、自动扩缩容策略。在托管集群(EKS/AKS/GKE)中节点池是一等公民;自建集群可用标签/污点模拟等价分组。
节点池 A:m5.large(通用计算),无污点,标签 app=general
节点池 B:c5.xlarge(CPU 密集),污点 dedicated=compute:NoSchedule
节点池 C:r5.2xlarge(内存密集),污点 dedicated=memory:NoSchedule
节点池 D:g4dn(GPU),污点 gpu=true:NoSchedule,用 taint-based 专用
1.2 节点池划分维度
| 维度 | 划分方式 | 典型场景 |
|---|---|---|
| 规格 | 通用/CPU/内存/GPU | 不同负载的算力需求 |
| 竞价 vs 按需 | spot/on-demand | 成本优化(spot 承载可重调度负载) |
| 可用区 | zone 打散 | 容灾与就近调度 |
| 系统 vs 业务 | 专用节点池 | 网络插件、监控、ingress 独占 |
| 架构 | amd64/arm64 | 混合架构集群 |
1.3 节点池设计原则
- 职责单一:一个节点池承载一类负载,方便扩缩容与维护;
- 命名规范:
<role>-<zone>-<sizing>,如compute-az1-5xl; - 系统级节点池:给 kube-system 组件(CNI、监控、ingress)单独池,避免被业务抢占;
- 最小化规模:不要为每个服务建池,池太多会碎片化资源。
一句话:节点池 = 把"机器集合"变成"调度单元"——按规格/用途/成本分组,标签 + 污点让调度器知道"谁该去哪"。
2. 标签、污点与容忍:调度控制的三板斧
2.1 标签(Label):筛选与选择
标签是节点的属性标记,用于 nodeSelector 与拓扑调度:
kubectl label node worker-1 zone=az1 arch=amd64 gpu=true
# Pod 通过 nodeSelector 指定去哪类节点
spec:
nodeSelector:
zone: az1
gpu: "true"
2.2 污点(Taint)与容忍(Toleration):拒绝与例外
污点让节点排斥未容忍的 Pod;容忍是 Pod 声明"我能忍受这个污点"。两者配合实现独占式调度:
# 给 GPU 节点打污点,默认拒绝所有 Pod
kubectl taint nodes gpu-node gpu=true:NoSchedule
# Pod 声明容忍,才允许调度到 GPU 节点
spec:
tolerations:
- key: "gpu"
operator: "Equal"
value: "true"
effect: "NoSchedule"
2.3 三种污点效果
| 效果 | 行为 |
|---|---|
| NoSchedule | 新的不调度,已存在的保留 |
| PreferNoSchedule | 尽量不调度,软约束 |
| NoExecute | 立即驱逐不容忍的已有 Pod |
一句话:标签 = “怎么选”,污点 = “怎么拒”,容忍 = “谁能例外”——标签让调度灵活,污点让资源独占,三者结合是节点治理的基石。
3. 节点生命周期管理:cordon/drain/uncordon
3.1 三个核心命令
# cordon:标记节点不可调度(新 Pod 不再上去,已有 Pod 不受影响)
kubectl cordon node-1
# drain:优雅排空节点上的 Pod(先驱逐,等终止)
kubectl drain node-1 --ignore-daemonsets --delete-emptydir-data
# uncordon:恢复节点可调度
kubectl uncordon node-1
3.2 drain 的完整流程
kubectl drain node-1
├─ 驱逐 Pod(遵守 PDB)
├─ 等待 Pod 终止(Terminating → Gone)
├─ 排除 DaemonSet(--ignore-daemonsets)
└─ 完成后节点标记为不可调度
3.3 维护节点的标准操作流程
① cordon node-1 # 停止接收新 Pod
② drain node-1 --ignore-daemonsets # 排空业务 Pod
③ 执行维护(升级内核/更换硬件/重启)
④ kubectl uncordon node-1 # 恢复调度
关键:先 cordon 再 drain 是防御性习惯——即使 drain 中断,节点也不会接收新 Pod。
3.4 PDB 与驱逐的关系
drain 会尊重 PodDisruptionBudget:若驱逐会跌破 minAvailable,drain 会阻塞等待。这是保护服务的机制,但也意味着 drain 可能"卡住"——排空前先确认业务有冗余。
一句话:cordon = 关门、drain = 清场、uncordon = 开门——维护节点不是"直接重启",而是让 Pod 优雅离开、业务无损、节点干净退出。
4. 节点健康检测与问题自愈
4.1 节点健康状态
节点健康由 kubelet 定期上报,Node Conditions 反映状态:
kubectl describe node node-1 | grep -A 5 Conditions
# Ready/NotReady、MemoryPressure、DiskPressure、PIDPressure、NetworkUnavailable
4.2 问题检测与自愈工具
| 工具 | 定位 |
|---|---|
| node-problem-detector | 检测文件系统、Docker、内核等节点级问题 |
| Cluster Autoscaler + 健康检查 | 未就绪节点自动替换 |
| descheduler | 平衡调度,处理节点碎片 |
| kured / 云厂商维护 | 自动重启与滚动维护 |
| 自愈控制器 | 检测 NotReady 节点,drain + 替换 |
4.3 未就绪节点的处理策略
kubectl get node 发现 node-3 NotReady
├─ 立即排查(kubelet 日志、磁盘、网络)
├─ 若短期难恢复:cordon + drain 迁移业务
└─ 长期:移除节点 + 节点池滚动替换
一句话:节点自愈 = 健康检测(NPD)+ 自动替换(Autoscaler)+ 主动平衡(descheduler)——让节点故障从"人工救火"变成"自动化纠偏"。
5. 节点自动扩缩容:Cluster Autoscaler 与 Karpenter
5.1 为什么需要自动扩缩容
固定节点池要么浪费(负载低时闲置)要么不够(高峰排队)。自动扩缩容让节点数量跟随 Pod 需求。
5.2 Cluster Autoscaler(CA)
CA 根据 Pending Pod 决策扩容,根据资源利用率缩容:
Pod 因资源不足 Pending
→ CA 检测到 Pending Pod
→ 扩容节点池(加到对应 AZ)
→ Pod 调度成功
缩容:节点利用率低 + 可安全驱逐 → 缩容
# 最小/最大节点池限制
cluster-autoscaler:
min: 2
max: 10
5.3 Karpenter:更激进的节点自治
Karpenter 直接按需求创建/删除实例,不依赖节点池模板,支持多规格、竞价、细粒度调度:
apiVersion: karpenter.sh/v1beta1
kind: NodePool
metadata:
name: general
spec:
template:
spec:
requirements:
- key: karpenter.sh/capacity-type
operator: In
values: ["on-demand", "spot"]
- key: node.kubernetes.io/instance-type
operator: In
values: ["c5.large", "m5.large", "r5.large"]
disruption:
consolidationPolicy: WhenUnderutilized
5.4 CA vs Karpenter 对比
| 维度 | Cluster Autoscaler | Karpenter |
|---|---|---|
| 模型 | 基于节点池模板 | 按需求直接创建实例 |
| 规格灵活性 | 低(需预建池) | 高(按需选择规格) |
| 竞价支持 | 需配置 | 原生支持 |
| 运维复杂度 | 中 | 低(声明式) |
| 适用 | 云厂商托管、需要精细池控制 | 追求极致弹性与成本 |
一句话:CA = “节点池级别"扩缩,Karpenter = “实例级别"自治——从"管理池"到"管理需求”,弹性从被动变主动。
6. 节点维护窗口与重启策略
6.1 为什么需要维护窗口
内核补丁、安全更新、硬件更换都需要重启节点。若无窗口管理,重启会同时驱逐业务,导致服务抖动。
6.2 维护窗口设计
时间窗口:每周日凌晨 02:00-05:00(业务低谷)
范围:分批滚动(先非核心池,再核心池)
预警:提前 24h 通知业务方
流程:cordon → drain → 维护 → uncordon
6.3 kured:自动化重启
kured(KUbernetes Reboot Daemon) 检测需要重启的节点,自动执行 cordon/drain/uncordon:
# kured 配置示例
image: ghcr.io/kubereboot/kured
args:
- --reboot-command=/usr/bin/systemctl reboot
- --lock-ttl=30m
- --period=10m
- --drain-timeout=30m
一句话:维护窗口 = 固定时机 + 分批滚动 + 自动化工具(kured)——把节点重启从"随机打扰"变成"计划内无感维护”。
7. 节点运维自动化与可观测性
7.1 节点可观测性指标
| 指标 | 含义 | 目标 |
|---|---|---|
| node.ready | 节点就绪状态 | 100% |
| kubelet 请求错误率 | kubelet 健康 | < 1% |
| 节点 CPU/内存使用率 | 资源水位 | 合理阈值内 |
| disk pressure | 磁盘告警 | 无 |
| 驱逐计数 | 被驱逐 Pod 数 | 趋零 |
7.2 节点运维自动化
- Terraform/CloudFormation:节点池声明式管理
- Node Operator(如 Cluster API):节点生命周期自动化
- Node Healthcheck:自动检测 + 替换坏节点
- Rancher/平台:节点管理 UI 化
7.3 节点排障常用命令
kubectl describe node <node> # 全面状态
kubectl get node -o wide # 版本/地址/角色
ssh node-1 # 节点内排障
journalctl -u kubelet -f # kubelet 日志
kubectl debug node/node-1 -it # 临时进入节点
一句话:节点可观测 + 自动化 = 指标全监控、故障自检测、运维可声明——把节点从"手工台账"变成"数据驱动的资产"。
8. 常见坑与最佳实践
8.1 常见坑
| 坑 | 现象 | 对策 |
|---|---|---|
| 不设污点 | 系统 Pod 被业务抢占 | 系统池加污点 |
| 维护直接重启 | 业务被强制驱逐 | 先 cordon + drain |
| 无 PDB | drain 时服务中断 | 给关键服务配 PDB |
| 池太多 | 资源碎片化 | 按职责最小化分池 |
| 忽略 NotReady | 故障累积 | 健康检查 + 自动替换 |
| 竞价池混业务 | 被回收中断 | 竞价池只放可重调度负载 |
| 缩容无保护 | 状态fulset 误缩 | 配置 min 限制 |
8.2 最佳实践清单
- 节点池职责单一 + 命名规范;
- 系统池与业务池分离;
- 关键服务配 PDB 与拓扑分布;
- 自动扩缩容设 min/max 护栏;
- 维护走 cordon → drain → uncordon;
- 节点健康全指标监控 + 告警。
8.3 总结表
9. 总结
以下为全篇核心要点汇总:
| 环节 | 要点 |
|---|---|
| 节点池 | 按规格/用途分组,系统池隔离 |
| 调度控制 | 标签选择 + 污点拒绝 + 容忍例外 |
| 生命周期 | cordon → drain → 维护 → uncordon |
| 自愈 | NPD + Autoscaler + 自动替换 |
| 弹性 | CA(池级)/ Karpenter(实例级) |
| 维护 | 固定窗口 + kured 自动化 |
| 可观测 | 就绪率、压力、驱逐计数全监控 |
一句话记住:节点治理的终极目标,是让"节点故障"对业务无感——用节点池规划容量、用污点保护调度、用 drain 优雅维护、用自动扩缩容跟随需求、用自愈把故障挡在业务之外。节点不是黑盒,而是需要设计、治理与自动化的计算地基。
继续阅读
探索更多技术文章
浏览归档,发现更多关于系统设计、工具链和工程实践的内容。