深色模式
节点 NotReady 排障
摘要:本文面向生产 SRE / 集群运维,讲解节点
NotReady的根因定位框架:NotReady本质是 kubelet 无法向 API Server 上报心跳(默认超时约 40s)。覆盖容器运行时、资源压力、证书、网络分区四大类,给出节点层systemctl/journalctl/crictl/df命令与危险操作的回滚。覆盖版本:Kubernetes v1.28+。
适用版本与前提
- Kubernetes:v1.28+。
- 工具:
kubectl、kubectl debug node/<node>、节点 SSH。 - 前提:具备节点运维权限(NotReady 往往意味着需登录节点排障)。
背景与问题
节点 Ready 条件是 kubelet 周期上报 NodeStatus 的结果。一旦 kubelet 进程挂掉、容器运行时不可用、或节点与控制面网络中断,Ready 会在约 40s 后翻转为 False,节点被自动打上 node.kubernetes.io/not-ready 污点,该节点 Pod 被驱逐(经 taint-based-eviction 宽限期,默认 300s)。因此 NotReady 本身只是症状,必须下钻到 node conditions 才能找到根因(来源:GKE 官方文档 - Troubleshoot nodes with the NotReady status;Kubernetes Recipes - Node NotReady)。
核心概念:Node Conditions
kubectl describe node 的 Conditions 段是诊断入口:
| Condition | True 含义 |
|---|---|
NetworkUnavailable | CNI / 节点到控制面网络异常 |
MemoryPressure | 节点内存不足,kubelet 即将驱逐 |
DiskPressure | 节点磁盘不足 |
PIDPressure | 节点 PID 耗尽 |
Ready | kubelet 正常上报 |
心智模型
Ready=False 是结果,上面五个 condition 才是原因。排障顺序永远是:先看 conditions 锁定是哪一类压力,再进节点查具体进程/磁盘/证书/网络。
排障决策树
清单 1:kubelet / 容器运行时故障
- 现象:
Ready=False,kubelet 日志报Container runtime not ready/ 无法连接/run/containerd/containerd.sock。 - 原因:containerd(或 CRI-O/docker-shim)崩溃、配置损坏、反复重启。
- 定位(节点层):bash
systemctl status kubelet journalctl -u kubelet --since '15 minutes ago' --no-pager | tail -40 systemctl status containerd journalctl -u containerd -f # 或 crictl info 验证 CRI 可达1
2
3
4 - 修复:若运行时配置损坏,先备份
/etc/containerd/config.toml再修正;确认无损坏后重启:bashsystemctl restart containerd systemctl restart kubelet1
2 - 回滚:重启前备份相关 unit 配置;若误改配置导致更差,还原备份文件并重启。
生产危险
systemctl restart kubelet 会短暂中断本节点 Pod 的存活/就绪上报,并可能触发 kube-proxy、CNI 插件重启。务必先 kubectl cordon 阻止新调度,确认影响面后再执行;多控制面节点逐个操作,避免同时重启。
清单 2:磁盘压力(DiskPressure)
- 现象:
DiskPressure=True,节点拒绝新 Pod,旧 Pod 被驱逐。 - 原因:容器镜像/日志堆积,
/var/lib/containerd、/var/lib/kubelet或根分区超过 kubelet 驱逐阈值(默认imagefs.available<15%触发)。 - 定位:bash
df -h / /var/lib/kubelet /var/lib/containerd du -sh /var/log/* 2>/dev/null journalctl --disk-usage1
2
3 - 修复:清理无用镜像与日志:bash
crictl rmi --prune # 删除未被使用的镜像 journalctl --vacuum-size=500M # 压缩 systemd 日志1
2 - 回滚:清理不可逆但影响小;建议先
df -h记录基线,确认释放量符合预期。
清单 3:内存压力(MemoryPressure)
- 现象:
MemoryPressure=True,节点级 OOM。 - 原因:节点整体内存耗尽,内核 OOM Killer 杀进程。
- 定位:bash
free -h dmesg | grep -i 'oom\|killed' kubectl top pods -A --sort-by=memory | head1
2
3 - 修复:定位内存大户 Pod 调小其 request/limit 或驱逐;必要时扩容节点池。
- 回滚:
kubectl rollout undo回退有问题的 workload。
清单 4:网络分区 / CNI 故障(NetworkUnavailable)
- 现象:
NetworkUnavailable=True或Ready=False但 kubelet 在跑。 - 原因:节点到 API Server 网络中断、防火墙阻断 6443、CNI 插件崩溃。
- 定位:bash
# 节点到控制面连通性 curl -k https://<api-server-ip>:6443/healthz # CNI 配置与插件状态 ls /etc/cni/net.d/ systemctl status kubelet | grep -i 'network'1
2
3
4
5 - 修复:放行防火墙/安全组 6443;重启 CNI 插件 DaemonSet(视厂商)。
- 回滚:防火墙变更前记录原规则,异常即还原。
注意
托管集群(GKE/EKS/ACK)的节点组件由云厂商托管,NotReady 多为底层 VM/网络问题,应优先 kubectl drain 后联系厂商或替换节点,而非手动改节点系统组件。
清单 5:证书过期导致 kubelet 失联
- 现象:kubelet 日志持续报 TLS 错误,
Ready=False,多为所有节点同一时刻失效。 - 定位:bash
openssl x509 -in /var/lib/kubelet/pki/kubelet-client-current.pem -noout -dates1 - 修复与回滚:见《证书过期与 kubeconfig 问题》专篇。
kubeadm certs renew后用 manifest 移出/移回方式重启静态 Pod;回滚即还原/etc/kubernetes/pki备份。
维护操作:cordon / drain / uncordon
生产危险
kubectl drain 会驱逐节点上所有业务 Pod(DaemonSet 默认保留)。执行前必须确认有充足冗余容量,并加 --ignore-daemonsets --delete-emptydir-data。生产节点维护标准流程:
bash
kubectl cordon <node> # 停止调度
kubectl drain <node> --ignore-daemonsets --delete-emptydir-data --grace-period=120
# ... 节点维护 ...
kubectl uncordon <node> # 维护完成恢复调度1
2
3
4
2
3
4