news 2026/9/29 1:39:56

K8s离线部署必看:Calico v3.20.6镜像包与yaml配置详解

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
K8s离线部署必看:Calico v3.20.6镜像包与yaml配置详解

简介:面向 Kubernetes 集群管理员、运维工程师及网络策略配置人员,这份 Calico v3.20.6 版本容器镜像与 calico.yaml 部署文件合集,聚焦 Calico 在 Kubernetes 中的核心组件与部署配置。包含 Node、CNI、kube-controllers、pod2daemon-flexvol 四个 tar 格式镜像,分别负责节点网络与 BGP 路由、Pod 接口设置、网络策略与 IP 管理、配置卷挂载等任务,另附一份完整的 calico.yaml 清单文件,定义了 DaemonSet、CNI 插件、策略控制器及 BGP 参数。这些组件协同工作,可实现跨节点 Pod 通信、路由宣告与基于策略的访问控制。压缩包共 5 个文件,大小约 96.68MB,便于内网离线分发与快速部署。目前已有 1076 人学习下载。通过这一资源,可一次性获得整套组件镜像和统一配置模板,省去手动拉取镜像、编写繁琐 YAML 的步骤,适合在离线或受限网络环境下搭建具备安全隔离和细粒度策略控制的 Kubernetes 集群,无论是新集群初始化还是已有环境补全,都能直接复用。

1. calico v3.20.6 镜像包 + calico.yaml:离线集群网络插件的最省心组合

先给一个反直觉的结论:CNI 部署里翻车最多的,往往不是 BGP 对等关系,也不是 IP 池规划,而是“yaml 里写的镜像 tag 和仓库里实际存的镜像对不上”。尤其是离线环境,网络插件没起来,整个集群的 Pod 调度都会卡在 ContainerCreating,排查一圈发现只是镜像版本漂移,非常不值。

这份资源是 calico v3.20.6 的容器镜像集合加一份配套的 calico.yaml 部署清单。它解决的是 K8s 集群在无法直接访问外网镜像仓库时,怎么把 CNI 网络跑起来的核心问题。适合三类人:做离线交付的实施工程师、自建机房或内网环境的运维、以及想把网络插件版本固定下来避免“追最新追出问题”的集群管理员。版本固定、镜像齐全、yaml 配套,这就是它最实在的价值。

2. 拆解 calico.yaml:五个核心组件与镜像的一一对应

拿到这份资源,第一步不是急着 apply,而是先弄清楚 calico.yaml 里到底声明了什么东西。很多人习惯性kubectl apply -f calico.yaml一把梭,等 Pod 报错了再回头看 yaml,那个时候往往已经绕了弯路。v3.20.6 的这份 yaml 是标准的手动安装形态,里面组件分工很清晰,值得先花十分钟拆一遍。

2.1 calico.yaml 里真正被用到的组件

calico.yaml 不是单个资源,而是一整套声明式部署文件。它包含 CustomResourceDefinition、ConfigMap、DaemonSet、Deployment 和 RBAC 授权对象,拆开看主要有五个角色:

第一个是 calico-node DaemonSet,这是整个 CNI 的核心,yaml 中它以 DaemonSet 形式在每个节点上启动一个 Pod,Pod 内部实际跑了两个进程:Felix 负责路由和网络策略,BIRD 负责 BGP 路由广播。第二个是 calico-kube-controllers Deployment,它是管控面组件,负责同步网络策略、清理 IPAM 租约,没有它 Calico 的策略功能会失灵,但普通路由转发不受影响。第三个是 calico-cni 相关的 CNI 插件二进制与配置,yaml 里通过 initContainer 把二进制写入宿主机的 /opt/cni/bin,再由 ConfigMap 生成 /etc/cni/net.d 配置给 kubelet 调用。第四个是 flexvol 相关的 DaemonSet 组件,用于支持 Calico 的文件系统挂载能力,一般 AlibabaCloud 或自建存储相关场景才会显式用到它。第五个是 CRD 定义,包括 IPPool、FelixConfiguration、KubeControllersConfiguration 等,calicoctl 能查询的这些对象都由它们支撑。

这里有个细节值得注意:v3.20.6 的 yaml 里 Typha 组件默认是注释掉的。Typha 是 Calico 的扩展组件,专门用来在高密度节点集群里降低 API Server 压力,节点数少的时候不启用反而更简洁。很多人在部署时看到 yaml 里有注释的 Deployment 就开始纠结“要不要打开”,实际不需要,默认注释状态就是官方推荐的路数。

2.2 四个镜像与 yaml 内的位置

理解了组件,再对照镜像逐个确认,就不会出现“节点上镜像都导入了,还是起不来”的尴尬。v3.20.6 这套资源里最具辨识度的四个镜像如下:

镜像名对应 yaml 中的角色说明
calico/node:v3.20.6DaemonSet calico-node主进程镜像,内含 Felix 与 BIRD
calico/cni:v3.20.6DaemonSet 的 initContainer提供 CNI 插件二进制,写入宿主机
calico/kube-controllers:v3.20.6Deployment calico-kube-controllers管控面组件,处理策略与 IPAM 租约
calico/pod2daemon-flexvol:v3.20.6DaemonSet 的辅助容器提供 flexvol 挂载能力,部分环境必需

镜像与角色的对应关系,在排查问题时的实际用途非常大。比如 calico-node Pod 起来后一直 CrashLoopBackOff,先看它用的是不是 calico/node 镜像;如果是 calico/cni 镜像被误用在了 node 位置,那必然是启动参数解析失败。类似这种错位,光看日志很难快速定位,对照表格查一遍就清楚了。

2.3 为什么固定 v3.20.6 而不是追 latest

很多人在部署时习惯性拉 latest,理由是“反正能跑就行”。但 CNI 这种底层组件恰恰最怕版本漂移。今天拉到的 latest 和三个月前部署环境的 behavior 可能完全不同,接口名变了、Felix 默认参数变了、IP 池校验逻辑变了,结果就是集群升级的时候网络静默翻车。

v3.20.6 这个版本在 v3.20.x 这条线里属于稳定迭代期,Kubernetes 1.20 到 1.23 这个区间内,它经历了足够多的生产验证。把版本固定在 v3.20.6,意味着两件事:一是离线环境部署时所有组件行为可预期,二是后续排查问题时,社区检索到的经验、参数、issue 都与你手上的版本对齐,不会出现“网上答案是 v3.19 的,yaml 写法对不上”的情况。这也是这类固定版本镜像包比直接拉 latest 更适合生产环境的原因。

3. 离线部署 v3.20.6:镜像搬运、yaml 改址与三处强制检查

离线部署的核心链路就三步:把镜像弄进内网,把 yaml 里的镜像地址改成内网仓库,然后 apply 并观察启动。每一步都有对应的检查点,跳过任何一步,后面都会用异常状态回报你。

3.1 联动镜像导出与导入的完整链路

在有外网访问的机器上,先把四个镜像拉到本地并打包,命名规范一点,避免传到内网后分不清哪个文件对应哪个镜像。常见做法是用镜像名加版本号做文件名,例如 calico_node_v3.20.6.tar:

mkdir -p calico-v3.20.6-images && cd calico-v3.20.6-images for img in calico/cni:v3.20.6 calico/node:v3.20.6 calico/kube-controllers:v3.20.6 calico/pod2daemon-flexvol:v3.20.6; do image_name=$(echo $img | tr '/' '_' | tr ':' '_') docker pull docker.io/$img docker save -o ${image_name}.tar docker.io/$img done

这段脚本的逻辑很直白:循环拉取四个指定版本的镜像,然后按“镜像名_版本号.tar”的规则导出。这里有一个血泪经验值得强调——导出前务必确认 tag 完整,不要只打docker pull不校验。曾经见过有人拉的时候写了calico/node:latest,导出还叫 v3.20.6,传到内网加载后 Pod 起不来,查了半天才发现 tag 被 latest 覆盖了。

内网侧导入时,先确认运行环境用的是 docker 还是 containerd。纯 docker 环境直接用docker load -i导入即可;k8s 1.24 之后默认用 containerd 的环境,需要走ctr命令:

sudo ctr -n=k8s.io images import calico_node_v3.20.6.tar sudo ctr -n=k8s.io images list | grep calico

-n=k8s.io这个参数很关键,它指定了命名空间。containerd 的镜像默认命名空间是default,而 kubelet 拉取镜像时走的是k8s.io命名空间,导入到错误命名空间的话,kubelet 依然会报镜像不存在。

3.2 改 yaml 前先核对的三件事

镜像进入仓库或本地后,下一步是修改 calico.yaml。这里说的“修改”,不是把镜像 tag 改一改就完事,而是三处强制检查:镜像仓库地址、Pod 网段、以及 API Server 参数一致性。

镜像仓库地址的替换是首先做的。如果内网搭了私有仓库,将docker.io/calico/批量替换成内网仓库地址:

sed -i 's#docker.io/calico/#registry.local/calico/#g' calico.yaml grep -E 'image:' calico.yaml | sort | uniq -c

sort | uniq -c的作用是把替换后的镜像地址汇总计数,一眼就能看出全部 image 字段是否都指向了同一个仓库前缀。替换完成后要查看每个 Deployment / DaemonSet 的 image 值,确认没有任何一处漏改。很多“部分节点起得来、部分节点 pull 失败”的问题,根源就是 sed 没替换干净,手工检查比盲目相信正则更可靠。

第二处检查是 Pod 网段。calico.yaml 里默认的CALICO_IPV4POOL_CIDR是 192.168.0.0/16,如果kubeadm init时已经指定了--pod-network-cidr=10.244.0.0/16,两者必须一致。不一致的直接后果是 kubelet 分配的 Pod IP 与 Calico 的 IP 池完全不匹配,Pod 创建后 IP 地址落在池外,路由表乱成一团。

第三处检查是看 kube-apiserver 是否启用了--network-plugin=cni。这个参数在 kubeadm 部署的集群里通常由 kubelet 配置自动带入,但二进制部署环境下很容易漏。集群没网络插件且 kubelet 没开启 CNI 模式时,CNI 插件不会生效,calico-node 就算全 Running,Pod 依然会在容器创建阶段卡住。

3.3 应用与滚动观察

三处检查确认无误后,apply yaml 并观察 Pod 状态:

kubectl apply -f calico.yaml kubectl -n kube-system get pod -l k8s-app=calico-node -o wide kubectl -n kube-system get pod -l k8s-app=calico-kube-controllers -o wide

calico-node 是 DaemonSet,预期状态是每个节点一个 Running Pod;calico-kube-controllers 是 Deployment,预期是 1/1 Running。启动顺序上,calico-node 先起来,因为它是提供 CNI 网络能力的实体;kube-controllers 随后完成策略同步和租约清理。如果你的集群节点有几十个,第一次滚动启动时看到部分节点还在 ContainerCreating 是正常的,calico-node 的 initContainer 需要先把 CNI 二进制写入宿主机再启动主容器,这个过程在批量节点上会有几十秒的窗口期。超过五分钟仍未 Running,直接看对应节点的 Pod 事件,重点查镜像拉取和 CNI 配置挂载两类问题。

4. IP 池与封装选型:四个关键参数改完立即生效

calico.yaml 部署成功只是第一步,真正影响网络表现的是 IP 池和封装模式这几个参数。v3.20.6 的 calico.yaml 里,这些参数大多数以环境变量形式出现在 calico-node DaemonSet 中,少数以 CRD 形式存在。改参数的方式很直接:改 yaml 后重新 apply,DaemonSet 会自动滚动。但有几个典型的理解误区需要先讲清楚。

4.1 修改 CALICO_IPV4POOL_CIDR:一处地址两处同步

CALICO_IPV4POOL_CIDR 是最常被改的参数,但也是最容易改出“只改一半”问题的地方。在 calico.yaml 中,这个 CIDR 同时存在于两个位置:calico-node DaemonSet 的环境变量CALICO_IPV4POOL_CIDR,以及默认的 IPPool CRD 资源里。

只改环境变量、不改 CRD 的话,calico-node 会按新网段执行 IPAM,但 IPPool 对象里记录的仍是旧网段,calicoctl 查询时看到的是旧配置,后续扩容节点或新增 pool 时可能冲突。反过来只改 CRD 不改环境变量,calico-node 启动时会按环境变量重新自动创建 IPPool,手动改的 CRD 被覆盖。正确做法是两处同步修改,确保环境变量与 CRD 一致。改完 apply 后,用以下命令确认 IP 池实际生效范围:

calicoctl get ippool -o wide

看到输出中的 CIDR 与预期一致后,再去创建测试 Pod 验证分配出的 IP 是否落在该网段内。

4.2 IPIPMode:跨网段与同网段怎么选

IPIPMode 控制的是跨节点通信的封装方式:

模式行为适用场景
Always所有跨节点流量都走 IPIP 封装节点间网络不互通,底层路由不可控
CrossSubnet同子网直连,跨子网才封装节点分处多个网段,同网段性能优先
Never不封装,依赖底层路由可达节点网络全互通,或已由底层 BGP 接管

Always 最省心但性能最差,每个数据包多一层 IP 头;Never 性能最好但要求底层交换机或路由已经允许 Pod 网段路由通过。大多数内部网络可控的机房场景,首选 CrossSubnet,它在同机房同网段节点之间走直连,跨网段节点自动加封装,兼顾性能与可用性。v3.20.6 默认为 Always,实际生产环境建议根据集群规模重新评估后再确定。

4.3 MTU 与接口前缀:网卡级翻车点

MTU 不一致是 Pod 间通信时隐晦丢包的高频原因。Calico 创建的 veth 接口默认 MTU 取 0 时,会跟随主网卡自动推导,但推导规则不是直接复制,而是取“主网卡 MTU 减 50”。例如主网卡 MTU 是 1500,veth 接口就是 1450,这 50 字节是为封装层预留的。

主机网卡 MTUCalico veth 推荐 MTU说明
15001450默认以太网环境
90008950数据中心 jumbo frame 环境,需同时调整底层交换机

此参数对应 yaml 中的FELIX_MTUIFACE或MTU相关字段,v3.20.6 里也可在 IPPool 中设置。若集群网络流量大、延迟敏感,建议显式设置 MTU 值,不要依赖自动推导。另外接口前缀默认是cali,多个网络插件共存时,可通过INTERFACE_PREFIX调整以避免接口名冲突,比如改成cali0+。

5. 避坑清单:五个真实翻车场景与排查路径

这一部分是把 v3.20.6 部署过程中最容易踩到的坑集中做一遍复盘,每一条都是真实环境里出现过的现象。按“现象 → 原因 → 解决”的顺序写下来,排查时直接对号入座。

5.1 镜像 tag 换了,节点 Pull 不下来

现象:calico-node Pod 长时间 ImagePullBackOff,kubectl describe pod显示manifest unknown,但仓库里明明有 calico 相关镜像。原因:打包镜像时拉取了 latest 或未固定 tag,离线导入后镜像列表里根本没有带 v3.20.6 标签的镜像。解决:在镜像列表源侧执行docker images | grep calico确认 tag 完整,不存在的 tag 用docker tag补齐后重新 save、传输、load。如果已经是通过 commit 生成的镜像,tag 只是标签,需要重新打标签再导入。

5.2 Pod 网段和节点网段重叠,路由错乱

现象:calico-node 全部 Running,但部分节点上的 Pod 无法跨节点通信,ip route里出现与物理网段冲突的条目。原因:CALICO_IPV4POOL_CIDR 设置的网段与节点主机的物理网段重叠,BGP 路由把物理流量和容器流量混在了一起。解决:在部署前先确认所有节点的/etc/kubernetes/manifests/或 kubelet 配置里的 Pod CIDR,一定不要与主机网段交叠。一旦部署后发现重叠,需要重新安装 calico,修改 CIDR 后卸载老旧 IPPool 资源再重新 apply,没有简单后悔药。

5.3 残留的 flannel 干扰 CNI 初始化

现象:calico-node 正常,但 Pod 创建时仍报 CNI 插件初始化失败,日志里出现 flannel 相关残留。原因:该节点此前部署过 flannel,/etc/cni/net.d下残留了10-flannel.conflist,kubelet 优先读到了它,阻塞了 calico 的 CNI 配置生效。解决:清理旧插件:

rm -f /etc/cni/net.d/10-flannel.conflist rm -rf /opt/cni/bin/flannel* && systemctl restart kubelet

同时确认 flannel 相关的 DaemonSet、NetworkAttachmentDefinition 已删除,避免重复配置 CNI。

5.4 镜像导进去了,kubelet 还是报拉取失败

现象:用docker load导入镜像成功后,calico-node Pod 仍然报image pull failed。原因:节点实际运行环境是 containerd 而非 docker,docker load导入的镜像是写进 docker 自己的存储层的,containerd 完全看不到。解决:用ctr -n=k8s.io images import重新导入,或用crictl images确认 containerd 侧确实能看到镜像。实际工作中,还有部分环境用nerdctl管理 containerd,此时nerdctl --namespace k8s.io load -i也是可行的替代方案。

5.5 只改了 env,没改 IPPool CRD

现象:应用新网段后,calico-node 启动正常,但 calicoctl get ippool 看到的 CIDR 还是旧值,Pod 分配的 IP 与预期不符。原因:改环境变量后 calico-node 会自动创建或者复用已有 IPPool,已有 IPPool 的 CIDR 不会因为环境变量变化而同步变更。解决:同时修改 calico.yaml 中的 env 与 CRD 资源两处,apply 前用grep -n CALICO_IPV4POOL_CIDR calico.yaml确认出现位置,逐个核对全部一致再执行。

6. 部署后的验证:从 calicoctl 状态到镜像安全校验

部署完成不等于交付完成,验证阶段要落到两件事:网络状态是否健康,以及镜像是否可信。

calicoctl 是验证 Calico 状态的直接入口。先看 BGP 节点状态:

calicoctl node status calicoctl get ippool -o yaml calicoctl get workloadEndpoint -o wide

calicoctl node status会列出每个节点的 BGP 会话状态,正常情况下相邻节点间的状态应为 Established。如果某个节点与所有邻居都不建立会话,先检查该节点的 BGP 配置和节点间 179 端口是否被防火墙拦截。IPPool 的 yaml 输出则用于二次确认网段与封装模式,这两个输出与 yaml 配置一致,再进入网络连通性验证。

镜像安全校验是很多人忽略的一步。离线交付的镜像包,传输过程中是否被篡改、导入后 tag 与内容是否对应,都应该做一次显式校验。拿到 tar 包时先算 sha256,与源侧记录比对:

sha256sum calico_node_v3.20.6.tar docker run --rm docker.io/calico/node:v3.20.6 calico-node --version

校验过后,再看镜像的 layer 信息,确认没有额外的奇怪历史层。从容器安全的角度,镜像导入后尽量先在工作节点之外单独跑一次容器做冒烟测试,观察是否正常输出版本,确认镜像本身没有被植入额外指令,这也是保护生产集群的最后一道防线的习惯性动作。

从那以后,我每次接手 K8s 集群,在网络阶段都会强制走一遍“三对表”:镜像 tag 对一遍,calico.yaml 版本对一遍,Pod CIDR 对一遍。这套流程省下的排查时间远超部署时的几分钟,希望帮到你。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/29 1:39:15

Power SI AC阻抗仿真全攻略:从PDN建模到目标阻抗曲线解读

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/29 1:38:56

MBENET驱动详解:ZLG网关虚拟串口通信实战指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/29 1:38:35

SMT产线芯片供应:从6周交期到24小时现货,如何选对供应链

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/29 1:38:19

Stable Diffusion三大核心组件原理与工程实践

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/29 1:38:19

C++构造函数初始化列表:从冒号语法到底层原理与常见坑

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/29 1:37:37

LCD调试方法论:从时序参数到工具使用的完整排查思路

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华