
简介Calico v3.20.6版本的离线部署资源包面向需要在Kubernetes集群中集成Calico网络插件的中高级运维、开发人员尤其适用于无外网或内网受限环境下的集群搭建。资源共5个文件由4个容器镜像tar包和1个核心配置文件calico.yaml组成压缩包整体约96.68MB。镜像分别涵盖Calico Node、CNI插件、kube-controllers及pod2daemon-flexvol对应节点Pod IP分配与BGP路由、Pod网络接口设置、网络策略与IP池管理、DaemonSet配置挂载等职责calico.yaml则定义了DaemonSet、CNI配置、策略控制器及BGP参数可通过kubectl apply直接部署。已有1083人学习下载适合离线环境下的Calico网络规划与策略调试能为多租户或高安全需求集群提供完整的网络隔离与管控能力。资源包内文件命名清晰便于核对版本与组件部署时可大幅节省逐一下载镜像的时间。1. 一条命令装完却在重启后丢网络Calico v3.20.6 镜像与 YAML 为什么必须一起准备做 Kubernetes 集群交付的人多半遇到过这种场面kubectl apply 一条 calico.yaml 下去节点 ReadyPod 也能跑起来隔天重启节点cni0 没了Pod 调度过去全是 ContainerCreatingkubelet 日志里反复报 “failed to setup network”。多数时候不是 Calico 不好用而是镜像版本和 YAML 没配对或者离线环境里镜像根本没导进去。我这次要拆的就是 calico-v3.20.6 版本容器镜像 加 calico.yaml 这套组合镜像从哪来、怎么导入 containerdYAML 里哪些参数必须改装完之后怎么验证以及最容易翻车的几个现场。这套东西不复杂但每一步都有坑跟着做一遍比搜十篇帖子有用。适合正在搭私有云、信创环境或离线集群的运维和交付工程师。2. 准备 v3.20.6 容器镜像离线包清单与导入到 containerd 的完整过程2.1 v3.20.6 需要哪几个镜像、为什么是这三个Calico 在 v3.20.x 这个版本线里部署形态已经收敛得很干净一个 DaemonSet 跑 calico-node一个 Deployment 跑 calico-kube-controllers再加一个 CNI 插件镜像。对应到镜像仓库里就是三个镜像calico/node:v3.20.6calico/cni:v3.20.6calico/kube-controllers:v3.20.6很多人只准备了前两个等到 kubectl apply 之后发现 calico-kube-controllers 一直 CrashLoopBackOff才回头补第三个。这个控制器管 IP 池回收、节点 IP 自动分配、Felix 配置下发少了它网络策略和 IP 池的生命周期管理会出问题属于必须带上的。还有一个容易忽略的点v3.20.6 默认的安装方式用的是 Kubernetes API 作为数据存储不再依赖 etcd所以不需要准备 calico-etcd 镜像。这一点和老的 v2.x、v3.0 系列差别很大如果你是从老集群迁移过来别把 etcd 镜像也塞进来。镜像来源上常见做法是先在能联网的机器上 docker pull 官方镜像然后 save 成 tar 包。如果你有自建的 Harbor 或 Nexus也可以直接 docker tag 后推到私有仓库节点上配置好 containerd 的 registry 认证即可。离线环境里更省事的路径是docker save 成单个 tar 文件U 盘或内网传过去再用 ctr 导入。2.2 导出与导入镜像docker save 到 ctr images import 全流程先在一台能联网的 Linux 机器上拉镜像。这里建议加上--platform linux/amd64避免在 ARM 或多架构环境里拉到不匹配的镜像。# 拉取 v3.20.6 相关的三个镜像 docker pull --platform linux/amd64 calico/node:v3.20.6 docker pull --platform linux/amd64 calico/cni:v3.20.6 docker pull --platform linux/amd64 calico/kube-controllers:v3.20.6 # 导出成一个 tar 包方便拷贝 docker save calico/node:v3.20.6 calico/cni:v3.20.6 calico/kube-controllers:v3.20.6 -o calico-v3.20.6-images.tar导出后到目标节点上执行导入。这里有个容易踩的位置你的节点如果用的是 containerd就不要用 docker load要用 ctr。# 导入到 k8s 使用的 containerd 命名空间 ctr -n k8s.io images import calico-v3.20.6-images.tar # 验证镜像是否导入成功 crictl images | grep calicoctr 导入这步很多人会漏掉-n k8s.io。kubelet 默认只从 k8s.io 这个命名空间里找容器镜像如果你不加-n k8s.io镜像导入到了默认命名空间kubelet 一样拉不到Pod 状态永远是 ImagePullBackOff。crictl images 是直接对接 kubelet 视角的用它验证最靠谱。如果你不是离线环境而是走私有仓库那么导入后还需要改 tag 指向私有仓库地址并确保每个节点的 containerd 配置里加了config_path或registry.mirrors否则同一个镜像名在不同节点上的解析结果会不一致表现就是有的节点 Pod 正常有的节点一直拉镜像超时。2.3 镜像的 tag 和 digest 要锁住升级后重启不踩回旧版一个很多人忽视的细节imagePullPolicy 默认是 IfNotPresent但如果你的 YAML 里写的是:latest或者没写 tagNode 重启后 containerd 会尝试重新拉取而在离线环境里拉取失败就直接报错。所以 v3.20.6 的三个镜像 tag 必须写全最好是写带 digest 的 addressable 格式。# 查看镜像 digest crictl inspecti calico/node:v3.20.6 | grep imageDigest拿到 digest 后可以把 calico.yaml 里的镜像地址写成calico/nodesha256:xxxx这种形式。好处是不管哪个节点只要导入的镜像 digest 和 YAML 里写的对得上就一定用这个版本不会出现某台节点还是旧镜像、某台节点已经换了新镜像的混乱状态。这一点在交付给客户、后续做版本审计时特别有用能省掉一半扯皮。3. 照着改 calico.yaml镜像仓库替换、IP 自动检测与平台适配3.1 从官方 manifests 拿 YAML先做镜像地址替换Calico 的 calico.yaml 不是随手装就能用的。官方发布包里的 manifests/calico.yaml 默认镜像地址是docker.io/calico/...。在线环境没问题但离线或内网环境必须改成你自己的仓库地址或本地导入的镜像名。以离线导入为例镜像已经通过 ctr 导入到了 k8s.io 命名空间此时 YAML 里的镜像名不需要改成私服地址保持calico/node:v3.20.6这种原样即可因为 kubelet 会把calico/node解析为 containerd 里的同名校验和。但如果你走的是 Harbor就需要把docker.io/calico统一替换成harbor.example.com/library/calico。常见的做法是下载官方 v3.20.6 发布页的 calico.yaml然后用 sed 批量替换镜像前缀。注意不要只改 calico-node 那一段calico.yaml 里同时有 calico/cni、calico/node、calico/kube-controllers 三处镜像地址漏掉任何一个对应组件都会拉不到镜像。# 替换镜像仓库前缀为自建 Harbor sed -i s#docker.io/calico#harbor.example.com/library/calico#g calico.yaml # 确认替换结果 grep image: calico.yamlsed 命令里的分隔符用了#是为了避免镜像地址里的/和:干扰替换。替换后建议人工再过一眼 grep 结果确认三处镜像都变成了目标地址不要只看到一处就继续。3.2 必改参数CALICO_IPV4POOL_CIDR 与 IP_AUTODETECTION_METHODv3.20.6 的 calico.yaml 里calico-node 的 DaemonSet 环境变量里有几个关键项直接决定集群能不能在已有网络环境下正常工作。第一是CALICO_IPV4POOL_CIDR它定义 Calico 为 Pod 分配的网段。默认值是192.168.0.0/16这个网段在真实环境里极其容易和宿主机网段、企业内网网段冲突。如果你在用 Flannel 时习惯用10.244.0.0/16或者集群的--cluster-cidr已经定成10.244.0.0/16那么这里就必须改成同一个网段。Calico 不会帮你去读 kube-apiserver 的 cluster-cidr 配置它只信自己 YAML 里的值。两边不一致的时候Pod 分配的 IP 和路由表会出现各种诡异的不通现象。# calico.yaml 中 calico-node DaemonSet 的环境变量片段 - name: CALICO_IPV4POOL_CIDR value: 10.244.0.0/16 - name: IP_AUTODETECTION_METHOD value: interfaceeth.*IP_AUTODETECTION_METHOD是第二个必调参数。Calico 在节点上需要选一张网卡来建立 BGP 或 VXLAN 隧道默认的first-found策略不靠谱。在多网卡机器上比如有 eth0 管理网、eth1 业务网或者有 docker0、br-ex 这种虚拟网卡Calico 可能选到一张没有实际流量的网卡结果就是节点状态 Ready但 Pod 间通不了。这个参数的值建议用正则匹配你实际业务的网卡名。常见的内网服务器是eth.*云主机可能是ens.*、enp.*。你可以在节点上先ip addr看一眼再决定写哪个正则。3.3 按需裁剪关掉你不用的功能少给自己找麻烦v3.20.6 的 calico.yaml 默认会把大部分功能都打开包括 Felix 的策略 enforcement、BGP 组网、VXLAN 封装选择。但对一些场景这些功能反而是负担。比如你只是想用 Calico 做纯 overlay 网络不想让集群内部的 BGP 路由泄露到物理网络那就把CALICO_IPV4POOL_IPIP改成Never同时考虑开启 VXLAN 模式。v3.20.6 里 VXLAN 是作为 IPPool 的封装选项存在的不是全局开关需要在 calico.yaml 里找到 IPPool 资源定义把encapsulation: VXLAN放开。注意这里不是简单的改环境变量需要同时修改 IPPool 的 CRD 定义否则改了环境变量不会生效。还有一类场景集群里同时存在 AMD64 和 ARM64 节点。Calico 的官方 YAML 默认没做多架构亲和性你需要给 calico-node 和 calico-kube-controllers 加上 nodeSelector按kubernetes.io/arch分流。如果只有一个架构的节点这一步可以跳过。但如果你交付的是信创环境飞腾、鲲鹏这种 ARM 节点占多数建议直接把 YAML 里的镜像 tag 换成 multi-arch 支持的版本名并在节点上确认导入的镜像 digest 对得上当前架构。# 给 calico-node 增加节点选择避免调度到不合预期的节点 nodeSelector: kubernetes.io/os: linux kubernetes.io/arch: amd64这段逻辑在做混合架构集群时更容易体现价值。Calico 的组件对架构敏感程度高镜像拉错架构会导致容器启动即崩溃日志里只会有 exec format error 一行提示不看架构的话很难定位。4. 从安装到验证kubectl apply 之后怎么看网络状态、路由和策略4.1 安装顺序先 ready 网络插件再看节点状态Calico 的安装顺序我一般会放在 kubeadm init 完成之后、加入其他工作节点之前。原因很简单如果你先把所有节点 join 进来再装 Calico节点会长时间处于 NotReady 状态期间如果集群里有初始化容器或健康检查会把问题带出来。# 应用修改后的 calico.yaml kubectl apply -f calico.yaml # 查看 calico 相关 Pod 是否 Running kubectl get pods -n kube-system | grep calico这里有个细节calico.yaml 会在 kube-system 命名空间里创建 DaemonSet 和 Deployment所以你需要在 kube-system 里看 Pod 状态。正常情况下calico-node 的 Pod 数量应该和你集群里的节点数一一对应calico-kube-controllers 应该有一个 ReplicaSet 维护的单副本。如果 calico-node 的 Pod 一直 Pending最可能是节点亲和性或资源不足。v3.20.6 默认给 calico-node 设置了较多资源请求在低配机器上可能调度不过去。你可以看 Pod 的事件kubectl describe pod -n kube-system calico-node-xxx事件里会明确写调度失败原因。如果是资源不足就改了 requests 再 apply。4.2 验证网络节点路由、Pod 间互通、跨节点流量三条线装完 Calico 后不能只看 Pod 状态要验证三类东西第一是节点上有没有生成 Calico 的路由表项第二是 Pod 与 Pod 之间通不通第三是跨节点的流量走的是不是 Calico 管理的路径。# 在节点上查看路由确认 calico 网段和隧道设备存在 ip route | grep 10.244 # 查看 veth 设备是否创建 ip link | grep cali如果你用的是 VXLAN 模式节点上应该能看到 vxlan.calico 这个设备。如果是 BGP 模式节点上的 BGP 会话应该能看到对端节点地址。看不到路由表项时不要急着重启 Calico先看 felix 日志。# 进入 calico-node 容器查看 felix 日志 kubectl logs -n kube-system calico-node-xxx | grep -i error\|fatalFelix 是 Calico 的数据面代理报错信息比 kubelet 的报错明确得多。常见错误比如 “auto-detected IP is not a valid IP” 说明 IP_AUTODETECTION_METHOD 匹配到了错误网卡“Could not connect to etcd” 说明 datastore 配置没配对虽然是 k8s 模式但某些老 YAML 片段还会尝试连 etcd。4.3 备份与回滚calico.yaml 的“后悔药”要提前留好很多人在集群里手动改过 Calico 的配置然后发现网络异常后想回滚结果发现没备份原 YAML只能重新去下载再改一遍镜像地址。这个成本没必要花。我习惯的做法是calico.yaml 在 apply 之前先cp calico.yaml calico.yaml.bak-$(date %Y%m%d)并且把改动过的关键 diff 记下来。万一改坏了直接kubectl delete -f calico.yaml kubectl apply -f calico.yaml.bak-xxx就能恢复。注意 delete 之后要等几十秒让旧的网络规则完全清掉再 apply 回去。这个步骤虽然看起来笨但在生产环境里是能扛住事故的兜底动作。5. 镜像 YAML 踩坑排查v3.20.6 最常见的 5 个现场5.1 现象一ctr 导入成功但 Pod 一直 ImagePullBackOff原因crictl 能看到镜像但 YAML 里镜像 tag 和导入的 tag 不一致。比如你在 YAML 里写的是calico/node:v3.20.6但离线包导入时 tag 被改成了calico/node:v3.20.6-bakkubelet 自然找不到。解决以 crictl images 显示为准反向核对 YAML。如果导入时确实改了 tag就重新导入一次或者在 YAML 里用 digest 地址。crictl images | grep calico5.2 现象二节点多网卡Pod 间跨节点不通原因IP_AUTODETECTION_METHOD 没写Calico 自动选了一张不参与集群流量的网卡比如 docker0 或某张空网卡。表现是节点上的 calico-node Pod 是 Running但 Pod 跨节点 ping 不通ip route里也没有对端节点的路由。解决把IP_AUTODETECTION_METHOD显式指定为业务网卡的正则然后重启 calico-node Pod。kubectl set env daemonset/calico-node -n kube-system IP_AUTODETECTION_METHODinterfaceeth.*5.3 现象三Pod 网段和内网网段冲突集群刚搭好就被网管叫停原因默认的 192.168.0.0/16 是内网高频段很多企业的办公网、服务器网段都在这上面。Pod 路由一旦发布出去可能导致物理网络设备学习到错误路由。解决安装前就改成 10.244.0.0/16 或 172.20.0.0/16 这类不冲突的网段并把CALICO_IPV4POOL_CIDR和 kube-apiserver 的--cluster-cidr对齐。如果已经装完才发现冲突要修改 YAML 后逐个节点重启 Calico并把已有 Pod 重建让 IP 重新分配。5.4 现象四重装集群后 Calico 组件反复 CrashLoopBackOff原因上一次部署残留的 calico-node 配置、kube-controllers 的旧配置没有清干净或者 Calico 在节点上写的/var/lib/calico数据还在。新 YAML apply 上去后组件读到旧数据按新逻辑跑直接崩。解决重装前把 kube-system 里旧的 calico 资源删掉并在每个节点清理/var/lib/calico。注意要备份你需要的数据业务数据别误删。kubectl delete daemonset calico-node -n kube-system kubectl delete deployment calico-kube-controllers -n kube-system rm -rf /var/lib/calico清理完后重新 apply 新的 calico.yaml确认组件回到正常状态。5.5 现象五从别的版本迁移calico.yaml 和镜像版本不配套原因图省事直接拿了新版 YAML配旧版镜像。比如用了 v3.20.6 的镜像却套了 v3.33 的 manifests。Calico 的 YAML 里有不少 CRD 字段是随版本演进的旧镜像不认识新字段controller 会报 CRD validation error。解决镜像和 YAML 必须锁定同一个版本线。做交付时把 v3.20.6 的三件套镜像 tar、calico.yaml、版本说明放在同一个交付目录里不接受混用。6. 最后一步把 v3.20.6 做成一个可复现的交付基线到这里镜像导入、YAML 改造、安装验证、踩坑排查都过了一遍。我最后想强调的不是某个命令而是一个交付习惯把 v3.20.6 的镜像和 calico.yaml 当成一个整体单元管理而不是两个独立的东西。我在做离线交付时目录结构一般长这样calico-v3.20.6/ ├── images/ │ └── calico-v3.20.6-images.tar ├── manifests/ │ ├── calico.yaml │ └── calico.yaml.bak-20241201 └── README.mdREADME 里只写三件事镜像 digest 列表、calico.yaml 改过的参数、以及每个参数的适用场景。这样不管过多久哪怕换了人接手只要照着这个目录的 README 走一遍就能原样复现一套 Calico 网络。升级的时候这套基线也方便你对比新旧差异而不是对着十几个 yaml 文件猜哪个是哪个。至于要不要追新版本比如看到热词里提到 calico v3.33 那种后续版本我的看法是如果你现在的集群没有功能缺口v3.20.6 完全够用。版本升级一定要看官方升级文档里的迁移说明特别是 CRD 变化和默认行为变化不要只看镜像 tag 变了就敢直接替换。这行做久了你会发现Calico 这类网络组件的坑大多不在功能上而在版本配套和现场环境适配。把 v3.20.6 的准备流程固定下来镜像、YAML、验证命令一起走每次交付都按同一套来能省掉大量半夜排查的功夫。希望帮到你。本文还有配套的精品资源点击获取