Calico v3.20.6离线部署实战:YAML+镜像搞定Kubernetes网络

📅 发布时间:2026/10/15 20:14:31
Calico v3.20.6离线部署实战:YAML+镜像搞定Kubernetes网络
简介面向 Kubernetes 集群管理员和网络运维人员的 Calico v3.20.6 部署资源包解决容器网络配置、跨节点路由与网络策略控制问题。压缩包内含 5 个文件四个镜像 tar 包分别对应 Calico Node、CNI 插件、控制器及 FlexVol 配置卷插件另附核心配置文件 calico.yaml涵盖 DaemonSet、CNI、BGP 及策略控制器等定义可直接通过 kubectl apply 应用到集群资源包体积约 96.68MB便于离线环境使用已有 1083 人学习下载。其中 node 镜像负责 IP 分配与 BGP 路由cni 镜像负责 Pod 网络接口创建controllers 处理策略同步flexvol 实现配置挂载配合 yaml 可迅速搭建具备细粒度安全隔离的多租户集群网络适合需要离线部署或深入理解 Calico 组件协作方式的 K8s 实践者。1. calico-v3.20.6 离线救急一份 YAML 加一堆镜像能解决什么在一台无法访问外网的服务器上装 Kubernetes最打脸的时刻往往不是 kubelet 报错而是 CoreDNS 起不来、Pod 一直 Pending——原因只有一个没有 CNI 插件。calico-v3.20.6 的离线部署资源把全套运行镜像和一份 calico.yaml 合在一起正好卡在这个痛点上内网直接加载镜像、apply 清单全程不需要从公网仓库拉一个字节。适合离线交付、私有机房或实验环境里的人。只要集群已经初始化好只缺一个既能跑通 Pod 通信又能下发 NetworkPolicy 的网络插件下面这些步骤可以照着走。镜像怎么灌进去、calico.yaml 要改哪几个参数、改了之后为什么跨节点还是不通往下看。2. 拆开 v3.20.6镜像清单、组件职责与模式选型2.1 一组镜像和一份完整清单这个资源解压后核心是两部分镜像压缩包和 calico.yaml。镜像压缩包里是 Calico 在 v3.20.6 版本下的完整镜像集calico.yaml 则是官方整合好的多文档清单里面把 Namespace、RBAC、CRD、ConfigMap、DaemonSet、Deployment 全塞在一个文件里apply 的时候一次性生效。v3.20.6 的镜像集大概包含下面这些角色我按实际部署时的依赖关系列一下镜像名组件角色部署形式calico/node核心节点代理负责路由、Felix 策略、隧道封装DaemonSetcalico/cniCNI 插件二进制kubelet 调用来建 Pod 网络DaemonSet 启动时安装到宿主机calico/kube-controllers监听策略、IP 池、Node 变化并同步Deploymentcalico/pod2daemon-flexvolFlexVolume 插件用于 CSI 之前的本地卷挂载DaemonSetcalico/csiCSI 驱动按需DaemonSetcalico/node-driver-registrarCSI 注册器按需DaemonSetcalico/typha高并发下的 Felix 数据聚合代理按需Deployment前四个是绝大多数离线集群要用的后三个看要不要 CSI 和 Typha。很多人第一次拿到压缩包会想是不是把所有 tar 都 load 进去就行这个思路没问题但要分清楚哪些镜像会被 calico.yaml 真正引用。如果 calico.yaml 里没启用 CSI那 csi 和 node-driver-registrar 加载了也不会被使用只是占空间不影响运行。calico.yaml 本身不是只有 DaemonSet。以 v3.20.6 这套为例文件开头是一大批 CustomResourceDefinition包括 FelixConfiguration、BGPPeer、BGPPConfiguration、IPPool、BlockAffinity 等中间是 kube-system 下的 RBAC 规则最后才是 calico-node 和 calico-kube-controllers。这意味着 apply 的先后次序其实已经被文件内部排好kubectl apply -f 一个文件就能按顺序创建资源不需要拆开手工分步执行。2.2 kdd 与 etcd先想清楚数据交给谁v3.20 这个版本正好处在 Calico 数据模式转型的过渡期它同时支持 etcd 模式和 Kubernetes 数据存储模式也就是常说的 kdd。理解这一点对排查问题很有用因为很多老教程写的是 etcd 模式命令和 yaml 都对不上。kdd 模式下Calico 的 IP 池、策略、BGP 配置全部以 CRD 形式存在 Kubernetes 里直接用 kubectl 就能看。etcd 模式则需要单独维护一套 etcd 集群Calico 自己往里面读写。v3.20.6 的 calico.yaml 默认就是 kdd因为清单开头创建了一堆 CRDcalico-node 的启动参数里也会通过 DATASTORE_TYPEkubernetes 指明。现在新建集群基本不需要考虑 etcd 模式除非你是从老集群迁移过来的否则跟着默认走就行。选 kdd 的好处很明显备份、权限控制、故障恢复都复用 Kubernetes 的机制。比如我要看当前集群的 IP 池配置kubectl get ippool 直接能看到不用再连一个独立的 etcd。坏处也实在APIServer 压力会随着节点和策略数量增加节点特别多比如上千时 Felix 的配置同步可能跟不上这时才需要引入 Typha。对大多数几百节点的集群kdd 没有任何问题。2.3 IPIP 与 VXLAN隧道模式的取舍v3.20.6 的默认清单里IP 池的封装模式是 IPIP AlwaysVXLAN Never。这个组合在物理机或同一二层网络里很稳因为 BGP 路由直接通告Pod 网段在节点间直接路由。但它有个前提底层网络允许 IPIP 协议的报文通过。很多公有云的安全组或内网防火墙对 IPIP 协议并不友好表现为节点间 Pod 时通时不通或者完全不通。这时要考虑 VXLAN。VXLAN 走的是 UDP 封装常规网络设备对 UDP 的容忍度高得多。VXLAN 模式下 Calico 会关闭节点间 BGP mesh数据走隧道而不是直接路由性能上比 IPIP 略低但兼容性最好。两种模式的选择逻辑很简单同一二层、网络设备你能控制用 IPIP跨云、跨机房、网络限制多用 VXLAN。后面第四章我会写具体怎么切。这里的另一个细节是 CrossSubnet 模式。IPIP 可以选择 Only 或 Always其中 CrossSubnet 表示只在跨子网时封装同子网走纯三层既保留同网段性能又解决跨网段路由问题。我一般会先把集群节点是否在同一个子网确认清楚再决定用 Always 还是 CrossSubnet别一上来就按默认值配。3. 离线部署落地加载镜像、改参数、apply 三步走3.1 先导入镜像docker 与 containerd 两条路径拿到镜像压缩包后第一件事是把它导入到集群实际使用的容器运行时里。很多现场翻车都是因为把镜像导进了 docker但 kubelet 用的是 containerd两边镜像互相看不见。先看节点上用的是哪种运行时。用 kubeadm 建的集群无论是 1.20 还是更高版本大部分都是 containerd socket。这种情况导入 containerd 的命令是# 在每台节点上执行或者下发到 /opt/calico/images ctr -n k8s.io images import calico-v3.20.6.tar# 导入后确认镜像 crictl images | grep calico说明一下这里的-n k8s.io是指定 containerd 命名空间kubelet 默认从这个命名空间拉镜像如果你不带这个参数镜像是会被导入但 kubelet 看不到calico-node 启动时依然会去尝试拉取然后报 image pull back off。crictl 是 kubelet 侧查看镜像最直接的工具能看到带 tag 的完整镜像名比如docker.io/calico/node:v3.20.6。如果集群确实用的是 docker那直接把 tar 喂给 dockerdocker load -i calico-v3.20.6.tar# 验证镜像是否都进来了 docker images | grep calico/node\|calico/cni\|calico/kube-controllers这里有两个容易踩的细节。第一docker load 和 ctr import 的 tar 格式不完全一样docker save 出来的 tar 用 docker load 肯定没问题但 containerd 的 ctr import 也能认反过来用 ctr export 的格式 docker 不保证认。所以离线包是谁打的最好就问清楚或者直接把两种命令都试一遍。第二镜像导入后不要立刻 apply先确认 tag 是不是 v3.20.6 这个精确版本。如果压缩包里打了 latest 标签而 calico.yaml 里写的是 v3.20.6kubelet 会老老实实去 repo 拉又卡在拉镜像上。3.2 改 calico.yaml 的三个关键参数镜像导入之后打开 calico.yaml。这个文件很大但真正每次必改的其实就三处Pod 网段、节点 IP 自动检测方式、封装模式。Pod 网段就是 CALICO_IPV4POOL_CIDR。这个值必须和你初始化集群时 kubeadm 指定的 pod-network-cidr 一致。比如 kubeadm init 时用了 10.244.0.0/16这里也必须是 10.244.0.0/16否则 kube-controllers 创建的 IP 池和 kubelet 预期的路由范围对不上。# 我的习惯是先备份再改 cp calico.yaml calico.yaml.bak# 把默认的 192.168.0.0/16 替换成实际 Pod 网段 sed -i s#192.168.0.0/16#10.244.0.0/16#g calico.yaml第二个是 IP_AUTODETECTION_METHOD。默认情况下 Calico 用 first-found 方式自动找一个可用的本机 IP多网卡节点经常找错比如找成 docker0 或另一个不相关网卡的地址。这个参数在 yaml 里未必存在如果没看到就自己在 calico-node 容器的 env 里加一行# calico.yaml 中 calico-node 容器的 env 片段 - name: IP_AUTODETECTION_METHOD value: interfaceeth.*# 或者直接指定网段更稳 sed -i /name: CLUSTER_TYPE/a\ - name: IP_AUTODETECTION_METHOD\n value: cidr10.10.0.0/16 calico.yaml这段逻辑是让 Calico 只在匹配 eth 开头或指定 CIDR 的网卡上选地址。在物理机上是 eth0、ens192在云主机上可能是 eth0 但有多网卡绑定用 cidr 匹配更保险。注意 value 里的引号不能丢整段是字符串带等号和星号。第三个是封装模式。默认的 IPIP Always 如果确定底层网络支持可以先不动。不确定的话直接改成 VXLAN# 把 IPIP 设为 NeverVXLAN 设为 Always sed -i s#CALICO_IPV4POOL_IPIP: Always#CALICO_IPV4POOL_IPIP: Never#g calico.yaml sed -i s#CALICO_IPV4POOL_VXLAN: Never#CALICO_IPV4POOL_VXLAN: Always#g calico.yaml还有一处容易被忽略如果网络里有 MTU 限制建议顺手看 Felix 配置里的 MTU 段落这个我放到第四章展开。改完三个参数后用 grep 检查一下改动是否都落到了 env 里grep -E IPV4POOL|IP_AUTODETECT calico.yaml注意后面的命令里我用的是 IP_AUTODETECT 做 grep实际环境变量名就是 IP_AUTODETECTION_METHODgrep 的时候写成 IP_AUTODETECTION 更精确否则可能只会匹配到部分行。我一般会把 Pod 网段和重叠问题一并检查调换一下顺序先把 ClusterIP 和 Pod 网段列出来确认再改 CIDR避免和 Service 网段重叠。3.3 apply 与初始验证参数改完后apply 这个文件。由于清单里有大量 CRD第一次 apply 时 kubectl 会把所有自定义资源定义先创建然后再创建 DaemonSet 等资源。正常的输出会包含一大批customresourcedefinition.apiextensions.k8s.io/... configured或created以及最终的daemonset.apps/calico-node created。kubectl apply -f calico.yamlapply 后不要急着看 Pod Ready先看容器是否启动kubectl get pods -n kube-system -o wide | grep calico这里的预期结果是一个节点跑一个 calico-node同时有 calico-kube-controllers 的一个副本。如果 calico-node 出现 CrashLoopBackOff 或 ImagePullBackOff先用kubectl logs看启动日志kubectl logs -n kube-system calico-node-xxxxx | head -80日志里最常见的是两种Failed to auto-detect an IPv4 address和Error getting Node ... spec。前者说明 IP 检测没生效回头检查 IP_AUTODETECTION_METHOD 有没有写对后者通常在 kdd 模式下是因为 Node 对象没有正常同步等几秒再看。等到 calico-node 全部 Running再用一条命令看集群整体状态kubectl get pods -n kube-system | grep -E calico|kube-proxy|coredns这一步建议连着 CoreDNS 一起看因为 CoreDNS 能正常 Running说明 CNI 已经把 Pod 网络打通了至少本节点内是通的。跨节点的通联验证放到第六章。这里要多看一个细节kube-proxy 的 status。Calico 的 IPIP 或 VXLAN 路由只负责 Pod 间流量Service 的 DNAT 走的是 kube-proxy iptables两者配合不好时 Service 会假死。所以初始验证阶段把这三个组件一起确认掉。4. 网络参数往深处调隧道切换、MTU 对齐、BGP 与 Typha4.1 切换封装模式从 IPIP 到 VXLAN 的现场操作默认配置在实际环境里大概率要调整。前面我提到先把 yaml 里的环境变量改了再 apply这是一种方式。但如果集群已经跑起来了改环境变量然后重建 DaemonSet 会闪断现有网络。更平滑的方式是直接改 IPPool 资源让 Calico 动态切换。先看当前 IP 池用的什么模式kubectl get ippool default-ipv4-ippool -o yamlspec: cidr: 10.244.0.0/16 ipipMode: Always vxlanMode: Never切换到 VXLAN 的话用 kubectl patchkubectl patch ippool default-ipv4-ippool -p {spec:{ipipMode:Never,vxlanMode:Always}} --typemerge这里要特别指出只改 IPPool 是不够的。calico-node 里 Felix 和 confd 的启动逻辑还依赖环境变量里的 CALICO_IPV4POOL_IPIP 和 CALICO_IPV4POOL_VXLAN它们决定了新建节点时默认池的创建策略。两个地方不一致可能造成旧节点走 VXLAN、新节点注册时又拉一个 IPIP 池。所以我改 IPPool 之前先确认 calico.yaml 里那两行 env 已经同步改成 Never/Always然后滚动重启 calico-node 让参数生效kubectl delete pods -n kube-system -l k8s-appcalico-node删除后 DaemonSet 会自动重建这个过程会让节点上的网络断几十秒窗口期建议挑维护时间。改完后用kubectl get ippool -o yaml确认两行已经切过来再看 calico-node 日志里有没有报 route 冲突。切换后如果业务 Pod 都在正常跑不建议来回切IPIP 和 VXLAN 的 NAT 行为有差异频繁切换会把 conntrack 表搞乱。4.2 MTU 对齐隧道开销和 flannel 的经典区别MTU 是离线排障里最容易被忽略的“玄学参数”。同样一份 calico.yaml在机房物理机里跑得好好的搬到公有云上跨节点 Pod 互相 ping 大包就丢小包正常典型就是 MTU 没对齐。默认物理网卡 MTU 是 1500。IPIP 封装会额外吃掉 20 字节所以隧道网卡 MTU 应该是 1480。VXLAN 封装开销更大额外约 50 字节隧道 MTU 应设 1450。如果宿主机网卡本身 MTU 是 1450一些云环境里常见VXLAN 隧道就要设 1400。Calico v3.20.6 的 Felix 配置支持直接指定 MTU。在 calico.yaml 的 FelixConfiguration 里改 mtu 字段或者在 calico-node 的 env 里加 FELIX_MTU。我一般会改 FelixConfiguration因为它是动态资源apply 后 Felix 会热加载kubectl patch felixconfiguration default -p {spec:{mtu:1450}} --typemerge这个命令是修改运行中的配置。如果要在 yaml 里固化就在 calico.yaml 的 felix-config ConfigMap 里加apiVersion: v1 kind: ConfigMap metadata: name: calico-config namespace: kube-system data: veth_mtu: 1450注意 ConfigMap 的 key 在 v3.20.6 里有veth_mtu和felix等不同版本命名有差异。最稳妥的做法是先看现有 ConfigMap 里有什么 key再按它的结构追加。改完 ConfigMap 要重启 calico-node 才会同步到 veth。这里有个判断技巧如果同节点 Pod 互 ping 1500 字节包没问题跨节点 1400 也通但 1450 不通那隧道开销就是 50按 VXLAN 的 1450 设置如果跨节点 1480 通但 1500 不通那是 IPIP 模式设 1480。别靠猜直接拿 ping -M do -s 大小去试。4.3 需要 BGP 时配置 Peer 或关闭 meshIPIP 模式下节点间默认用 BGP mesh 全互联节点多的时候连接数爆炸。常见做法是关闭默认 mesh改成指定 Peer让流量走交换机/路由器的 BGP 反射。先关 meshkubectl apply -f - EOF apiVersion: projectcalico.org/v3 kind: BGPPConfiguration metadata: name: default spec: nodeToNodeMeshEnabled: false EOF再建一个 BGP Peer指向你的网关或核心交换机kubectl apply -f - EOF apiVersion: projectcalico.org/v3 kind: BGPPeer metadata: name: tor-switch spec: nodeSelector: rack rack1 peerIP: 10.10.0.254 asNumber: 65000 EOF这段 yaml 里的 nodeSelector 把 Peer 限制在指定标签的节点上asNumber 是交换机所在的自治域。配置完成后去 calico-node 日志里看 BGP 会话是否 Establishedkubectl logs -n kube-system calico-node-xxxxx | grep -i bgp | tail -20BGP 场景下有个容易翻车的点IPPool 和路由通告范围。Calico 默认只通告 Calico 管理的 Pod 网段外部路由器想要访问 Service 网段需要额外配置 route reflector。大多数内部环境只需要 Pod 网段即可不要贪多。另外关闭 mesh 后如果 Peer 突然断开跨节点 Pod 会立刻失联这和 IPIP 隧道不同。所以我建议在关 mesh 之前先把交换机侧的 BGP 配置准备好不要先撤网再连。Typha 在 kdd 模式下是一个可选组件。节点数多、Felix 同步慢时Typha 的价值才体现。v3.20.6 的 calico.yaml 默认不会部署 Typha需要单独创建 Deployment。如果你只是 10 来个节点不用上 Typha它的额外成本是部署一套证书和转发规则排障面会变大。什么时候加节点的 Felix 报错felix: ... timeout、apiserver wait字样频繁或者calico/kube-controllers的同步延迟明显时再考虑。5. 避坑清单镜像不可见、节点起不来、跨节点不通的五个排障现场5.1 镜像明明导入成功kubelet 还是 ImagePullBackOff现象ctr -n k8s.io images import执行成功crictl images 也能看到 calico 镜像但 calico-node pod 一直 ImagePullBackOffdescribe 显示 image pull 失败。原因镜像 tag 不一致。离线包里的镜像 tag 可能是v3.20.6但 calico.yaml 里写的是latest或者反过来。另一个常见原因是 containerd 的命名空间没搞对crictl images 和 ctr 看到的实际上是两个空间。解决先crictl images | grep calico确认精确 tag再grep image: calico.yaml确认清单里引用的 tag两边一致即可。如果命名空间不对重新用ctr -n k8s.io images import导入一次导入后立刻用 crictl 验证。注意 docker load 对 containerd 集群无效这是 Kubernetes 1.20 以后最常见的坑。5.2 calico-node 起不来日志报 Failed to auto-detect an IPv4 address现象calico-node 反复 CrashLoopBackOffkubectl logs第一屏就是Failed to auto-detect an IPv4 address或者检测到了但地址不是节点自身 IP。原因节点上有多个网卡Calico 默认的 first-found 选错了网卡最常见是选了 docker0 的 172.17.0.1或者云主机绑定的备用网卡。另一种情况是配置了 IP_AUTODETECTION_METHOD 但正则不匹配。解决给 calico-node 设置显式的 IP 检测规则。用 interface 正则匹配真实的业务网卡kubectl set env daemonset/calico-node -n kube-system IP_AUTODETECTION_METHODinterfaceeth.*如果网卡名不确定先执行ip -4 addr看实际网卡名再写规则。最稳的方式是直接按节点所在网段检测kubectl set env daemonset/calico-node -n kube-system IP_AUTODETECTION_METHODcidr10.10.0.0/16设置完 DaemonSet 会自动滚动重建观察新 Pod 是否 Running。这里要强调IP_AUTODETECTION_METHOD 的值是一个完整字符串interfaceeth.*里的点号是正则别转义过头。5.3 节点都 Ready但跨节点 Pod 不通现象calico-node 全部 Runningkubectl get nodes 也 Ready同节点 Pod 互通但不同节点上的 Pod 互 ping 不通或者时通时不通。原因封装模式与底层网络不匹配。IPIP 模式下公有云防火墙或安全组限制了 4 号协议IP-in-IP导致跨节点隧道报文被丢。另一个常见原因是 MTU 没有对齐小包通、大包全丢。解决先确认当前封装模式再在节点上直接测试隧道开销ping -M do -s 1450 对端节点IP如果 1450 不通但 1400 通把 Felix MTU 调到 1400。如果封装模式是 IPIP 且底层限制严格直接切成 VXLAN步骤见 4.1。切完之后不建议只看 ping 结果还要用kubectl exec进去跑一次 curl 或 nc验证 TCP 数据面。5.4 改过 Pod 网段后新加的节点不在默认池里现象初始化时 calico.yaml 里写的 Pod 网段是 192.168.0.0/16后面想改成 10.244.0.0/16apply 新配置后旧节点正常但新加入的节点没有可分配的 IPkubelet 报 failed to allocate ip range。原因IPPool 创建后是持久化的 CRD 资源calico.yaml 里的环境变量只在首次创建默认池时生效改 yaml 并不会修改已存在的 IPPool。kube-controllers 又是按 IPPool 来分配块的旧池的 CIDR 没匹配新节点网段时范围不够用。解决如果集群还没有业务数据把旧池先删掉再应用新的 CIDRkubectl delete ippool default-ipv4-ippool kubectl apply -f calico.yaml注意删池子等于把当前所有 Pod 的网络配置掀掉Pod 必须重建才能拿到新地址。生产环境里更安全的做法是保留旧池再补一个新池把两个网段都纳入 Calico 管理缺点是路由表会膨胀不建议长期这么干。遇到这种问题先看kubectl get ippool -o yaml核对现有池的 cidr 和模式别一上来就删。5.5 calico-kube-controllers 反复重启日志报 CRD 或 RBAC 错误现象calico-node 正常但 calico-kube-controllers 的 Pod 一直 CrashLoopBackOff日志里出现Failed to list projectcalico.org/v3 ...或Forbidden ...。原因要么是 calico.yaml 里的 RBAC 被老版本覆盖导致权限缺失要么是 CRD 与 kube-controllers 版本不一致。v3.20.6 的 kube-controllers 需要监听 IPPool、BlockAffinity、IPAMHandle 等资源旧 CRD 里缺失这些资源list 时直接报错。解决先确认是权限还是 CRD 问题kubectl logs -n kube-system calico-kube-controllers-xxxxx | tail -40看到resource ... is not permitted走 RBAC重新 apply 一遍 calico.yaml 里的 ClusterRole 部分看到no matches for kind走 CRD把 calico.yaml 开头那批 CRD 重新 apply再重建 workloads。我遇到过集群升级时把 calico.yaml 覆盖成精简版少了几个 CRD最终靠补全 CRD 解决。以后凡是动 calico.yaml先记下原文件的 CRD 数量apply 后对比kubectl get crd | grep projectcalico.org的行数。6. 上线后的体检calicoctl 验证、策略实测与升级备份6.1 用 calicoctl 做状态体检v3.20.6 的离线环境里calicoctl 最省事的用法是直接进到 calico-node 容器里执行。节点管理是 KDD 模式KUBERNETES_SERVICE_HOST 环境变量已经在容器里calicoctl 会自动连接集群。kubectl exec -n kube-system calico-node-xxxxx -- calicoctl node status输出里重点看 BGP status 是不是 Established。IPIP 模式下这里是判断跨节点路由是否生效的唯一硬指标VXLAN 模式下这里不显示 BGP要看网卡状态。再看 IP 池分配kubectl exec -n kube-system calico-node-xxxxx -- calicoctl get ippool -o wide检查一下每个节点的 block 数量是否均匀有没有一个节点把整个网段都占掉的情况。IPAM 分配不均通常说明有节点反复重启导致 IP 没释放反复出现会让 Pod 的 IP 越用越偏。6.2 网络策略实测Calico 在 Kubernetes 里的卖点是 NetworkPolicy。CNI 只是第一步策略好使才算真正到位。我一般会先建一个测试 Pod再写一条只允许特定来源访问的策略验证 Deny 和 Allow 都生效。apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: deny-all-except-front namespace: test spec: podSelector: matchLabels: app: backend policyTypes: - Ingress ingress: - from: - podSelector: matchLabels: app: frontkubectl apply -n test -f - EOF apiVersion: v1 kind: Pod metadata: name: frontend labels: { app: front } spec: containers: - name: alpine image: alpine command: [sleep, 3600] EOF策略 apply 后从带app: front的 Pod 里访问 backend 的端口能通从别的 Pod 访问就是拒绝。这个测试能顺带验证 kube-proxy 和 Calico 的规则匹配顺序有没有被 SELinux 或本地规则干扰。测试通过后策略对象会跟着 calico.yaml 的 CRD 走备份时别漏。6.3 升级前快照与恢复Calico 这类网络组件升级最大风险是 IP 池和策略被覆盖。我习惯在升级前把 Calico 的 CRD 资源全部导出到一个文件出问题时能一键恢复。kubectl get felixconfigurations,bgpconfigurations,bgppeers,ippools,networkpolicies,globalnetworkpolicies -o yaml calico-backup.yaml这里注意导出对象不是 calico.yaml 本身而是运行时的所述 CRD 实例。恢复时kubectl apply -f calico-backup.yaml升级 v3.20.6 到更高版本时镜像 tag 要全局替换calico.yaml 里的 CRD 版本也可能变化。不要直接 apply 新文件先把新旧 yaml 里的 CRD 名称 diff 一遍确认没有删除旧资源。Calico 升级后的回滚比升级本身麻烦一旦发现新版本要 rollback就重新导入旧镜像、apply 旧 yaml再用备份文件恢复 CRD。从那以后我每次部署完 Calico 都强制走一遍这个体检先看镜像 tag 和节点数量是否对应再看 calicoctl node status 的 BGP 状态最后拿一条 NetworkPolicy 做一次跨节点访问实测。三步下来九成以上的网络隐患会在业务接入前暴露。希望帮到你。本文还有配套的精品资源点击获取