worker01 NotReady 排查与修复步骤

文章目录

    • [为什么其他节点也是 localhost:6443 却是 Ready?(Kubespray 设计)](#为什么其他节点也是 localhost:6443 却是 Ready?(Kubespray 设计))
    • [诊断结论(从 control plane 与 worker01 日志)](#诊断结论(从 control plane 与 worker01 日志))
    • [在 worker01 上执行的步骤(SSH 到 192.168.22.152)](#在 worker01 上执行的步骤(SSH 到 192.168.22.152))
      • [1. SSH 登录](#1. SSH 登录)
      • [2. 检查 kubelet 与 containerd](#2. 检查 kubelet 与 containerd)
      • [3. 处理 "invalid capacity 0 on image filesystem"](#3. 处理 “invalid capacity 0 on image filesystem”)
      • [4. 确认本机 6443 与 Kubespray 代理(重要)](#4. 确认本机 6443 与 Kubespray 代理(重要))
      • [5. 再次查看 kubelet 日志(重点看 Ready 与 image filesystem)](#5. 再次查看 kubelet 日志(重点看 Ready 与 image filesystem))
      • [6. 从 control plane 侧再次检查](#6. 从 control plane 侧再次检查)
    • 小结

为什么其他节点也是 localhost:6443 却是 Ready?(Kubespray 设计)

在 Kubespray 部署的集群里,worker 节点上的 kubelet.conf 写 server: https://localhost:6443 是预期配置,不是笔误。

  • Kubespray 在每个节点(包括 worker)上会跑一个 本机 API 代理 (例如 nginx-proxy-<node名> Pod),在本机 监听 127.0.0.1:6443,把 kubelet 的请求转发到真正的 apiserver(master 或 LB)。
  • 所以 kubelet 配 https://localhost:6443 时,实际连的是本机上的这个代理,由代理再去连 control plane。
  • worker02 Ready:说明 worker02 上的 nginx-proxy 等代理 Pod 正常运行,本机 6443 有进程在监听,kubelet 能连上。
  • worker01 NotReady :说明 worker01 上没有进程在监听 localhost:6443 ,所以 kubelet 报 connection refused。常见原因是:该节点上的 nginx-proxy(或等价代理)Pod 没起来------例如因重启后 containerd 的 sandbox 状态异常,导致 "sandbox name is reserved" 等错误,Pod 创建失败,代理自然起不来。

因此:不要 把 worker01 的 kubelet 改成直连 master IP,否则会和 Kubespray 设计不一致(证书/代理都按 localhost 设计)。应恢复本机代理能正常启动,即解决 containerd sandbox 冲突,让 nginx-proxy 等 Pod 在 worker01 上跑起来。


诊断结论(从 control plane 与 worker01 日志)

  • 节点: worker01,IP 192.168.22.152
  • 状态 : NotReady,Condition 为 NodeStatusUnknown,信息为 "Kubelet stopped posting node status."
  • Taints : node.kubernetes.io/unreachable:NoExecute、NoSchedule
  • 关键事件 : 节点 Rebooted ;kubelet 连 https://localhost:6443 报 connection refused ;CreatePodSandbox 报 sandbox name is reserved for xxx(nodelocaldns、nginx-proxy-worker01、kube-proxy 等);Calico 访问 10.233.0.1 超时(因节点未 Ready,网络未就绪)。

结论 :worker01 上负责监听 localhost:6443 的 nginx-proxy(或等价)Pod 起不来 ,根因是 containerd 侧 sandbox 名字占用冲突 (重启后状态不同步)。应在本机清理 containerd 的 CRI 状态并重启 containerd/kubelet,使 nginx-proxy 等系统 Pod 能正常创建,本机 6443 有代理监听后 kubelet 即可上报、节点变为 Ready。


在 worker01 上执行的步骤(SSH 到 192.168.22.152)

1. SSH 登录

bash 复制代码
ssh 192.168.22.152
# 或使用你的跳板机/账号,例如: ssh user@192.168.22.152

2. 检查 kubelet 与 containerd

bash 复制代码
sudo systemctl status kubelet
sudo systemctl status containerd

若任一为 inactive 或 failed,先尝试启动并看日志:

bash 复制代码
sudo systemctl start containerd
sudo systemctl start kubelet
sudo journalctl -u kubelet -n 80 --no-pager
sudo journalctl -u containerd -n 50 --no-pager

3. 处理 "invalid capacity 0 on image filesystem"

该告警通常与 kubelet 使用的「镜像文件系统」路径有关(containerd 的 root 或 image 目录)。检查以下目录是否存在、可读且所在分区非满:

bash 复制代码
# 镜像/容器数据目录
sudo df -Th /var/lib/containerd
sudo df -Th /var/lib/kubelet
ls -la /var/lib/containerd
ls -la /var/lib/kubelet

# 若使用 overlay,看 overlay 挂载
mount | grep overlay

若 /var/lib/containerd 或 kubelet 的 image 目录在异常挂载上(或刚重启未挂好),先确保挂载正常,再重启 containerd 和 kubelet:

bash 复制代码
sudo systemctl restart containerd
sleep 5
sudo systemctl restart kubelet

4. 确认本机 6443 与 Kubespray 代理(重要)

Kubespray 下 kubelet 连的是本机 localhost:6443,由本机上的 nginx-proxy 等 Pod 代理到 apiserver。先确认本机是否有进程在监听 6443:

bash 复制代码
# 本机 6443 是否有监听(若为空说明 nginx-proxy 等代理未起)
ss -tlnp | grep 6443
# 或
sudo netstat -tlnp | grep 6443
  • 若 6443 无监听:说明本机 API 代理 Pod(如 nginx-proxy-worker01)没起来,需先修 containerd/sandbox(见下),让该 Pod 能创建;或临时改 kubelet server 为 master 地址以恢复 Ready,再修代理。

  • 若有监听 :再测 kubelet 能否连上:

    bash 复制代码
    curl -sk https://127.0.0.1:6443/healthz

从本机测到 control plane 的直连(可选,用于判断网络是否通):

bash 复制代码
curl -sk https://192.168.22.151:6443/healthz

若本机 6443 无监听且日志里有 "sandbox name is reserved",优先做 containerd 状态清理:

bash 复制代码
sudo systemctl stop kubelet
sudo systemctl stop containerd

清理 CRI sandbox 目录时,若出现 "Device or resource busy" (多为 sandbox 下的 shm tmpfs 仍挂载),需先卸载再删:

bash 复制代码
# 先卸载 sandbox 下的 shm 挂载点
SANDBOX_ROOT=/var/run/containerd/io.containerd.grpc.v1.cri/sandboxes
for d in "$SANDBOX_ROOT"/*/shm; do
  [ -d "$d" ] && sudo umount "$d" 2>/dev/null
done
# 再删除 sandbox 目录
sudo rm -rf "$SANDBOX_ROOT"/*

然后启动服务:

bash 复制代码
sudo systemctl start containerd
sleep 5
sudo systemctl start kubelet

若重启后仍报 "sandbox name ... is reserved for 633ecebd..." 等:说明名字占用在 containerd 内部状态里,只删 sandbox 目录不够,需要二选一:

方法 A:用 crictl 删掉占用的 sandbox(先试)

bash 复制代码
# 看所有 pod(含已退出的),找到对应 SANDBOX_ID 的 pod
crictl pods -a
# 若日志里写的 reserved for 633ecebd...,看是否有该 ID 或对应 nginx-proxy 的 pod,然后停掉并删掉
crictl stopp <POD_ID>   # 若还在跑
crictl rmp <POD_ID>     # 删除 pod,会释放 sandbox 名字

方法 B:清空整个 CRI 运行时状态(方法 A 找不到或删不掉时)

停 kubelet/containerd 后,先 umount sandbox 下的 shm(同上),然后删掉整个 CRI 状态目录,让 containerd 不再保留任何 sandbox 名字:

bash 复制代码
sudo systemctl stop kubelet
sudo systemctl stop containerd

SANDBOX_ROOT=/var/run/containerd/io.containerd.grpc.v1.cri/sandboxes
for d in "$SANDBOX_ROOT"/*/shm; do [ -d "$d" ] && sudo umount "$d" 2>/dev/null; done
sudo rm -rf /var/run/containerd/io.containerd.grpc.v1.cri
# 然后启动
sudo systemctl start containerd
sleep 5
sudo systemctl start kubelet

删掉 io.containerd.grpc.v1.cri 后,该节点上所有 CRI 的 sandbox/容器状态会清空,kubelet 会按当前 Pod 列表重新创建,包括 nginx-proxy。

然后观察 nginx-proxy 等 Pod 是否在 worker01 上 Running,以及 ss -tlnp | grep 6443 是否出现。

5. 再次查看 kubelet 日志(重点看 Ready 与 image filesystem)

bash 复制代码
sudo journalctl -u kubelet -f -n 100 --no-pager

观察是否仍有 InvalidDiskCapacity 或 image filesystem 相关报错;正常时应有 "Node worker01 status is now: NodeReady" 之类事件。

6. 从 control plane 侧再次检查

在 可执行 kubectl 的机器 上执行:

bash 复制代码
kubectl get nodes
kubectl describe node worker01

若 Ready 恢复,节点上的 unreachable taint 通常会由 control plane 自动清理;若长时间未清理,可手动去掉 taint(仅在确认节点已正常后):

bash 复制代码
kubectl taint nodes worker01 node.kubernetes.io/unreachable:NoExecute-
kubectl taint nodes worker01 node.kubernetes.io/unreachable:NoSchedule-

小结

项目 内容
节点 worker01,192.168.22.152
现象 NotReady,kubelet 连 localhost:6443 被拒;CreatePodSandbox "sandbox name is reserved"
原因 Kubespray 用本机 nginx-proxy 提供 localhost:6443;worker01 上该 Pod 因 sandbox 冲突起不来
建议操作 SSH 到 worker01 → 确认 `ss -tlnp

按上述步骤在 worker01 上执行后,若仍有问题,把 journalctl -u kubelet -n 100 和 describe node worker01 的完整输出贴出即可继续排查。

相关推荐
分布式存储与RustFS5 天前
MinIO 官方 Docker 镜像被移除:依赖它的项目该怎么办
docker·云原生·devops·对象存储·minio·分布式存储
codeejun5 天前
每日一Go·MySQL-5、锁机制全解析
云原生·golang
赵文宇(温玉)5 天前
CoreDNS的hosts插件的缺行配置导致k8s集群异常
容器·kubernetes·rancher
张洛闻Eren5 天前
k8s云原生【第十课】:水平 Pod 自动扩缩容
运维·数据库·云原生·kubernetes·github
Thneonl6 天前
你的 Pod 为什么 Pending:调度器两阶段
后端·kubernetes
不吃香菜kkk、6 天前
CI/CD(GitOps)学习与部署手册
运维·云原生·容器·kubernetes·云计算·jenkins·argocd
ChaITSimpleLove6 天前
云原生性能对决:JDK21虚拟线程+GraalVM vs .NET10/11 技术栈深度对比
微服务·云原生·serverless·graalvm native·native aot·runtime async·.net11/java21
春天花会开1316 天前
Supabase 自部署 Edge Functions 超时从 60s 延长到 360s 完整复盘
运维·云原生
ysu_03147 天前
【2026】K8s GPU调度空占怎么解?Kueue与Volcano Gang配置
云原生·kubernetes·gpu算力·volcano·ai基础设施·kueue·gang scheduling
哈__7 天前
KES-Operator重塑Kubernetes环境下的KES数据库集群管理
数据库·kubernetes·operator·kes