这是一份关于 Kubernetes 集群节点 NotReady 状态排查与修复 的完整复盘总结。

本次故障的核心原因是 未安装 CNI 网络插件,且在安装过程中遇到了 Kubelet 状态同步延迟 的小插曲。


一、 故障现象

  1. 集群状态:执行 kubectl get nodes,所有节点(Master 和 Worker)均显示 NotReady。
  2. Pod 状态:执行 kubectl get pods -n kube-system,发现缺少网络组件(如 Calico/Flannel),且 coredns 处于 Pending 状态。

二、 核心原因

Kubernetes 是一个高度解耦的系统,它默认不包含容器网络解决方案。

  1. CNI 缺失:Kubelet 启动时会检查 CNI 插件。如果没有安装,Kubelet 会上报 NetworkPluginNotReady,导致节点被标记为 NotReady。
  2. CoreDNS 依赖:CoreDNS 必须依赖 Pod 网络互通才能启动,因此在网络插件 Ready 之前,CoreDNS 会一直 Pending。
  3. Kubelet 假死/延迟(安装过程中遇到):在镜像已存在的情况下,Pod 依然卡在 Init 状态,说明 Kubelet 进程没有及时刷新 Pod 的状态或触发容器启动。

三、 详细修复步骤

1. 诊断问题

首先确认 NotReady 的具体原因。

kubectl describe node <节点名称>
  • 关键指标:查看 Conditions 字段下的 Ready 行。
  • 典型报错:runtime network not ready: NetworkReady=false reason:NetworkPluginNotReady。

2. 安装网络插件 (CNI)

针对 Kubernetes v1.16+ 版本,我们选择了 Calico v3.11。

kubectl apply -f https://docs.projectcalico.org/v3.11/manifests/calico.yaml
  • 作用:部署了一系列的资源(ConfigMap, DaemonSet, Deployment等)来建立集群内部网络。

3. 监控安装进度(排错关键)

安装后,并没有立即成功,我们通过以下命令监控:

kubectl get pods -n kube-system -w
  • 遇到的阻碍:calico-node 一直卡在 Init:0/3 或 Pending 状态,没有进入 Running。
  • 进一步排查:使用 kubectl describe pod <pod名> -n kube-system 查看 Events,发现调度成功(Scheduled)但未启动。

4. 解决节点卡顿问题

我们在 k8snodetwo 节点上发现,虽然镜像已经下载完毕(手动 pull 提示 up to date),但 Pod 依然不动。

  • 操作:手动重启该节点的 Kubelet 服务。

    systemctl restart kubelet
    
  • 原理:强制 Kubelet 重新读取配置、扫描本地镜像并拉起容器。

5. 最终验证

  • Pod 检查:所有 calico-node 和 coredns 状态变为 Running,且 READY 列为 1/1。

  • 节点检查

    kubectl get nodes
    

    状态由 NotReady 变为 Ready


四、 知识点与避坑指南

为了防止下次遇到类似问题,请检查以下环境配置(由浅入深):

  1. 必须安装网络插件
    • K8s 初始化后第一件事就是装 CNI(Calico, Flannel, Weave 等任选其一)。
  2. 镜像拉取问题
    • 国内环境经常拉取不到 k8s.gcr.io 或 docker.io 的镜像。若 Pod 卡在 ContainerCreating 或 ImagePullBackOff,务必检查网络或配置 Docker 镜像加速器。
  3. Swap(交换分区)必须关闭
    • 现象:Kubelet 启动失败,或者节点反复 NotReady。
    • 命令:swapoff -a 并修改 /etc/fstab 永久禁用。
  4. 时间同步
    • 所有节点时间误差不能超过几秒,否则证书验证失败,组件无法通信。
  5. 防火墙/SELinux
    • 建议初学者在测试环境直接关闭 firewalld 和 selinux,避免被复杂的规则拦截导致网络不通。

五、 常用排查命令清单(建议收藏)

# 1. 看节点大概状态
kubectl get nodes

# 2. 看节点具体为什么 NotReady (最重要!)
kubectl describe node <node-name>

# 3. 看系统级 Pod 是否都在跑
kubectl get pods -n kube-system

# 4. 看某个卡住的 Pod 到底发生了什么事件
kubectl describe pod <pod-name> -n kube-system

# 5. 看 Kubelet 服务日志 (当 kubectl 命令都无法工作时用这个)
journalctl -u kubelet -f