简介:这份资源是面向 Kubernetes 运维与集群管理人员的 Calico v3.25.0 离线安装包,专为解决内网、隔离环境或网络受限场景下无法在线拉取镜像的部署难题。压缩包共 3 个文件,约 187.24MB,包含 1 个 tar 镜像包、1 个 yaml 部署清单和 1 个 txt 说明文档:tar 包封装了 Felix、BIRD、Typha 等 Calico 核心组件镜像,yaml 提供集群网络与策略配置模板,txt 则给出离线安装的步骤指引。借助这套材料,读者无需连接外部网络即可完成 Calico 网络插件的部署,快速搭建集群网络通讯与网络策略管理能力,同时可对照文档理解各组件职责与配置要点,降低离线环境下的排错门槛。目前已有 453 人学习下载,适合需要在内网环境中落地 Calico 的运维人员参考使用。
1. calico-image-v3.25.0离线包:内网 K8s 集群怎么把 CNI 镜像一次备齐
机房里有一套完全隔离的 Kubernetes 集群,kubelet 起来了,节点也 Ready 了,结果 Pod 全部卡在 ContainerCreating,kubectl describe pod一看,事件里写着拉取calico/node、calico/cni、calico/kube-controllers这几个镜像失败。这就是 calico-image-v3.25.0 离线包要解决的事:把 Calico v3.25.0 这一版所需的全部容器镜像,提前在能联网的机器上拉下来、打成 tar 包,再搬到内网导入到每个节点的容器运行时里。它适合运维、交付、信创环境实施的同学,尤其是那些节点不能出网、但又必须跑 Calico 做 Pod 网络的场景。下面按「镜像清单怎么定 → 离线包怎么做 → 内网怎么导 → 怎么验证 → 坑在哪」的顺序讲清楚,参数和命令都能直接抄。
2. 先搞清楚 Calico v3.25.0 到底要哪几个镜像
2.1 从 manifest 反推镜像清单,而不是凭记忆
很多人做离线包翻车,第一步就错了:凭印象只拉calico/node,结果部署时发现还缺calico/cni和calico/kube-controllers。正确做法是从官方 release 的 manifest 文件里把镜像名抠出来。Calico 的部署清单通常是一个calico.yaml或tigera-operator.yaml,里面image:字段就是权威清单。
常见做法是先把 manifest 下载到联网机器上,然后用 grep 提取:
# 下载 v3.25.0 的 manifest(以 calico.yaml 为例) curl -O https://raw.githubusercontent.com/projectcalico/calico/v3.25.0/manifests/calico.yaml # 提取所有 image 字段,去重排序 grep -E 'image:\s' calico.yaml | awk '{print $2}' | tr -d '"' | sort -u这段命令的逻辑很直白:grep抓出所有含image:的行,awk取第二个字段(也就是镜像地址),tr -d '"'去掉可能存在的引号,最后sort -u去重。跑完你会看到类似docker.io/calico/node:v3.25.0、docker.io/calico/cni:v3.25.0、docker.io/calico/kube-controllers:v3.25.0这样的输出。注意 v3.25.0 这个 tag 必须和你的 manifest 版本严格一致,混用 v3.24 的镜像会出现 CRD 字段不匹配,Pod 起不来还报一堆看不懂的 schema 错误。
2.2 三个核心镜像各自干什么,缺一个都不行
calico/cni是装在每个节点上的 CNI 插件,负责给 Pod 分配 IP、配置 veth pair,它由 DaemonSet 以 initContainer 形式跑,装完就退出。calico/node是常驻的 Felix + BIRD 进程,负责路由下发、网络策略执行,是真正让 Pod 能通的核心。calico/kube-controllers是单副本的控制器,同步 K8s 的 NetworkPolicy、IPPool 等资源到 Calico 的数据存储。
| 镜像 | 作用 | 部署形态 | 是否必须 |
|---|---|---|---|
| calico/cni | 节点 CNI 插件安装 | DaemonSet initContainer | 必须 |
| calico/node | 路由与策略执行 | DaemonSet 主容器 | 必须 |
| calico/kube-controllers | 资源同步控制器 | Deployment 单副本 | 必须 |
| calico/typha | 大规模集群的 datastore 缓存 | Deployment | 节点数 > 50 建议 |
如果你的集群节点数超过 50,manifest 里还会带calico/typha,这个镜像也别忘了。判断方法很简单:grep 出来的清单里有几个就备几个,不要自己删减。参数上唯一要盯的是 tag,v3.25.0 全系列镜像 tag 都是v3.25.0,没有3.25.0这种不带 v 的写法,写错了 docker pull 直接报 manifest unknown。
3. 在联网机器上把镜像打成离线 tar 包
3.1 用 docker save 逐个导出,别用 export
镜像导出有两个命令容易混:docker save保留镜像的完整层和元数据,docker export只导出容器文件系统、丢掉镜像历史。离线包必须用save。先把三个镜像拉下来:
# 拉取 v3.25.0 全部镜像 docker pull docker.io/calico/node:v3.25.0 docker pull docker.io/calico/cni:v3.25.0 docker pull docker.io/calico/kube-controllers:v3.25.0 # 逐个 save 成 tar,文件名带版本号方便追溯 docker save -o calico-node-v3.25.0.tar docker.io/calico/node:v3.25.0 docker save -o calico-cni-v3.25.0.tar docker.io/calico/cni:v3.25.0 docker save -o calico-kube-controllers-v3.25.0.tar docker.io/calico/kube-controllers:v3.25.0-o指定输出文件,后面跟镜像全名。这里建议一个镜像一个 tar,而不是三个塞一个包。原因是内网导入时如果某个镜像损坏,单独重传一个几百 MB 的文件比重传一个 1GB+ 的大包省事得多。calico/node大概 200MB 上下,calico/cni100MB 左右,kube-controllers几十 MB,三个加起来通常不超过 500MB,U 盘就能带走。
3.2 校验完整性,别等搬到机房才发现包坏了
tar 包在拷贝过程中损坏是血泪经验里最常见的一类问题,尤其是用 U 盘或移动硬盘跨机器搬。导出后立刻算校验和:
# 生成 sha256 校验文件 sha256sum calico-*.tar > calico-v3.25.0.sha256 # 拷贝到内网后,导入前先校验 sha256sum -c calico-v3.25.0.sha256sha256sum -c会逐行比对文件里的哈希值和实际文件,输出OK才算完整。如果显示FAILED,说明传输过程出了问题,别抱侥幸心理去导入,导进去的镜像层可能是残缺的,运行时才报错更难查。这一步花不了两分钟,但能省掉在机房里对着ImagePullBackOff抓头的半小时。
提示:如果内网节点用的是 containerd 而不是 docker,导出的 tar 格式是通用的 OCI 兼容格式,containerd 的
ctr命令可以直接导入,不需要额外转换。
4. 内网节点导入镜像并让 kubelet 认到
4.1 docker 运行时用 docker load,containerd 用 ctr
导入命令取决于节点用的容器运行时。先确认:
# 看节点用的是 docker 还是 containerd kubectl get nodes -o wide # 输出里 CONTAINER-RUNTIME 列会写 docker:// 或 containerd://如果是 docker,直接 load:
docker load -i calico-node-v3.25.0.tar docker load -i calico-cni-v3.25.0.tar docker load -i calico-kube-controllers-v3.25.0.tar如果是 containerd,用ctr,注意要指定 namespace,k8s 用的 namespace 是k8s.io:
ctr -n k8s.io images import calico-node-v3.25.0.tar ctr -n k8s.io images import calico-cni-v3.25.0.tar ctr -n k8s.io images import calico-kube-controllers-v3.25.0.tar-n k8s.io这个参数是新手最容易漏的。不指定 namespace,ctr默认导到default命名空间,kubelet 在k8s.io里找不到镜像,照样去外网拉,然后失败。导入完用ctr -n k8s.io images ls | grep calico确认能看到三个镜像。
4.2 每个节点都要导,或者推到内网 registry
Calico 的 DaemonSet 会在每个节点上跑,所以每个节点本地都得有镜像。节点少(三五个)就逐个 scp 加导入;节点多就搭一个内网 registry,把镜像 push 上去,然后改 manifest 里的 image 地址指向内网 registry。
# 内网 registry 方案:先打 tag 再 push docker tag docker.io/calico/node:v3.25.0 registry.internal:5000/calico/node:v3.25.0 docker push registry.internal:5000/calico/node:v3.25.0push 完记得把calico.yaml里所有docker.io/calico/替换成registry.internal:5000/calico/,用sed批量改:
sed -i 's|docker.io/calico/|registry.internal:5000/calico/|g' calico.yaml改完再kubectl apply -f calico.yaml。这一步的关键是 registry 地址必须是所有节点都能解析和访问的,如果 registry 用了自签证书,还得在每个节点的 containerd 配置里加insecure_registries或者把 CA 证书放到/etc/containerd/certs.d/下,否则拉取时报 x509 证书错误。
5. 离线部署 Calico 的避坑与排查清单
5.1 镜像导入了但 Pod 还是 ImagePullBackOff
现象:ctr images ls明明能看到 calico/node:v3.25.0,但 Pod 事件还是Failed to pull image。原因通常是镜像 tag 和 manifest 里写的不完全一致,比如 manifest 写的是docker.io/calico/node:v3.25.0,而你导入的镜像名被 containerd 规范化成了docker.io/calico/node:v3.25.0之外的形态,或者 manifest 里带了个@sha256:摘要。解决办法是ctr -n k8s.io images ls看镜像的完整 REPOSITORY 和 TAG,和 manifest 里的image:字段逐字符比对,包括docker.io前缀有没有。
5.2 calico-node 起来了但 Pod 之间不通
现象:calico-nodeDaemonSet 全部 Running,但新建的 Pod 互相 ping 不通,跨节点更不通。原因多半是 IPIP 或 VXLAN 的网卡没起来,或者节点间防火墙挡了协议号。Calico 默认用 IPIP 模式,需要内核加载ipip模块,且节点间放通 IP 协议号 4(IPIP)或 47(GRE)。解决:lsmod | grep ipip确认模块加载,没有就modprobe ipip;防火墙侧放通对应协议,或者改用 VXLAN 模式(协议号 UDP 4789)。
5.3 kube-controllers 报 datastore 连接失败
现象:calico-kube-controllers反复重启,日志里Failed to connect to datastore。原因通常是它连的 datastore 类型和实际不符。v3.25.0 默认用 K8s API 作为 datastore(KDD 模式),如果你的 manifest 里还留着 etcd 的配置,就会连不上。解决:确认calico.yaml里DATASTORE_TYPE环境变量是kubernetes,并且没有多余的ETCD_ENDPOINTS配置。
5.4 节点重启后镜像没了
现象:节点重启,之前docker load进去的镜像消失,Pod 又开始拉取失败。原因是有些环境把 docker 的存储目录挂在了 tmpfs 或者每次重启会重置的盘上。解决:检查/var/lib/docker或/var/lib/containerd是不是持久化目录,df -h看挂载点。如果是临时盘,得把存储目录迁到持久盘,或者干脆用内网 registry 方案,让节点重启后从 registry 拉。
5.5 版本混用导致 CRD 冲突
现象:集群里之前装过 v3.24 的 Calico,直接 apply v3.25.0 的 manifest,报 CRD 已存在且字段不兼容。原因:Calico 的 CRD 跨版本有字段增删,直接覆盖会冲突。解决:先kubectl delete -f旧版 manifest(注意这会短暂断网),或者用kubectl apply --server-side强制更新,再不行就手动kubectl replace相关 CRD。生产环境务必先在测试集群验证升级路径。
6. 把离线包做成可复用资产的两个技巧
第一个技巧是给离线包加一个manifest.txt,记录这一版包含哪些镜像、tag、sha256、导出时间。下次做 v3.26.0 的包时,直接 diff 两个 manifest,就知道镜像清单变了没有,不用重新 grep 一遍。这个习惯我坚持了两年,交接给同事时对方一眼就能看懂包里有什么。
第二个技巧是用skopeo替代docker save。skopeo copy可以在不启动 docker daemon 的情况下把镜像从 registry 直接拷成 tar,适合在 CI 流水线里批量做包:
# 用 skopeo 直接导出,无需 docker daemon skopeo copy docker://docker.io/calico/node:v3.25.0 docker-archive:calico-node-v3.25.0.tar:docker.io/calico/node:v3.25.0冒号后面那段docker-archive:文件:镜像名的写法是 skopeo 的固定格式,镜像名要写全,否则导入后 tag 会丢。我一般会在流水线里跑一个循环,把 grep 出来的镜像清单逐个 skopeo copy,最后统一算 sha256 打包。这样每次 Calico 发新版,改一个版本号变量就能重新出包,比手动 docker pull 靠谱得多。
验证离线包是否真的可用,最直接的办法是找一台干净的、断网的测试机,把包导进去,apply manifest,看三个组件是否全部 Running,再起两个测试 Pod 互相 ping。这一步别省,我吃过亏:有一次包里的 kube-controllers 镜像层缺了一块,导入时不报错,跑起来才崩,排查了半天才发现是导出时磁盘满了导致 tar 截断。从那以后我每次出包都先df -h看一眼磁盘余量,再算 sha256,两个动作加起来不到一分钟,但能挡掉大部分低级翻车。希望帮到你。
本文还有配套的精品资源,点击获取