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.confserver: 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:NoExecuteNoSchedule
  • 关键事件 : 节点 Rebooted ;kubelet 连 https://localhost:6443connection 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

若任一为 inactivefailed,先尝试启动并看日志:

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

观察是否仍有 InvalidDiskCapacityimage 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 100describe node worker01 的完整输出贴出即可继续排查。

相关推荐
阿里云云原生11 小时前
巨人网络《超自然行动组》携手阿里云打造云原生游戏新范式
云原生
71ber16 小时前
深入理解 HAProxy:四层/七层透传与高级 ACL 调度详解
linux·云原生·haproxy
A-刘晨阳16 小时前
K8S 之 DaemonSet
运维·云原生·容器·kubernetes·daemonset
2501_9481142419 小时前
资深程序员真实测评:9家中转API平台实战横评
微服务·云原生·架构
切糕师学AI19 小时前
Kubernetes 中的 Volume(存储卷)
云原生·容器·kubernetes
AI_567820 小时前
Terraform多环境部署:模块化配置一次搞定
云原生·terraform
DeepFlow 零侵扰全栈可观测20 小时前
使用 eBPF 零代码修改绘制全景应用拓扑
java·前端·网络·分布式·微服务·云原生·云计算
予枫的编程笔记1 天前
【Docker基础篇】Docker入门必看:镜像、容器、仓库的关系,用类比讲得明明白白
docker·云原生·后端开发·docker架构·docker入门·镜像与容器·程序员干货
xixiyuguang1 天前
解决Docker启动后自动生成docker0虚拟网卡(172.17.0.1)及启动失败问题
云原生·eureka