kubeadm init后节点NotReady是正常现象,因控制平面已启动但缺少CNI网络插件,导致kubelet无法配置Pod网络、分配IP,故无法上报Ready状态,coredns等依赖Service网络的Pod亦会Pending。

装 Kubernetes 不是“跑个脚本就完事”,真正卡住新手的,从来不是 kubeadm init 这条命令本身,而是执行后 Pod 起不来、coredns 一直 Pending、kube-proxy 报错找不到 iptables —— 这些现象背后,全是容器编排原理在起作用。
为什么 kubeadm init 后节点状态是 NotReady?
刚执行完 kubeadm init,kubectl get nodes 显示 NotReady 是正常现象。这不是安装失败,而是控制平面组件(apiserver、etcd、scheduler 等)虽已启动,但工作节点上还缺一个关键角色:网络插件。
- Kubernetes 默认不内置 CNI(容器网络接口)实现,
kubeadm只负责拉起控制平面,不自动装calico或flannel - 没有 CNI 插件,
kubelet就无法为 Pod 分配 IP、设置网络命名空间,自然无法上报 Ready 状态 -
corednsPod 卡在Pending,往往就是因为它依赖 Service 网络(ClusterIP),而该网络需等 CNI 就绪后才能初始化
所以看到 NotReady,第一反应不是重装,而是检查是否执行了类似 kubectl apply -f https://docs.projectcalico.org/manifests/calico.yaml 这类 CNI 部署操作。
Pod 为什么不能直接运行在宿主机上?
你写好一个 Deployment YAML,kubectl apply 后,Pod 并不会“直接”跑在节点操作系统里。它必须经过调度、注入、隔离三步:
-
Scheduler先从etcd读取未绑定节点的 Pod 对象,再查各 Node 的capacity和allocatable资源(CPU、内存、nodeSelector标签等),选中一个节点并把nodeName字段写回 etcd -
Kubelet在目标节点持续监听 etcd 中属于自己节点的 Pod 变更,一旦发现新 Pod,就调用容器运行时(如containerd)拉镜像、创建容器 - 每个 Pod 启动时,
Kubelet会为其创建独立的 Linux network namespace 和 IPC namespace,并挂载共享卷——这正是 Pod 内多个容器能用localhost通信、共用存储的根本原因
跳过这一整套机制(比如手动 docker run),就等于绕过了 Kubernetes 的编排能力,也失去了健康检查、重启策略、服务发现等所有上层功能。
etcd 里到底存了什么,为什么它一挂整个集群就瘫?
etcd 不是日志库或缓存,它是 Kubernetes 的唯一事实来源(Single Source of Truth)。所有“你想让集群变成什么样”的声明,最终都固化在这里:
- 用户提交的 YAML(Deployment、Service、ConfigMap)被
apiserver解析后,以键值对形式存入etcd,路径类似/registry/deployments/default/my-app - 节点状态(
Node对象)、Pod 实际运行位置(nodeName)、Endpoint 列表(Endpoints对象)也都实时写入etcd -
Controller Manager不靠“记忆”干活,而是不断对比etcd里的期望副本数(replicas: 3)和实际运行数(status.replicas: 2),差1就触发创建
所以 etcd 数据损坏或长期不可写,会导致控制器失明、调度器失效、kubectl get 返回过期信息——表面看是命令没响应,实则是整个编排逻辑的“大脑记忆”断连了。
真正难的不是装出一个能跑 nginx 的集群,而是理解每个 Pending、CrashLoopBackOff、ImagePullBackOff 状态背后,是哪一层组件在响应、哪条数据链路断了。这些细节藏在 kubectl describe pod 的 Events 里,也藏在 kubelet 日志和 etcd 健康检查中——而不是安装文档的第一行命令里。


















