worker01 NotReady 排查与修复步骤
摘要:Kubespray集群Worker节点NotReady问题分析与解决 问题现象: Worker01节点NotReady,kubelet报错连接localhost:6443被拒绝 Worker02节点正常,同样配置localhost:6443却显示Ready 根因分析: Kubespray设计机制:每个节点通过本机nginx-proxy代理连接apiserver Worker01故障原因: 节

文章目录
为什么其他节点也是 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 登录
ssh 192.168.22.152
# 或使用你的跳板机/账号,例如: ssh user@192.168.22.152
2. 检查 kubelet 与 containerd
sudo systemctl status kubelet
sudo systemctl status containerd
若任一为 inactive 或 failed,先尝试启动并看日志:
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 目录)。检查以下目录是否存在、可读且所在分区非满:
# 镜像/容器数据目录
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:
sudo systemctl restart containerd
sleep 5
sudo systemctl restart kubelet
4. 确认本机 6443 与 Kubespray 代理(重要)
Kubespray 下 kubelet 连的是本机 localhost:6443,由本机上的 nginx-proxy 等 Pod 代理到 apiserver。先确认本机是否有进程在监听 6443:
# 本机 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 能否连上:
curl -sk https://127.0.0.1:6443/healthz
从本机测到 control plane 的直连(可选,用于判断网络是否通):
curl -sk https://192.168.22.151:6443/healthz
若本机 6443 无监听且日志里有 “sandbox name is reserved”,优先做 containerd 状态清理:
sudo systemctl stop kubelet
sudo systemctl stop containerd
清理 CRI sandbox 目录时,若出现 “Device or resource busy”(多为 sandbox 下的 shm tmpfs 仍挂载),需先卸载再删:
# 先卸载 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"/*
然后启动服务:
sudo systemctl start containerd
sleep 5
sudo systemctl start kubelet
若重启后仍报 “sandbox name … is reserved for 633ecebd…” 等:说明名字占用在 containerd 内部状态里,只删 sandbox 目录不够,需要二选一:
方法 A:用 crictl 删掉占用的 sandbox(先试)
# 看所有 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 名字:
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)
sudo journalctl -u kubelet -f -n 100 --no-pager
观察是否仍有 InvalidDiskCapacity 或 image filesystem 相关报错;正常时应有 “Node worker01 status is now: NodeReady” 之类事件。
6. 从 control plane 侧再次检查
在 可执行 kubectl 的机器 上执行:
kubectl get nodes
kubectl describe node worker01
若 Ready 恢复,节点上的 unreachable taint 通常会由 control plane 自动清理;若长时间未清理,可手动去掉 taint(仅在确认节点已正常后):
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 | grep 6443 无监听 → 停 kubelet/containerd → 清理 CRI sandbox 后重启 → 确认 nginx-proxy 起、6443 有监听 → 必要时去 taint |
按上述步骤在 worker01 上执行后,若仍有问题,把 journalctl -u kubelet -n 100 和 describe node worker01 的完整输出贴出即可继续排查。
更多推荐



所有评论(0)