恒美微站
首页
关于我们
建站服务
主题模板
案例展示
资讯中心
联系我们
Kubernetes离线部署Calico v3.20.6:镜像导入与避坑指南
首页
资讯中心
/
Kubernetes离线部署Calico v3.20.6:镜像导入与避坑指南
Kubernetes离线部署Calico v3.20.6:镜像导入与避坑指南
发布时间:2026/10/21 11:58:45
简介本资源面向在 Kubernetes 集群中部署与运维容器网络的工程师提供 Calico v3.20.6 所需的容器镜像与核心部署清单帮助解决离线环境或内网集群无法直接拉取镜像、网络策略难以落地的问题。压缩包共 5 个文件包含 4 个 tar 镜像包与 1 个 yaml 配置文件整体约 96.68MB其中镜像分别对应节点代理、CNI 插件、控制器与 FlexVol 插件yaml 则用于定义 DaemonSet、CNI 配置、策略控制器及 BGP 参数等部署对象。已有 1084 人学习下载适合需要快速搭建 Calico 网络、验证跨节点通信与网络隔离策略的中高级读者。借助这套文件读者可完成镜像导入与清单应用理解各组件在 Pod 网络分配、策略执行和路由通告中的职责并在此基础上调试多租户或安全要求较高场景下的服务通信。1. 从一次 Calico 拉取镜像失败说起为什么我坚持用 v3.20.6 这套离线包凌晨两点某公司内网 Kubernetes 集群节点 NotReadykubectl get pods -n kube-system 里 calico-node 清一色 ImagePullBackOff。节点上 docker images 空空如也registry 又在内网隔离区外网拉取根本走不通。这种场景我一年能碰上三四回每次都是同一套解法提前备好 calico-v3.20.6 的容器镜像包和 calico.yaml 清单离线导入、按序部署。Calico 是 Kubernetes 里最常见的 CNI 插件之一负责 Pod 网络互通和 NetworkPolicy 落地装不好轻则节点 NotReady重则整个集群网络瘫痪。这套资源适合两类人一是内网隔离环境里搭 K8s 的运维二是想在生产集群升级前先在测试环境复现一遍 Calico 部署流程的开发者。下面把我自己装这套环境的完整过程拆开写版本、参数、踩坑点都落到具体命令上。2. 装前把环境列清楚版本、节点与镜像清单2.1 版本选择为什么锁定 v3.20.6 而不是最新版Calico 的版本和 Kubernetes 版本之间有兼容矩阵不是越新越好。v3.20.6 属于 v3.20 系列的一个补丁版本这个系列对 Kubernetes 1.21 到 1.24 的支持比较稳很多还在跑 1.22、1.23 的存量集群直接用它最省心。我一般不会在生产集群上追最新大版本原因有两个一是新版本对 iptables 模式、eBPF 数据面的默认行为可能变存量 NetworkPolicy 规则容易出玄学问题二是离线镜像包和 yaml 清单必须版本对齐混用 v3.20 的 yaml 配 v3.21 的镜像大概率在 calico-node 启动阶段报 CRD 字段不识别。选版本时先确认三件事集群的 K8s 版本、节点操作系统内核版本、以及是否用了 eBPF 模式。v3.20.6 默认走 iptables 模式内核要求 3.10 以上即可CentOS 7 的 3.10 内核也能跑。如果你的集群是 1.25 以上那这套 v3.20.6 就不合适了得换更新的系列。这一步别偷懒版本对不上后面全是白工。2.2 节点环境对照表装之前把每个节点的信息列成表比装到一半才发现内核不对要省事得多。下面是我一般会确认的字段检查项要求查看命令K8s 版本1.21 ~ 1.24kubectl version --short内核版本 3.10uname -r容器运行时Docker 或 containerddocker version/ctr version节点主机名唯一且已加入集群kubectl get nodes网卡名与 calico.yaml 中配置一致ip addr防火墙放行 IPIP 协议或已关闭iptables -LSELinux建议 permissivegetenforce这张表里最容易翻车的是网卡名和防火墙。calico.yaml 里有个IP_AUTODETECTION_METHOD环境变量默认是first-found多网卡机器上它可能选到一张业务网卡导致 Pod 跨节点不通。我一般会显式指定成interfaceeth0或者can-reach某网关IP把选择权抓在自己手里。2.3 镜像与清单文件清单这套资源里实际要用到的文件就两类容器镜像包和 calico.yaml。镜像包通常是一个 tar 归档里面包含 calico/node、calico/cni、calico/kube-controllers 这几个核心镜像版本号都是 v3.20.6。calico.yaml 是部署清单里面定义了 DaemonSet、Deployment、ServiceAccount、CRD 等一堆资源。拿到资源后先核对镜像 tag用下面这条命令看 tar 包里到底有哪些镜像# 查看镜像包内容不实际导入 tar -tf calico-v3.20.6-images.tar | head -20 # 或者已经导入后查看本地镜像 docker images | grep calico逻辑说明tar -tf只列出归档内容不解压适合导入前确认包是否完整docker images | grep calico用于导入后核对 tag 是否和 yaml 里写的一致。参数上没什么花头关键是 tag 必须精确匹配v3.20.6和v3.20.6-amd64在 yaml 里就是两个不同的字符串对不上就是 ImagePullBackOff。3. 导入镜像与部署 calico.yaml两条命令背后的参数取舍3.1 镜像导入docker load 与 ctr 的差别镜像导入这一步用 Docker 和用 containerd 的命令完全不同先确认你的运行时是哪个。K8s 1.24 之后很多集群默认用 containerddocker load就不好使了。Docker 运行时的导入方式# 在每个节点上执行导入 calico 镜像 docker load -i calico-v3.20.6-images.tar # 导入后确认 docker images | grep calicocontainerd 运行时的导入方式# containerd 用 ctr 导入注意 -n 指定 namespace ctr -n k8s.io images import calico-v3.20.6-images.tar # 确认导入结果 ctr -n k8s.io images ls | grep calico逻辑说明docker load -i的-i指定输入文件导入后镜像进入 Docker 的本地存储。containerd 这边关键是-n k8s.ioK8s 用的 namespace 就是k8s.io不加这个参数镜像导进去 K8s 也看不见这是最常见的坑之一。导入操作要在每个可能跑 calico-node 的节点上执行因为 DaemonSet 会在所有节点起 Pod镜像没提前铺好就会拉取失败。3.2 calico.yaml 关键参数逐项改calico.yaml 拿到手不能直接 apply得先改几个地方。下面是我一般会动的参数# calico.yaml 中需要关注的环境变量片段 - name: CALICO_IPV4POOL_CIDR value: 10.244.0.0/16 # 必须和 kubeadm init 时的 pod-network-cidr 一致 - name: IP_AUTODETECTION_METHOD value: interfaceeth0 # 多网卡环境必须显式指定 - name: CALICO_IPV4POOL_IPIP value: Always # 跨网段通信建议开启 IPIP逻辑说明CALICO_IPV4POOL_CIDR是最容易出错的一项它必须和集群初始化时kubeadm init --pod-network-cidr指定的网段完全一致不一致的话 Pod 拿不到 IP。IP_AUTODETECTION_METHOD默认first-found在多网卡机器上会乱选改成interfaceeth0把网卡钉死。CALICO_IPV4POOL_IPIP设成Always表示所有流量走 IPIP 隧道封装跨网段节点通信更稳代价是有一点封装开销同网段集群可以设Never省掉这层开销。改完 yaml 后用kubectl apply -f calico.yaml部署。如果集群里已经有旧版本 Calico先kubectl delete -f 旧yaml再 apply 新的别直接覆盖CRD 字段冲突会报错。3.3 部署顺序与等待策略apply 之后不要立刻去查 PodCalico 的启动有依赖顺序先是 CRD 和 ServiceAccount 创建然后 calico-node DaemonSet 起 Pod最后 kube-controllers 才就绪。我一般用下面这条命令盯着# 持续观察 calico 相关 Pod 状态直到全部 Running kubectl get pods -n kube-system -l k8s-appcalico-node -w # 另开一个窗口看 kube-controllers kubectl get pods -n kube-system -l k8s-appcalico-kube-controllers -w逻辑说明-w是 watch 模式状态变化会实时刷新比反复敲 get 省事。正常情况下 calico-node 会在 1 到 2 分钟内全部 Running如果超过 5 分钟还有 Pod 卡在 Init 或 CrashLoopBackOff就得去看日志了。kubectl logs -n kube-system pod名 -c calico-node是第一个要看的报错信息基本都在里面。4. 避坑与排查五条我踩过的 Calico 部署坑4.1 坑一节点 NotReadycalico-node 一直 Init现象kubectl get nodes显示节点 NotReadycalico-node Pod 卡在 Init:0/1 或者 PodInitializing。原因最常见的是镜像没导入到该节点或者导入到了错误的 namespace。containerd 环境下用ctr images import忘了加-n k8s.io镜像进了 default namespaceK8s 在 k8s.io 里找不到。解决在该节点执行ctr -n k8s.io images ls | grep calico确认镜像存在。不存在就重新导入命令带上-n k8s.io。Docker 环境则用docker images确认。4.2 坑二Pod 跨节点不通同节点正常现象同一节点上的 Pod 互相能 ping 通跨节点就不通NetworkPolicy 也没生效。原因IP_AUTODETECTION_METHOD选错了网卡。多网卡机器上默认first-found可能选到一张没有跨节点路由的网卡IPIP 隧道建不起来。解决把IP_AUTODETECTION_METHOD改成interfaceeth0换成你实际的网卡名重新 apply。改完可以进 calico-node Pod 用ip route看路由表确认隧道网卡正确。4.3 坑三CALICO_IPV4POOL_CIDR 与集群网段不一致现象calico-node 起来了但新创建的 Pod 一直 ContainerCreatingdescribe 显示 failed to allocate IP。原因calico.yaml 里的CALICO_IPV4POOL_CIDR和kubeadm init --pod-network-cidr指定的网段不一样IPAM 分配不到地址。解决kubectl get pod -n kube-system calico-node-pod -o yaml | grep CIDR看实际生效值和集群初始化参数对齐后重新 apply。已经分配出去的旧 IP 池可以用calicoctl ipam show检查。4.4 坑四CRD 字段冲突导致 apply 报错现象kubectl apply -f calico.yaml报field is immutable或 CRD 版本不匹配。原因集群里残留了旧版本 Calico 的 CRD新 yaml 里的字段定义和旧 CRD 冲突。解决先kubectl delete -f 旧版本calico.yaml等 Pod 清理干净再 apply 新版本。如果 CRD 删不掉用kubectl patch crd 名称 -p {metadata:{finalizers:[]}} --typemerge清掉 finalizer 再删。4.5 坑五内核模块未加载IPIP 隧道起不来现象calico-node 日志报Failed to create tunnel或ipip: Operation not supported。原因节点内核没加载ipip模块或者内核版本太低不支持。解决modprobe ipip手动加载然后lsmod | grep ipip确认。要持久化就写进/etc/modules-load.d/calico.conf。内核低于 3.10 的节点建议升级内核否则 IPIP 模式跑不起来。5. 装完怎么验证从节点状态到跨节点连通性部署完不是看到 Running 就完事了得实际验证网络通不通。我一般按下面这个顺序走一遍每一步都有明确的通过标准。第一步确认所有节点 Readykubectl get nodes -o wide输出里 STATUS 列全是 Ready说明 calico-node 已经在每个节点正常工作。如果有 NotReady回到第 4 章排查。第二步确认 calico-node 和 kube-controllers 全部 Runningkubectl get pods -n kube-system | grep calico期望看到 calico-node 的 Pod 数量等于节点数calico-kube-controllers 一个 Running。数量对不上说明 DaemonSet 没调度到某些节点检查节点是否有污点。第三步验证 Pod 跨节点通信。这是最关键的一步起两个测试 Pod 分别调度到不同节点# 创建测试 Pod用 nodeName 强制调度到指定节点 kubectl run test-pod-1 --imagebusybox --overrides{spec:{nodeName:node-1}} -- sleep 3600 kubectl run test-pod-2 --imagebusybox --overrides{spec:{nodeName:node-2}} -- sleep 3600 # 拿到 test-pod-2 的 IP kubectl get pod test-pod-2 -o wide # 从 test-pod-1 里 ping test-pod-2 的 IP kubectl exec -it test-pod-1 -- ping -c 3 test-pod-2的IP逻辑说明--overrides里的nodeName强制把 Pod 调度到指定节点避免调度器把两个 Pod 放到同一节点导致测不出跨节点通信。ping 通说明 IPIP 隧道和路由都正常。如果 ping 不通先kubectl exec进 Pod 看ip route再回节点上看ip route和 iptables 规则。第四步验证 NetworkPolicy 生效。建一个默认拒绝的 policy确认未放行的流量被阻断# 应用一个默认拒绝入站的 NetworkPolicy cat EOF | kubectl apply -f - apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: default-deny-ingress namespace: default spec: podSelector: {} policyTypes: - Ingress EOF # 再次从 test-pod-1 ping test-pod-2应该超时 kubectl exec -it test-pod-1 -- ping -c 3 -W 2 test-pod-2的IP逻辑说明podSelector: {}表示选中 namespace 下所有 PodpolicyTypes: Ingress表示只控制入站。应用后 ping 应该超时说明 policy 生效。验证完记得删掉这个 policy不然会影响后续测试kubectl delete networkpolicy default-deny-ingress。第五步清理测试资源kubectl delete pod test-pod-1 test-pod-2这套验证流程走完基本能确认 Calico v3.20.6 在集群里是真正跑通了而不是表面 Running。从那以后我每次装完 Calico不管节点状态多好看都强制把跨节点 ping 和 NetworkPolicy 这两步走一遍因为 Running 的 Pod 不代表网络真的通这个教训是某次生产事故换来的。希望帮到你。本文还有配套的精品资源点击获取