
文章目录
-
- [为什么其他节点也是 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 能否连上:
bashcurl -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 的完整输出贴出即可继续排查。