面向初级运维,使用 Linux 节点和稳定 Kubernetes API。命令按 Bash 编写。本文为教学故障场景,日志及结果为示意,不冒充生产实测;执行前确认 context、命名空间和权限。
一、遭遇情况:一台工作节点突然 NotReady
同一节点上的多个服务出现异常,kubectl get nodes 显示 worker 节点 NotReady。有人准备立刻删除 Node 对象,也有人打算批量重启所有节点。
本篇案例设定为:某台使用 containerd 的 Linux 工作节点更新运行时配置后,containerd 启动失败,kubelet 无法正常访问 CRI。它只是 NotReady 的一种原因,网络中断、证书、磁盘和 CNI 都可能产生其他路径。
本篇以取证和受控恢复为实践,不要求读者主动停止真实节点来制造故障。
二、原因分析:Ready 是条件,不是一个进程名称
Node 状态由节点与控制面通信、kubelet 观察和相关组件健康共同影响。控制面长时间收不到心跳时,Ready 还可能变为 Unknown;不同原因需要读 condition 的 reason、message 与更新时间。

SchedulingDisabled 通常反映节点被 cordon,不等于 NotReady。节点可以 Ready 但不接受新的普通调度,也可以不 Ready 却仍留有尚未完全终止的业务进程。不要把对象展示状态与物理执行状态简单划等号。
三、排查思路:先看影响,再登录对应节点
1. 从控制面读取对象与事件
kubectl get nodes -o wide
kubectl describe node 目标节点
kubectl get pods -A -o wide --field-selector spec.nodeName=目标节点
kubectl get lease -n kube-node-lease 目标节点 -o yaml
替换目标节点名,并确保有相应读取权限。Lease 的更新可以帮助观察心跳,但不单独证明节点上应用和网络都正常。
比较影响是否只在单节点,近期是否有运行时、系统、证书或网络变更。多个节点同时失败时,也要考虑共享网络或控制面入口,不应逐台重复同一重启命令。
2. 仅在获准访问的故障节点读取服务信息
以下针对使用 systemd 和 containerd 的 Linux 节点,其他运行时或托管平台应按对应流程调整:
sudo systemctl status kubelet --no-pager -l
sudo systemctl status containerd --no-pager -l
sudo journalctl -u kubelet --since '30 minutes ago' --no-pager
sudo journalctl -u containerd --since '30 minutes ago' --no-pager
df -h
df -i
free -h
如果 kubelet 错误明确指向运行时连接,而 containerd 又有配置解析失败,两组时间与原因能对应,就形成了本案例的证据链。不要仅看 kubelet 进程 active 就宣布节点没问题。
四、实践:围绕具体分支做判断
| 证据 | 下一步重点 |
|---|---|
| kubelet 本身未运行 | 读取启动错误、配置与凭据 |
| kubelet 无法访问 CRI socket | 检查真实 endpoint 与对应运行时 |
| 运行时正常,网络未就绪 | 看 CNI 组件与节点网络配置 |
| 节点到 API 超时 | 路由、DNS、代理、证书与入口 |
| DiskPressure / MemoryPressure | 沿资源压力继续查,第 15 篇详述 |
有 crictl 的节点可以按现有配置执行 sudo crictl info、sudo crictl ps -a。工具应使用集群实际的 CRI endpoint,默认探测失败不一定等于运行时不可用。
现代 Kubernetes 节点不必使用 Docker Engine,docker ps 失败不能作为 containerd 集群运行时损坏的证据。也不要为了排查而临时切换运行时。
五、修复实践:恢复已确认损坏的一项配置
在本案例中,应保存失败日志与修改前后的 containerd 配置,核对安装方式和版本,按节点维护流程恢复此前确认可用的配置。不要直接运行“生成默认配置并覆盖”,那可能丢掉集群需要的 registry、cgroup 或插件设置。
确认维护范围与业务恢复安排后,才在该节点恢复运行时服务,例如:
sudo systemctl start containerd
sudo systemctl is-active containerd
sudo journalctl -u kubelet --since '5 minutes ago' --no-pager
这里适用于服务已失败、配置已修正的案例。已运行的运行时是否需要重启,必须根据实际变更判断;重启 kubelet 或运行时可能影响节点工作,不是无代价的“刷新”。
如果只是 API 连接或证书问题,就修对应通路,不要套用这组服务启动操作。
六、验证:Ready 恢复后仍要核对业务
kubectl wait --for=condition=Ready node/目标节点 --timeout=180s
kubectl describe node 目标节点
kubectl get pods -A -o wide --field-selector spec.nodeName=目标节点
确认心跳、条件与相关组件稳定,再检查业务 Pod 和真实请求。若节点原本因维护被 cordon,是否 uncordon 应由维护流程决定,不因 Ready 恢复就自动接回新负载。
NotReady 节点上的有状态应用还要考虑存储附加与重复实例风险,不能因为控制面看不到进程就直接强制删除所有 Pod。节点对象删除也不是通用修复方法。
七、总结
排查顺序是:影响边界 → Node 条件与心跳 → 对应节点的 kubelet/运行时/网络证据 → 修复确认的原因 → 节点与业务双重验收。先定位哪一层失联,再决定是否需要服务操作。