U盘装Kubernetes离线集群失败的关键在于路径绑定与拉取策略未覆盖:需重定向镜像、二进制、依赖包的访问路径,显式配置工具(如Kubespray/kubeadm/KubeKey)使用本地file://或私有仓库地址,并严格匹配目录结构;同时必须提前完成时间同步与hosts解析,且worker节点需配置insecure-registries绕过认证。

U盘能装下完整 Kubernetes 集群所需资源,但直接“插上就装”会失败——关键不在存储容量,而在镜像、二进制、依赖包三类资源的路径绑定和拉取策略是否被正确覆盖。
U盘挂载后必须重定向所有资源访问路径
Kubespray、kubeadm 或 KubeKey 等工具默认从网络地址(如 https://storage.googleapis.com)下载文件或拉取镜像。离线时若不显式覆盖这些路径,即使 U 盘里有全部文件,工具仍会卡在超时或 404 错误上。
- 对 Kubespray:需修改
inventory/sample/group_vars/all/all.yml中的download_localhost: true,并设置local_release_dir: "/mnt/usb/kubespray-offline",确保files.list和images.list中的 URL 被脚本自动替换为本地file:///mnt/usb/...形式 - 对 kubeadm:不能只拷贝
kubeadm二进制,还必须用kubeadm config images list核对版本,再通过docker load -i把对应镜像逐个导入,并用kubeadm init --image-repository 192.168.100.10:5000指向本地仓库(若 U 盘不跑服务,则改用--pod-network-cidr+ 手动kubectl apply -f离线 YAML) - 对 KubeKey:运行前必须设环境变量
KKZONE=cn并指定--container-runtime docker,否则它仍会尝试走 GitHub CDN 下载images-list.txt
U盘内文件结构必须严格匹配工具预期路径
不同工具对离线资源的目录层级敏感。例如 Kubespray 的 manage-offline-files.sh 默认把二进制解压到 temp/files/,而 KubeKey 的 offline-installation-tool.sh -s 要求镜像存放在 ./kubesphere-images/ 下,且子目录名必须是镜像仓库路径(如 library/kube-apiserver)。
- 常见错误:把所有
.tar.gz镜像丢进 U 盘根目录,结果kubekey报错failed to find image: kubesphere/ks-installer:v3.2.1—— 它实际在找/kubesphere-images/kubesphere/ks-installer_v3.2.1.tar.gz - 安全做法:挂载 U 盘后先
ls /mnt/usb确认结构,再执行部署命令;不要用cp -r *,而用rsync -av --delete保持层级 - Ubuntu 系统下注意:U 盘默认可能以
noexec挂载,导致./offline-installation-tool.sh权限拒绝,需mount -o remount,exec /mnt/usb
节点间时间同步与 hosts 解析不能依赖网络服务
无网环境下,chrony 或 systemd-timesyncd 会持续报错,进而导致 kubeadm init 因证书时间校验失败退出;同时,若 /etc/hosts 未提前写死所有节点 IP 和主机名,kubelet 启动后无法解析 etcd 地址,日志里反复出现 context deadline exceeded。
- 必须在复制 U 盘前,就在每台目标机上运行:
timedatectl set-ntp false && chronyd -q 'server 192.168.100.10 iburst'(用 Master 节点做局域网 NTP 源) -
/etc/hosts至少包含:192.168.100.10 k8s-master1、192.168.100.11 k8s-node1、192.168.100.12 k8s-node2,且所有节点内容完全一致 - 验证方式:在任意节点执行
ping -c1 k8s-node1 && date -u,两项都成功才算过关
最易被忽略的是镜像 registry 的认证绕过——很多方案教你在 Master 上起 registry:2,却没提 worker 节点的 /etc/docker/daemon.json 必须加 "insecure-registries": ["192.168.100.10:5000"],否则 kubelet 拉镜像时直接拒连,错误信息藏在 journalctl -u kubelet -n 50 里,不是 kubeadm init 主流程输出。











