这是一份关于 Kubernetes 集群节点 NotReady 状态排查与修复 的完整复盘总结。
本次故障的核心原因是 未安装 CNI 网络插件,且在安装过程中遇到了 Kubelet 状态同步延迟 的小插曲。
一、 故障现象
- 集群状态:执行 kubectl get nodes,所有节点(Master 和 Worker)均显示 NotReady。
- Pod 状态:执行 kubectl get pods -n kube-system,发现缺少网络组件(如 Calico/Flannel),且 coredns 处于 Pending 状态。
二、 核心原因
Kubernetes 是一个高度解耦的系统,它默认不包含容器网络解决方案。
- CNI 缺失:Kubelet 启动时会检查 CNI 插件。如果没有安装,Kubelet 会上报 NetworkPluginNotReady,导致节点被标记为 NotReady。
- CoreDNS 依赖:CoreDNS 必须依赖 Pod 网络互通才能启动,因此在网络插件 Ready 之前,CoreDNS 会一直 Pending。
- 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。
四、 知识点与避坑指南
为了防止下次遇到类似问题,请检查以下环境配置(由浅入深):
- 必须安装网络插件:
- K8s 初始化后第一件事就是装 CNI(Calico, Flannel, Weave 等任选其一)。
- 镜像拉取问题:
- 国内环境经常拉取不到 k8s.gcr.io 或 docker.io 的镜像。若 Pod 卡在 ContainerCreating 或 ImagePullBackOff,务必检查网络或配置 Docker 镜像加速器。
- Swap(交换分区)必须关闭:
- 现象:Kubelet 启动失败,或者节点反复 NotReady。
- 命令:swapoff -a 并修改 /etc/fstab 永久禁用。
- 时间同步:
- 所有节点时间误差不能超过几秒,否则证书验证失败,组件无法通信。
- 防火墙/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