在部署完 Kubernetes 集群之后,如果新建的 Pod 一直停留在 ContainerCreating 状态,执行 kubectl describe pod 后看到类似 network plugin is not ready: cni config uninitialized 或者 No CNI configuration file in /etc/cni/net.d 的报错,基本可以确定是 CNI 网络插件缺失或者没有正常初始化。这类问题在手动搭建集群和使用 kubeadm 初始化的场景中极为高发,本文将系统梳理排查思路。

CNI 的工作原理与故障表现
CNI 全称 Container Network Interface,是 CNCF 定义的一套容器网络规范。它约定了 kubelet 在创建 Pod 沙箱(sandbox)时,如何调用外部网络插件为沙箱配置网络接口、分配 IP 地址、设置路由。kubelet 本身并不关心网络细节,它只负责在合适的时机以命令行方式执行插件二进制文件,并把网络配置通过标准输入和环境变量传给插件。
整个链路涉及三个关键要素:一是节点上的配置目录 /etc/cni/net.d,kubelet 从这里读取网络配置文件;二是插件二进制所在目录,通常是 /opt/cni/bin,里面应该有 bandwidth、bridge、loopback、portmap 等文件;三是插件自身的守护进程,比如 Flannel 的 kube-flannel DaemonSet 或 Calico 的 calico-node。任何一个环节缺失,Pod 网络都无法建立。
故障表现非常典型:Pod 长时间处于 ContainerCreating,describe 输出中的 Events 部分会重复打印 Failed to create pod sandbox,并附带 cni config uninitialized 之类的消息。此时 kubectl get nodes 还可能看到节点状态是 NotReady,因为 kubelet 的节点就绪条件之一就是 CNI 插件可用。
常见原因逐一分析
1. 插件根本没有部署
最常见的情况就是用 kubeadm 初始化完集群后忘记安装网络插件。kubeadm 不会自带任何 CNI,需要管理员手动部署一个。很多人 init 完直接就去看节点状态,发现 NotReady 才意识到少了东西。判断方法很简单,执行 kubectl get pods -n kube-system,查看是否存在 flannel、calico、weave 或 cilium 相关的 Pod。如果没有,直接部署即可。
2. 插件 Pod 部署了但起不来
第二种情况是插件已经部署,但对应的 DaemonSet Pod 没有正常运行。常见原因包括镜像拉取失败(国内环境访问 Docker Hub 或 gcr.io 受限)、节点上缺少某些内核模块、或者端口被占用。排查命令如下:
# 查看 kube-system 命名空间下的所有 Pod kubectl get pods -n kube-system -o wide # 详细查看插件 Pod 的事件,定位镜像拉取或调度问题 kubectl describe pod kube-flannel-ds-xxxxx -n kube-system # 查看 kubelet 日志中的 CNI 相关报错 journalctl -u kubelet --no-pager | grep -i cni
如果事件里出现 ImagePullBackOff,说明是镜像问题,需要手动导入镜像或者改用国内镜像源。如果 Pod 处于 Pending 状态,多半是调度失败,describe 输出里会有节点资源不足或污点不匹配的提示。
3. DaemonSet 只在部分节点运行
CNI 插件通常以 DaemonSet 形式部署,理论上每个节点都要跑一份。如果清单文件里写死了 nodeSelector,或者节点标签不符合要求,就会出现部分节点网络正常、部分节点 Pod 起不来的诡异现象。比如 Flannel 老版本默认要求节点带有 kubernetes.io/os=linux 标签,新加入的节点如果标签缺失就会被跳过。检查方法:
# 查看节点标签 kubectl get nodes --show-labels # 查看哪个节点上没有运行插件 Pod kubectl get pods -n kube-system -o wide | grep flannel
4. 配置目录或二进制目录异常
有时插件 Pod 显示 Running,但 Pod 仍然报 CNI 未就绪。这时需要登录到目标节点检查文件系统。正常情况下,安装完插件后 /etc/cni/net.d 下应该出现 10-flannel.conflist 或 10-calico.conflist 之类的配置文件,/opt/cni/bin 下应该有插件二进制。如果配置目录是空的,说明插器的初始化容器没有成功写入配置,可能是挂载路径不对或权限问题。另外要注意 kubelet 启动参数 --cni-bin-dir 和 --cni-conf-dir 如果被自定义过,目录位置会与默认值不同,检查时要保持一致。
完整排查流程与修复示例
把上面的分析串成一条完整的排查路径,遇到问题时按顺序执行以下步骤,基本可以覆盖绝大多数 CNI 缺失故障:
kubectl get nodes确认节点是否 Ready;kubectl get pods -n kube-system确认 CNI 插件是否存在并运行;kubectl describe pod查看 Pending 或 CrashLoopBackOff 的具体原因;- 登录节点检查
/etc/cni/net.d与/opt/cni/bin; - 通过
journalctl -u kubelet查看 kubelet 侧的报错细节。
以 Flannel 为例,标准的安装方式是先确认 Pod 网段与 kubeadm 初始化时的 --pod-network-cidr 参数一致(Flannel 默认 10.244.0.0/16),然后应用官方清单:
# 部署 Flannel kubectl apply -f https://github.com/flannel-io/flannel/raw/master/Documentation/kube-flannel.yml # 观察插件 Pod 是否全部 Running kubectl get pods -n kube-system -w
Calico 的安装类似,只是需要注意其默认网段是 192.168.0.0/16,若集群初始化时用了别的网段,需要在清单中修改 CALICO_IPV4POOL_CIDR 或使用环境变量注入,否则节点间路由会混乱,出现跨节点 Pod 无法互通的问题。
插件部署成功后,可以创建一个测试 Pod 来验证网络连通性:
kubectl run nettest --image=busybox --restart=Never -it --rm -- sh # 在容器内执行 ping 10.244.1.1 # 测试跨节点 Pod IP 连通性 nslookup kubernetes # 测试集群内 DNS 解析
如果 ping 通且 DNS 解析正常,说明 CNI 已经完全就绪。最后提醒一点:更换 CNI 插件属于高风险操作,务必先卸载旧插件、清理 /etc/cni/net.d 下的旧配置并重启 kubelet,再部署新插件,否则残留配置会与新插件冲突,导致更难排查的网络异常。
KubernetesCNI网络插件修改时间:2026-09-15 10:16:37