news 2026/10/15 20:14:26

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

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
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 策略、隧道封装DaemonSet
calico/cniCNI 插件二进制,kubelet 调用来建 Pod 网络DaemonSet 启动时安装到宿主机
calico/kube-controllers监听策略、IP 池、Node 变化并同步Deployment
calico/pod2daemon-flexvolFlexVolume 插件,用于 CSI 之前的本地卷挂载DaemonSet
calico/csiCSI 驱动(按需)DaemonSet
calico/node-driver-registrarCSI 注册器(按需)DaemonSet
calico/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,因为清单开头创建了一堆 CRD,calico-node 的启动参数里也会通过 DATASTORE_TYPE=kubernetes 指明。现在新建集群基本不需要考虑 etcd 模式,除非你是从老集群迁移过来的,否则跟着默认走就行。

选 kdd 的好处很明显:备份、权限控制、故障恢复都复用 Kubernetes 的机制。比如我要看当前集群的 IP 池配置,kubectl get ippool 直接能看到,不用再连一个独立的 etcd。坏处也实在:APIServer 压力会随着节点和策略数量增加,节点特别多(比如上千)时 Felix 的配置同步可能跟不上,这时才需要引入 Typha。对大多数几百节点的集群,kdd 没有任何问题。

2.3 IPIP 与 VXLAN:隧道模式的取舍

v3.20.6 的默认清单里,IP 池的封装模式是 IPIP Always,VXLAN 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 喂给 docker:

docker 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.6,kubelet 会老老实实去 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: "interface=eth.*"
# 或者直接指定网段,更稳 sed -i '/name: CLUSTER_TYPE/a\ - name: IP_AUTODETECTION_METHOD\n value: "cidr=10.10.0.0/16"' calico.yaml

这段逻辑是让 Calico 只在匹配 eth 开头或指定 CIDR 的网卡上选地址。在物理机上是 eth0、ens192,在云主机上可能是 eth0 但有多网卡绑定,用 cidr 匹配更保险。注意 value 里的引号不能丢,整段是字符串,带等号和星号。

第三个是封装模式。默认的 IPIP Always 如果确定底层网络支持,可以先不动。不确定的话,直接改成 VXLAN:

# 把 IPIP 设为 Never,VXLAN 设为 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_METHOD,grep 的时候写成 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.yaml

apply 后不要急着看 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 与 Typha

4.1 切换封装模式:从 IPIP 到 VXLAN 的现场操作

默认配置在实际环境里大概率要调整。前面我提到先把 yaml 里的环境变量改了再 apply,这是一种方式。但如果集群已经跑起来了,改环境变量然后重建 DaemonSet 会闪断现有网络。更平滑的方式是直接改 IPPool 资源,让 Calico 动态切换。

先看当前 IP 池用的什么模式:

kubectl get ippool default-ipv4-ippool -o yaml
spec: cidr: 10.244.0.0/16 ipipMode: Always vxlanMode: Never

切换到 VXLAN 的话,用 kubectl patch:

kubectl patch ippool default-ipv4-ippool -p '{"spec":{"ipipMode":"Never","vxlanMode":"Always"}}' --type=merge

这里要特别指出:只改 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-app=calico-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}}' --type=merge

这个命令是修改运行中的配置。如果要在 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 或关闭 mesh

IPIP 模式下节点间默认用 BGP mesh 全互联,节点多的时候连接数爆炸。常见做法是关闭默认 mesh,改成指定 Peer,让流量走交换机/路由器的 BGP 反射。

先关 mesh:

kubectl 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 会话是否 Established:

kubectl logs -n kube-system calico-node-xxxxx | grep -i 'bgp' | tail -20

BGP 场景下有个容易翻车的点: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 一直 ImagePullBackOff,describe 显示 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 反复 CrashLoopBackOff,kubectl 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_METHOD='interface=eth.*'

如果网卡名不确定,先执行ip -4 addr看实际网卡名,再写规则。最稳的方式是直接按节点所在网段检测:

kubectl set env daemonset/calico-node -n kube-system IP_AUTODETECTION_METHOD='cidr=10.10.0.0/16'

设置完 DaemonSet 会自动滚动重建,观察新 Pod 是否 Running。这里要强调:IP_AUTODETECTION_METHOD 的值是一个完整字符串,interface=eth.*里的点号是正则,别转义过头。

5.3 节点都 Ready,但跨节点 Pod 不通

现象:calico-node 全部 Running,kubectl 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/16,apply 新配置后旧节点正常,但新加入的节点没有可分配的 IP,kubelet 报 failed to allocate ip range。

原因:IPPool 创建后是持久化的 CRD 资源,calico.yaml 里的环境变量只在首次创建默认池时生效,改 yaml 并不会修改已存在的 IPPool。kube-controllers 又是按 IPPool 来分配块的,旧池的 CIDR 没匹配新节点网段时,范围不够用。

解决:如果集群还没有业务数据,把旧池先删掉再应用新的 CIDR:

kubectl 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: front
kubectl 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 做一次跨节点访问实测。三步下来,九成以上的网络隐患会在业务接入前暴露。希望帮到你。

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

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

本地 AI 助手 OpenClaw 安装记录,Windows 环境完整配置

Windows 一键部署 OpenClaw 教程&#xff5c;5 分钟搞定本地 AI 智能体&#xff0c;告别复杂配置 说明&#xff1a;本文适配 CSDN 发布&#xff0c;全部版本号、链接、文件大小已替换&#xff0c;删除标签 / 日期 / 阅读量 / 示意图&#xff0c;规避禁用词汇&#xff0c;首次全…

作者头像 李华
网站建设 2026/10/15 20:11:24

无人机VIO部署实战:SchurVINS yaml配置与调参避坑指南

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

作者头像 李华
网站建设 2026/10/15 20:10:34

Filebeat 7.7.0 Elasticsearch 输出配置详解与性能调优

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

作者头像 李华
网站建设 2026/10/15 20:09:59

C++工资个税计算器实战:累计预扣法、边界处理与参数化设计

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

作者头像 李华
网站建设 2026/10/15 20:09:51

STM32驱动OV2710:DVP链路与DMA搬运的避坑指南

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

作者头像 李华
网站建设 2026/10/15 20:09:51

Django REST Framework序列化器核心原理与实战精要

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

作者头像 李华