Calico v3.20.6内网部署全攻略:版本匹配、镜像导入与网络配置

📅 发布时间:2026/10/15 20:14:31
Calico v3.20.6内网部署全攻略:版本匹配、镜像导入与网络配置
简介Calico 是 Kubernetes 生态中主流的容器网络与网络策略开源方案。这份资源面向集群管理员与运维工程师针对 v3.20.6 稳定版本解决离线或内网环境下镜像获取不便、组件配置分散的问题。RAR 压缩包内共 5 个文件包含 4 个组件镜像包和 1 个核心部署配置整体约 96.68MB。镜像覆盖节点代理、CNI 插件、策略控制器与卷挂载扩展四类模块节点代理负责本地路由与策略执行CNI 插件在 Pod 创建时设置网络接口控制器监听 Kubernetes API 并同步策略卷插件保证配置正确挂载到目标 Pod。配置文件则将上述组件串联为完整部署清单集中声明守护进程集、边界网关协议参数、策略对象等关键项管理员可通过命令行一次性集成到集群无需手动调整镜像版本。已有 1083 人学习适合需要快速初始化生产集群网络、维护多租户隔离策略或进行标准化交付的中高级运维人员。整体结构清晰开箱即用能显著降低 Calico 部署排错成本同时对理解组件协作与网络策略下发机制也有直接帮助。1. 为什么要盯住 calico v3.20.6版本锁定与镜像配套一起解决Kubernetes 集群网络是玄学重灾区。去年我接手一个 K8s 1.24 集群跨节点 Pod 间歇性不通查到最后是 CNI 插件 calico 的 yaml 和镜像 tag 对不上——calico.yaml 里写着 v3.20.6节点镜像却是旧的 v3.20.2Felix 和 CNI 插件跨 patch 版本不兼容路由表偶发错乱。节点少时根本看不出来扩到 30 台就开始翻车。今天要装的是 calico v3.20.6 容器镜像配套 calico.yaml 文件这两样必须一起用镜像 tag 与 yaml 中 image 字段严格对齐。适合正用 kubeadm 搭 K8s 1.221.26 集群、卡在内网镜像拉取和 calico 部署参数上的开发者。装好它Pod 网络和 NetworkPolicy 才算真正落地。2. 部署前准备版本兼容表、镜像清单与私有仓库三件事2.1 先确定集群能不能用 v3.20.6Calico 每个版本都有 K8s 大版本兼容区间。v3.20 系列官方测试覆盖 K8s 1.201.26 这一段我实际线上跑得最稳的是 1.24 和 1.25。拿 v3.20.6 来说如果集群 K8s 版本低于 1.20建议直接放弃这个版本回头找 v3.19 或更早如果高于 1.26也不要硬上 v3.20换 v3.22 以上省心。版本不匹配的坑很隐蔽calico 能装上但 CRD schema 不兼容apiVersion 解析报错或者 Felix 某些特性识别不了日志里看不出来只有路由表行为异常。部署前用下面命令把 K8s 版本和 calico 二进制的版本都确认一遍kubelet --version kubectl version --short | grep server输出里 server 版本如果落在 1.201.26那 v3.20.6 可以继续走。这里还要提醒一句别在已有 calico 的集群上直接覆盖 apply 新版本 yaml尤其从 v3.10 这种老版本跨度升级时CRD 结构变化很大旧资源不会自动迁移路由规则会乱套。2.2 镜像清单cni、node、kube-controllers、flexvol 一个不能少资源包里镜像统一是 docker.io/calico 命名空间下的 v3.20.6 tag。核心四个镜像名角色是否必须calico/cni:v3.20.6Pod 网卡创建、IP 分配必须calico/node:v3.20.6每节点常驻 Felix 与 BIRD 进程必须calico/kube-controllers:v3.20.6策略同步、IP 池生命周期必须calico/pod2daemon-flexvol:v3.20.6FlexVolume 挂载兼容默认 yaml 引用calico/typha:v3.20.6高并发降低 apiserver 压力可选默认 calico.yaml 不启用 typha所以一般导入前四个镜像就够。资源包里的镜像压缩文件解压后可以先在任意一台节点上查看清单tar -tf calico-images.tar | head -20确认是否存在 cni、node、kube-controllers、flexvol 这几个 tag。缺了哪个后面部署时就会卡在 ErrImagePull。老手习惯是把这步当成强制检查因为镜像打包环节漏 tag 太常见了。2.3 私有仓库开通containerd 的 hosts.toml 写法K8s 1.24 以上默认运行时是 containerd没有 docker。我的做法是先在内网起一个 registry把镜像推到私有仓库再让节点从这个仓库拉取。containerd 1.7 以上推荐用 hosts.toml 方式配置在 /etc/containerd/certs.d/ 下按仓库域名建目录mkdir -p /etc/containerd/certs.d/registry.local:5000 cat /etc/containerd/certs.d/registry.local:5000/hosts.toml EOF server http://registry.local:5000 [host.http://registry.local:5000] capabilities [pull, resolve] skip_verify true EOF systemctl restart containerd这里 server 写的是 http因为内网仓库多数没配 TLS。capabilities 只给了 pull 和 resolve没给 push意思是节点只从这个仓库拉镜像不做推送。skip_verify 只建议在内网可信环境开公网仓库别这么干。改完 hosts.toml 有个检查技巧在任意节点执行 crictl pull registry.local:5000/calico/cni:v3.20.6能成功拉下来就说明 containerd 配置没问题。2.4 两种导入姿势docker load 与 ctr -n k8s.io如果集群节点上还保留着 docker很多人习惯先 docker load 再推送私有仓库docker load -i calico-images.tar docker tag docker.io/calico/cni:v3.20.6 registry.local:5000/calico/cni:v3.20.6 docker push registry.local:5000/calico/cni:v3.20.6但注意docker load 导入的镜像是进 docker 的 moby 命名空间containerd 的 k8s.io 命名空间看不到它。纯粹只有 containerd 的节点要用 ctr 导入ctr -n k8s.io images import calico-images.tar ctr -n k8s.io images list | grep calico参数 -n k8s.io 最关键不加这个命名空间导入的镜像 CRI 还是拉不到。资源包如果只给 tar 包这两种方式按节点环境二选一然后统一推进私有仓库calico.yaml 里的镜像地址全部改成 registry.local:5000/calico/xxx:v3.20.6。2.5 解压落位calico.yaml 先检查资源数量资源包里的 calico.yaml 是整理好的完整 manifest包含 Namespace、ConfigMap、DaemonSet、Deployment、ServiceAccount、CRD 等。拿到手先解压并确认 yaml 的合法性tar -xf calico-v3.20.6-bundle.tar kubectl apply --dry-runclient -f calico.yamldry-run 只做客户端校验不会真的写资源。输出没有 error 才继续。这里有个经验v3.20.6 的 calico.yaml 里 CRD 数量在 10 个左右资源总数大概 30如果 apply 时报no matches for kind多半是 yaml 被截断或者版本被改过直接换原始文件重来。3. 部署 calico.yaml改网段、换镜像、apply 三步走3.1 calico.yaml 的结构先看一遍Calico 的 manifest 是一整个大文件里面 ClusterRole、DaemonSet、Deployment 都在一起。v3.20.6 的 calico.yaml 里calico-node 是一个 DaemonSetcalico-kube-controllers 是一个 Deployment。核心配置在 kube-system 命名空间下的 calico-config 这个 ConfigMap 里。打开文件先搜 envgrep -n name: CALICO_\|name: FELIX_\|name: IP_AUTODETECTION calico.yaml | head -30重点看 CALICO_IPV4POOL_CIDR、CALICO_NETWORKING_BACKEND、IP_AUTODETECTION_METHOD 这三个环境变量的当前值。默认模板里 IP 池写的是 192.168.0.0/16网络后端是 vxlanIP 探测方式是 first-found。这三个参数几乎决定了一个集群网络能否跑通下面一一说明改法。3.2 IP 池默认 192.168.0.0/16 必须先检查Calico 默认 Pod 网段是 192.168.0.0/16这个网段和大量云厂商 VPC 内网、公司办公网冲突。冲突的后果是 Pod 出口流量在节点上就被静态路由劫走跨网段连接超时而且很难排查因为 calico 组件全部 Running。改法是直接编辑 calico.yaml把 CALICO_IPV4POOL_CIDR 的值替换成你规划好的网段比如 10.244.0.0/16sed -i s#192.168.0.0/16#10.244.0.0/16# calico.yaml grep -n CALICO_IPV4POOL_CIDR calico.yamlIP 池选择建议避开宿主机网段、Service CIDR默认 10.96.0.0/12、云 VPC 主网段。规划一个大网段比如 10.244.0.0/16后续扩节点不用改。这个值一旦集群跑起来就基本不能改想改只能删掉旧 IPPool 再重建影响面很大。所以部署前宁可花十分钟想清楚。3.3 网卡探测策略first-found 的不确定性IP_AUTODETECTION_METHOD 默认是 first-found意思是 Felix 启动时拿节点上第一个非 loopback 网卡的 IP 作为本机 IP。这个策略在双网卡节点上是坑管理网卡和业务网卡顺序不稳定跨节点 VXLAN 隧道可能建在错误的 IP 上。我的做法是改成 interface 匹配规则只选业务网卡前缀sed -i s#value: first-found#value: interfaceeth.*# calico.yaml如果网卡名不规则也可以用 can-reach 方式让 calico 探测能到达某个网关的网卡- name: IP_AUTODETECTION_METHOD value: can-reach172.16.0.1can-reach 的值填节点默认网关探测到能通的那张网卡就是业务网卡。这个参数对多网卡环境非常关键选错网卡时 Calico 组件也能启动但 Pod 跨节点不通看 calico-node 日志会看到 node 的 IP 和实际业务网段对不上。3.4 VXLAN 还是 BGPv3.20.6 的默认值和取舍v3.20.6 的 calico.yaml 默认 CALICO_NETWORKING_BACKEND 是 vxlan。VXLAN 模式下跨子网 Pod 流量走 UDP 封装对底层网络设备没有特殊要求三层可达就能跑。BGP 模式值设为 bird则依赖 BGP 协议同子网走直连路由性能更好但对网络设备和节点路由表有侵入性。选型建议如下场景推荐后端原因云 VPC、隔离网络VXLAN无需网络设备配合物理机房、纯二层BGP延迟低直连转发混合多子网VXLAN cross-subnet同子网直连跨子网封装Calico v3.20.6 的 VXLAN 还有 cross-subnet 模式同子网走二层直连、跨子网才封装兼顾性能与兼容性。配置方式是在 IPPool 的 yaml 里设置apiVersion: projectcalico.org/v3 kind: IPPool metadata: name: default-ipv4-ippool spec: vxlanMode: CrossSubnet默认模板不用动 CALICO_IPV4POOL_IPIP保持 Never 即可。IPIP 和 VXLAN 混用是新手常犯的错误两个后端同时开会导致路由优先级混乱。3.5 批量替换镜像地址sed 一次改完镜像推进私有仓库后calico.yaml 里所有镜像地址要替换。资源包里镜像原始地址是 docker.io/calico/xxx:v3.20.6用 sed 批量替换sed -i s#docker.io/calico#registry.local:5000/calico#g calico.yaml grep -n image: calico.yaml | head -20替换后确认 imagePullPolicy。内网私有仓库场景建议把 Always 改成 IfNotPresent避免节点每次重建 Pod 都去仓库校验减少启动延迟sed -i s#imagePullPolicy: Always#imagePullPolicy: IfNotPresent#g calico.yaml这里有个细节如果私有仓库的镜像 tag 是对的IfNotPresent 完全够用镜像 tag 是 latest 才必须用 Always而 calico v3.20.6 这种固定版本 tag 没必要 Always。3.6 apply 和回滚准备工作完成后正式部署kubectl apply -f calico.yaml kubectl get pods -n kube-system | grep calico观察几分钟calico-node 的 pod 应该逐渐变成 Running 和 Ready。如果发现哪个组件状态不对先别急着删看日志定位kubectl logs -n kube-system calico-node-xxxxx -c calico-node --tail100如果要回滚资源包场景下最稳妥的做法是清理全部 calico 资源恢复干净状态kubectl delete -f calico.yaml kubectl delete crd felixconfigurations.crd.projectcalico.org bgpconfigurations.crd.projectcalico.org kubectl delete crd ippools.crd.projectcalico.org networkpolicies.crd.projectcalico.orgcrd 删除这步很多人会漏。calico.yaml 自带的 CRD 如果不删再次 apply 旧版本 yaml 时结构不一致会报错。完整删完再 apply 新版本相当于后悔药重装之前把残骸扫干净避免旧 CRD 污染新配置。4. 启动后的配置检查网络策略、MTU 与 Typha 取舍4.1 启动检查三件套calico 部署完不是识别 Ready 就算完我习惯做三件事看进程、看路由、看 felix 状态。先看进程kubectl get pods -n kube-system -l k8s-appcalico-node -o wide然后进到任意一个 calico-node 里看 BIRD 路由信息。v3.20.6 的 VXLAN 模式可以用kubectl exec -n kube-system calico-node-xxxxx -- ip route | grep 10.244路由表里能看到指向其他节点的 vxlan 路由说明隧道已经建立。再看 felix 日志是否有 warning 级以上的异常kubectl logs -n kube-system calico-node-xxxxx -c calico-node | grep -i error\|warn这三步都过网络面才算真正起来。如果路由表里只有本机 Pod 网段没有跨节点路由多半是 IP 探测选错了网卡回头改 IP_AUTODETECTION_METHOD。4.2 网络策略Calico NetworkPolicy 的独立命名空间v3.20.6 的 calico.yaml 自带 projectcalico.org/v3 的 CRD和 K8s 官方的 networking.k8s.io/v1 NetworkPolicy 是两套东西可以同时存在。Calico 的 NetworkPolicy 字段更细支持动作和协议级别规则。默认命名空间没有策略时流量是全部放行的。但很多人在装好 calico 后立刻套默认拒绝策略误伤 kube-system。正确的做法是先建一个只作用于业务命名空间的 baseline 策略例如放行所有目标端口为 80 的入站流量apiVersion: projectcalico.org/v3 kind: NetworkPolicy metadata: name: allow-http namespace: shop spec: selector: app web ingress: - action: Allow protocol: TCP destination: ports: - 80这个策略只作用于 shop 命名空间里带 appweb 标签的 Pod不会碰 kube-system。我一般把这类策略和 calico.yaml 分开存放单独 apply避免混在大 bundle 里导致后续维护困难。4.3 MTU 设置VXLAN 的 50 字节开销怎么算Calico 在 VXLAN 模式下宿主机网卡 MTU 1500 时Pod 网卡 MTU 应该减掉 VXLAN 封装头 50 字节也就是 1450。v3.20.6 默认 calico.yaml 里 FELIX_MTU 如果是 0 表示自动但自动探测在多网卡或 Overlay 网络上不一定准。我的做法是指定明确值sed -i s#name: FELIX_MTU#name: FELIX_MTU\n value: 1450# calico.yamlMTU 不对的现象很典型小包通大包不通。ping 加上 -s 1500 就丢包普通 ping 正常。遇到这种情况先查 Pod 内和宿主机的 MTU 差值是不是 50。如果底层网络本身是 9000 jumbo frame那就把 FELIX_MTU 设成 8950规则不变永远是底层 MTU 减 50。4.4 Typha 要不要开v3.20.6 高密度集群的取舍默认 calico.yaml 不部署 typha所以大多数场景下不用动。但如果一个集群 node 数量超过 50或者 apiserver 压力已经偏高calico-node 大量连接 apiserver 监控资源会造成明显负载。这时候建议补一个 typha Deployment。默认 yaml 里 typha 相关配置是注释状态资源包如果有单独的 typha.yaml 可以单独 apply。部署后要把 calico-node 的启动参数加上 --typha-socket-filename并在白名单里去掉只剩 typha。没有 typha 的集群不要强行补配置不到位反而会让 node 找不到 typha 而重启。50 节点以内默认不加 typha 是合理的。5. 避坑与排查5 个真实踩坑记录从现象到修复5.1 docker load 了但 containerd 拉不到镜像现象节点上有 docker执行 docker load 成功但 kubectl 创建 calico pod 时一直 ErrImagePull事件里报 manifest unknown 或 image not found。原因docker load 把镜像导入到了 moby 命名空间而 kubelet 通过 CRI 调用 containerd 的是 k8s.io 命名空间。两边在同一个 containerd 进程里但命名空间隔离互相看不见。解决改用 ctr -n k8s.io images import 重新导入或者绕开本地导入直接把镜像推到私有仓库让 containerd 按仓库地址拉取。从那以后我要求装 calico 前先统一镜像来源不混用导入方式。5.2 双网卡节点跨 Pod 不通现象calico 组件全部 Running同节点 Pod 互通跨节点 Pod 不通ping 超时。原因节点两张网卡IP_AUTODETECTION_METHOD 的 first-found 选到了管理网卡的 IPVXLAN 隧道建立在管理网段上业务网卡收不到封装包。解决把 IP_AUTODETECTION_METHOD 改成 interfaceeth.* 或 can-reach172.16.0.1 形式重建 calico-node。日志里确认 node IP 属于业务网段后才能继续。5.3 网络策略误伤 CoreDNS现象业务 Pod 创建成功但域名解析全部超时nslookup 无响应calico 组件无异常。原因手动 apply 了 default deny 策略没放行 kube-system 命名空间CoreDNS 的流量被策略拦截。解决检查当前生效的 NetworkPolicykubectl get networkpolicies -A kubectl get networkpolicy -n kube-system为 kube-system 补一条放行策略或者在默认拒绝策略里显式放行 53 端口 UDP/TCP。这是把策略和网络插件混在一起最常见的事故。5.4 新旧 IP 池并存导致路由冲突现象某次调整 Pod 网段后新 Pod 分配到新网段但部分节点访问旧网段 Pod 路由跳转异常网络时通时断。原因旧 IPPool 的 CRD 没有删除Calico 同时保留新旧两个池Felix 生成了冲突的路由规则。解决删除旧 IPPool 后重建 calico-node。kubectl get ippools.crd.projectcalico.org kubectl delete ippools.crd.projectcalico.org old-pool-name删除 IP 池前确认池内没有运行中的 Pod不然这些 Pod 会失联。更稳的做法是先把旧池的 Pod 驱逐到新池再执行删除。5.5 calico-node CrashLoopBackOff先看 calico-config现象calico-node 启动即退出反复重启日志报 Failed to create Calico client找不到 calico-config 或 cluster information 无法获取。原因calico.yaml 没有完整 apply或者之前清理时把 ConfigMap 删了calico-node 启动时拿不到集群配置。解决不要只 apply DaemonSet把完整 calico.yaml 一次性 apply确认 ConfigMap 存在kubectl get configmap -n kube-system calico-config如果 ConfigMap 存在但内容异常检查 data 字段里 etcd_endpoints 或 kubernetes_service_host 是否为空。v3.20.6 默认走 kubernetes 模式不需要 etcd但配置缺失或格式错误会直接启动失败。6. 装完怎么验证跑通从 Pod 状态到跨节点互访装完 calico 不能只看组件状态要实际打流量验证。我会按下面顺序走一遍整个流程十分钟内搞定。先确认节点和组件kubectl get nodes -o wide kubectl get pods -n kube-system -l k8s-appcalico-node -o wide所有 node 应该 Ready而且每个节点都有一个 calico-node 在 Running。注意查看 calico-node 所在节点分布确保没有某个节点漏了 pod。然后创建两个测试 Pod分别调度到不同节点。用如下命令确认节点分布kubectl run test-a --imagebusybox -- sleep 3600 kubectl get pods -o wide如果两个 Pod 落在同一节点用节点亲和或 cordon 处理确保它们在不同节点上。跨节点测试才是 Calico 真正生效的标志。进入其中一个 Podping 另一个 Pod 的 IP再从另一端回 pingkubectl exec -it test-a -- ping -c 5 test-b-ip kubectl exec -it test-b -- ping -c 5 test-a-ip两边都通说明 VXLAN 隧道和路由表工作正常。接着验证 Service 网络。创建一个 Deployment 和 Service从同命名空间另一个 Pod 访问 ClusterIPkubectl create deployment nginx --imagenginx kubectl expose deployment nginx --port 80 kubectl run curl-test --imagecurlimages/curl -- sleep 3600 kubectl exec -it curl-test -- curl -I http://cluster-ip能返回 HTTP 200说明 kube-proxy 和 calico 的配合没有问题。最后验证网络策略确实生效写一条禁止某 Pod 访问的规则并实际测试通断apiVersion: projectcalico.org/v3 kind: NetworkPolicy metadata: name: deny-from-test-a spec: selector: app nginx ingress: - action: Deny source: selector: run test-a把这条策略 apply 后再从 test-a curl 一次 nginx 服务应该超时。验证完把测试资源清理掉kubectl delete pod test-a test-b curl-test kubectl delete deployment nginx kubectl delete service nginx kubectl delete networkpolicy deny-from-test-a从那以后每装完一套 calico我都强制把这一套流程走一遍组件检查、跨节点互通、ClusterIP 访问、策略拦截缺一不可。只有这四步全过才算真正跑通而不是停留在 Pod Running 的假象里。希望这套验证流程也能帮你少走弯路。本文还有配套的精品资源点击获取