K8s 节点 Node 变成 NotReady 排查
2026-08-11 00:53:03 # Kubernetes

集群中某个(或某些)节点的 STATUSReady 变成 NotReady,上面的 Pod 被驱逐并重新调度到其他节点。节点 NotReady 通常是 kubelet 与 API Server 心跳丢失,背后原因分散在 kubelet、容器运行时、网络插件、资源压力与证书等环节。

问题现象与背景原因

1
2
3
4
kubectl get nodes
NAME STATUS ROLES AGE VERSION
node-1 Ready <none> 200d v1.26.4
node-2 NotReady <none> 200d v1.26.4

节点 NotReady 的本质是 kubelet 无法再向 API Server 上报节点状态(NodeStatus / lease)。常见根因:

  1. kubelet 进程异常 / 退出:配置错误、kubeconfig 损坏、kubelet 证书过期、OOM 被杀。
  2. 容器运行时故障:containerd / docker 挂掉或无法启动,kubelet 连不上运行时(failed to connect to CRI)。
  3. CNI 网络插件异常:flannel / calico / cilium 相关 Pod 崩溃,节点网络不可达,触发 NetworkUnavailable
  4. 资源压力触发驱逐:节点磁盘(/var/lib / 日志盘)或内存达到 kubelet 驱逐阈值,kubelet 主动标记 DiskPressure / MemoryPressure
  5. 网络分区 / 时间不同步:节点与 apiserver 之间网络中断,或系统时间漂移导致证书校验失败。

排查过程(思路与定位方法)

第一步:在集群侧看节点的 Conditions 与消息。 describe node 的 Conditions 会列出 KubeletReadyMemoryPressureDiskPressureNetworkUnavailable 等状态及原因:

1
2
kubectl describe node node-2
kubectl get node node-2 -o jsonpath='{.status.conditions[*].message}'

重点关注 KubeletReadymessagereason,常能看到 kubelet stopped posting node status 之类线索。

第二步:登录故障节点,检查 kubelet 本身。 大部分 NotReady 根因在节点本地:

1
2
systemctl status kubelet
journalctl -u kubelet -n 100 --no-pager

若日志出现 x509: certificate has expired → 证书过期;出现 failed to connect to CRI / connect: connection refused → 运行时没起来。

第三步:检查容器运行时与 CNI。

1
2
3
4
5
6
7
8
9
10
11
12
# containerd
systemctl status containerd
crictl ps

# docker(旧版)
systemctl status docker
docker ps

# CNI 配置与插件 Pod
ls -l /etc/cni/net.d/
ip addr show | grep -E 'flannel|cali|cilium'
kubectl get pods -n kube-system -o wide | grep -E 'flannel|calico|cilium'

第四步:检查资源压力与时间。

1
2
3
df -h /var/lib
free -m
date # 与正常节点对比时间是否一致

提示:NotReady 多数不是「网络突然断了」这么简单。先看 kubelet 日志,再看容器运行时,再看 CNI,按这个顺序能最快收敛。

最终的解决方法

  • kubelet 起不来:根据 journalctl 报错修复配置;证书过期用 kubeadm certs renew 或轮换 kubelet 证书;被 OOM 则调大节点内存或限制其他负载。

  • 容器运行时故障:重启运行时并设为开机自启:

    1
    2
    systemctl restart containerd
    systemctl enable containerd
  • CNI 异常:重启对应网络插件 DaemonSet / Pod,或重装 CNI 配置;确认 /etc/cni/net.d 下只有一个插件配置生效,避免多个 CNI 互相覆盖。

  • 资源压力:清理磁盘(删除无用镜像 crictl rmi、清理容器日志)、扩容磁盘,或调整 kubelet --eviction-hard 阈值。

  • 时间不同步:启用并同步 NTP(chronyd / systemd-timesyncd)。

修复后确认节点回到 Ready:

1
2
systemctl restart kubelet
kubectl get nodes

操作命令(可直接复制执行)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 1. 集群侧看节点状态与条件
kubectl get nodes
kubectl describe node <node-name> | sed -n '/Conditions/,/Addresses/p'

# 2. 节点本地检查 kubelet
systemctl status kubelet
journalctl -u kubelet -n 100 --no-pager

# 3. 容器运行时
systemctl status containerd
crictl ps # 或 docker ps

# 4. CNI
ls -l /etc/cni/net.d/
kubectl get pods -n kube-system -o wide | grep -E 'flannel|calico|cilium'

# 5. 资源与时间
df -h /var/lib
free -m
date

# 6. 修复:重启运行时与 kubelet
systemctl restart containerd
systemctl restart kubelet
kubectl get nodes