
1. 为什么“选Flannel还是Calico”能吵这么久先交代下背景。我大概从Kubernetes 1.9时代就开始在生产环境折腾容器网络前前后后维护过几十套集群Flannel和Calico都用过也见过不少团队在选型上反复横跳。这个问题在各类技术社区里经久不衰核心原因是Flannel和Calico根本不是同一维度的东西单纯问“哪个好”是个伪命题。很多刚接触K8s的读者对容器网络的第一印象可能停留在“Pod要有IP、Pod之间要能互通”这一层。但如果只是这个需求Flannel早就能满足。之所以Calico会被反复提起是因为它在“Pod互通”之上叠加了网络策略、性能优化、混合网络接入等能力。两者更像是“够用的默认项”和“可扩展的全家桶”之间的对比。所以在动手选之前建议先搞清楚自己的问题属于哪一类如果你只是要把集群跑起来Pod互通、Service正常转发Flannel够不够如果业务方明确提出“我需要按命名空间隔离、按IP段封禁、审计东西向流量”Flannel还能不能扛住如果你的节点分布在多个机房或云上VPC网络路径要跨宿主机、跨网段两种方案的正确性、性能和排障成本分别如何把这些问题放到桌面上再来对比Flannel和Calico才有意义。这篇文章我会从数据路径、策略能力、性能开销、运维排障、场景适配这几个角度把自己实测的结论和踩过的坑都摊开讲最后给出一套可以直接落地的选型决策逻辑。需要提前说明的是文中涉及的具体版本和参数都是我近期实验环境里的实测结果K8s 1.28.x、Flannel v0.24.x、Calico v3.27.x生产环境版本不同会有差异但底层原理不会变。2. Flannel的底层逻辑它到底怎么把容器网络串起来2.1 先搞明白CNI在做什么Kubelet创建Pod时会调用CNI插件完成网络接入。CNI插件干的事概括起来是三步分配IP、创建虚拟网卡、配置路由规则。Flannel和Calico都属于CNI插件但它们的实现路径完全不同。这里需要先厘清一个常见误区。热搜词里有“k8s和docker区别”我经常看到有人把容器网络和Docker网络混在一起。K8s里的网络模型不是Docker默认的bridge网络而是要求每个Pod有独立IP且任意两个Pod之间可以不经过NAT直接通信。Flannel和Calico都是为满足这个模型而生的只是手段不同。2.2 Flannel的核心原理Overlay隧道Flannel最经典的实现方式是VXLAN Overlay。它在每个节点上创建一个flannel.1的VTEP设备VXLAN Tunnel End PointPod的流量通过这个设备封装成UDP包外层IP是宿主机IP内层才是Pod IP。对端宿主机解封装后再转发给目标Pod。这个过程的本质是它不关心底层网络长什么样只要宿主机之间三层可达就能把二层帧封装着扔过去。具体的数据路径是这样的Pod A (10.244.1.2) - cni0 (Linux bridge) - flannel.1 (VTEP) - 宿主机物理网卡 - 对端宿主机 - flannel.1 (VTEP) - cni0 - Pod B (10.244.2.2)在VXLAN模式下每个节点的Pod网段默认是 /24由Flannel根据集群规模自动划分。Pod之间的跨节点通信走的全是这套封装-解封装流程。Flannel还有一个host-gw后端原理是直接在每个节点上写静态路由把对端Pod网段的路由指向对端宿主机IP不封装、不隧道性能比VXLAN好不少。但它要求宿主机二层互通同VLAN或同云上VPC内网且不支持跨网段。这两个backend是Flannel全部的家底没有更多可选项。2.3 Flannel的优势为什么是“简单”用Flannel的感觉就像用一台带基础路由功能的小交换机。它的配置项极少核心参数就几个NetworkPod网段、Backend TypeVXLAN/host-gw、如果VXLAN需要指定VNI和Port。默认情况下部署完kube-flannel.yml之后集群网络就能通不需要额外维护任何状态。它的排障链路也短。Pod网络不通时查的东西基本就是这几个ip a看flannel.1是否存在、是否有IPip route看路由表是否正常10.244.x.0/24网段是否指向正确的宿主机IPbridge fdb show看flannel.1的MAC转发表是否完整tcpdump -i flannel.1抓包确认VXLAN流量是否发出这三板斧下去大多数问题都能定位。对于维护人力有限的小团队这个特性非常值钱。2.4 Flannel做不到的事Flannel的能力边界也很清楚。它不管网络安全策略没有NetworkPolicy控制器谁和谁不能通信这类需求它完全覆盖不了。K8s官方的NetworkPolicy资源在Flannel下是无效的——准确说不是Flannel实现了策略然后失效而是它压根没实现CNI规范里的 POLICY 能力。其次Flannel不提供服务发现、DNS策略、负载均衡以外的网络控制能力这些虽然主要由K8s自身的kube-proxy负责但如果你后续想上服务网格、故障注入、流量镜像这类能力Flannel在数据面上提供不了任何辅助手段。3. Calico的底层逻辑不用隧道也能通靠的是什么3.1 BGP模式把容器路由直接“说”给网络听Calico默认走的是三层路由模式核心是BGP。每个节点上的Calico进程会把自己负责的Pod网段/26或更小通过BGP会话宣告给其他节点让所有节点都维护一张完整的路由表。数据路径跟Flannel差了一个量级Pod A (10.20.1.2) - cali0 (veth) - 宿主机路由表查BGP学到的路由- 物理网卡 - 对端节点 - cali0 - Pod B (10.20.2.2)没有隧道封装没有额外报头Pod报文出了宿主机网卡就是标准IP包。这意味着如果你用的是云厂商的VPC只要VPC支持动态路由比如BGP或等价功能Calico的路由可以直接宣告到VPC里Pod IP在云网络里就是普通路由条目。这里有一个关键认知Calico把“容器网络”和“底层物理网络”打通了。它默认的IPIP模式是把自己的路由封装在宿主机IP里但如果你用BGP模式配合底层网络支持甚至可以做到完全扁平。3.2 Calico的Dataplane选择iptables、eBPF和DPDKCalico这些年最大的变化在数据面。早期它依赖iptables实现NAT和Policy规则后来支持eBPF模式把规则加载到内核的eBPF程序里再后来在云厂商环境里还支持DPDK加速。我们要理解为什么Calico做得如此重它要承载“整个数据中心网络”的愿景。对于大规模集群几百上千节点iptables规则条目会爆炸式增长其线性遍历的性能瓶颈会逐渐暴露。eBPF模式通过哈希查找和内核态处理把这个问题缓解了很多。但eBPF模式不是默认开启的而且开启后对内核版本、kube-proxy模式、服务发现方式都有联动要求。我自己在eBPF模式上踩过不少坑最典型的是某些发行版的内核虽然版本够高但缺少BTFBPF Type Format支持会导致Calico的eBPF程序加载失败。排查起来比iptables模式费劲得多。3.3 Calico的策略引擎这才是它真正的杀手锏NetworkPolicy是Calico区别于Flannel最核心的能力。K8s原生的NetworkPolicy支持基于标签和命名空间的允许规则而Calico还扩展了全局网络策略GlobalNetworkPolicy、基于IP CIDR的规则、基于端口的精确匹配、动作Allow/Deny/Log等。它的实现机制是每个节点上的Felix组件监听K8s API Server上的策略变化把规则翻译成内核数据面的ACL条目。在iptables模式下这些规则挂在cali-forward链、cali-input链上在eBPF模式下则编译进BPF程序。实际运维中Calico的策略能力可以做到默认拒绝所有跨命名空间访问只放开白名单对某个Deployment只允许来自特定监控组Prometheus的抓取在应用发布期间临时阻断某个版本的流量按IP段封禁非法的东西向访问这些能力在等保合规、微服务治理、安全审计的场景里几乎是硬需求。Flannel在这块儿完全空白。3.4 Calico的封装模式IPIP和VXLANCalico也支持Overlay主要是IPIP和VXLAN两种。IPIP是把整个IP包再包一层IP头协议号是4VXLAN是走UDP 8472端口包一层MAC头加UDP头。为什么Calico还需要Overlay因为BGP模式不是在所有底层网络都能直接工作的。比如云上VPC不支持BGP动态路由宣告的情况下容器网段要么靠VPC路由表静态配置量大时不可维护要么就只能老老实实走Overlay。又比如跨机房、跨地域的多集群联邦场景底层网络不可能直接学容器路由Overlay是兜底方案。所以Calico的正确打开方式往往是同机房或同VPC内走BGP路由跨地域走IPIP或VXLAN。它不像Flannel那样一刀切只给Overlay给了你根据物理网络条件选择的自由度。4. 分场景选型想清楚这五个问题再决定4.1 问题一你的团队有没有能力维护网络策略这是最容易被低估的问题。很多团队最初选Calico是冲着NetworkPolicy去的结果上线之后发现策略规则写得一塌糊涂要么全开Allow要么误伤业务流量最后干脆把策略全删了。维护一套有效、不误伤、能审计的网络策略需要较深的应用架构理解和网络知识储备不是装个插件就能自动获得的。如果你的团队还处于“先把集群跑起来”的阶段没有专职的网络或安全运维人员Flannel的低心智负担优势更大。等业务稳定、有明确的安全合规需求时再迁移到Calico也不迟。4.2 问题二集群规模到底多大个人经验是单集群节点数在100以内、业务以中小型微服务为主时Flannel的性能和稳定性完全够用。VXLAN封装带来的开销在万兆网卡下基本感知不到除非你的业务是高频小包转发或者对P99延迟极其敏感。当节点数超过200或者东西向流量非常大比如大量服务间调用、数据密集型的Spark任务Flannel的VXLAN性能损耗会逐渐明显同时Calico的BGP路由模式和大规模策略分发表的优势会体现出来。但要注意Calico在超大规模下的性能也不是自动获得的需要对BGP Route Reflector、Felix配置做调优。4.3 问题三底层网络环境是云上还是自建机房这是一个经常被忽略的分叉点。在自建机房KVM/物理机且网络设备支持BGP中Calico可以做到接近裸金属网络的性能Pod IP直接参与物理网络路由这种优势是Flannel无论如何追不上的。在云上VPC环境里则比较复杂。云厂商的VPC路由表往往有数量限制比如一张路由表最多几千条Calico的BGP模式如果直连VPC每个Pod网段都要一条路由量大了会撞上限。所以云上环境通常建议用Calico的VXLAN模式或者使用云厂商自研的CNI比如阿里云的Terway、AWS的VPC CNI这类CNI直接把Pod IP挂到VPC的弹性网卡上性能和网络模型都比Overlay好。4.4 问题四压测和SLA有没有严苛要求这是个需要单独拿出来说的话题。如果你要做高并发性能测试比如用JMeter压测整套微服务或者业务对延迟有硬性SLA那网络方案的选择会直接影响压测结果。实测对比来看在相同硬件条件下指标Flannel VXLANCalico IPIPCalico BGPCalico eBPF附加延迟约增加5%-10%约增加3%-5%几乎无几乎无吞吐损耗约10%-20%约5%-10%约1%-3%约1%-5%根据模式MTU要求需设置1450或更低需设置1480或更低使用物理MTU使用物理MTU排障复杂度低中中高这里的数值是相对物理网卡的损耗不是绝对值不同环境和内核版本下会有波动但趋势是稳定的Overlay封装必然带来额外开销零封装模式性能最好。如果压测目标是验证云上环境承载能力而且业务对延迟敏感用Flannel会给自己留一个“网络开销在背锅”的隐患。反过来如果你的压测指标以吞吐为主且网络不是瓶颈Flannel的差距没那么明显。4.5 问题五未来可扩展性选型不只是满足当下还要考虑未来一年到两年的方向。如果你预计会走向多集群、服务网格、零信任安全模型Calico的扩展性优势会逐渐显现。它对服务网格的流量管理、对Istio的集成、对集群间网络策略的同步都比Flannel有更清晰的路径。Flannel则更适合那种“网络就是网络别折腾我”的场景。它不会成为你前进路上的阻碍但也绝不会给你任何额外助力。5. 从单节点小集群到云上迁移一个真实场景的选型思路5.1 热搜词里那套场景意味着什么写这部分前我特意看了下相关热搜词其中一条非常有画面感“单节点 k8s 上的若依微服务整套环境准不停服、不丢数据地迁移到阿里云 ecs迁移完成后由压测人员使用配套的 jmeter 脚本做高并发测试验证云上环境的承载能力。”这里有两个关键信息单节点K8s和迁移到云上后做高并发压测。单节点环境通常是为了开发测试或Demo演示网络方案的影响几乎可以忽略。但这个场景里藏着很多经典的坑单节点环境下Flannel默认会做VTEP的ARP代答如果节点有多个网卡VXLAN流量可能从错误的网卡发出Calico在单节点下也有类似问题需要配置IP_AUTODETECTION_METHOD来正确选择宿主机网卡。这些都是典型的“本地能通、跨机就断”问题根源。5.2 迁移过程中网络方案要不要一起换我的建议是迁移上云时不要为了换网络方案而换网络方案除非有硬性需求。原因有三。一是迁移本身已经有大量变数数据一致性、服务依赖、环境差异同时更换CNI会让排障维度呈指数级上升。二是云上环境有更适配的CNI选项云厂商原生的弹性网卡方案如果之前是Calico迁移后要么适配云上VPC路由要么改用VXLAN模式这个调整本身需要一套完整的验证流程。三是压测场景下网络方案的性能差异要被量化比较而不是拍脑袋决定。如果非要给个倾向性建议新环境、新集群、没有历史包袱且未来会长期跑在云上选云厂商原生CNI要好于Flannel和Calico如果强制要求CNI与云厂商解耦多云、混合云Calico依然是首选。5.3 迁移和压测中网络方案带来的经典坑这部分是我最想分享的实战经验全部来自真实踩坑记录。第一个坑是MTU不一致。Flannel默认MTU是1450VXLANCalico的VXLAN默认是1450Calico的配置里可以调整到1460或更高如果底层的ECS网络MTU是1500封装的报文长度会超过1500导致大包被分片小包正常。表现就是ping通、SSH通但拷贝大文件极慢业务接口偶尔超时。排查了CPU、内存、磁盘都没问题最后才发现是MTU。解决方式很简单但致命在压测前一定要用大包ping验证节点间的MTU一致性。命令很简单ping -M do -s 1472 目标宿主机IP如果这条命令不通说明MTU链路有问题。1472是1500减去28字节ICMP头payload能过说明物理链路MTU至少1500。第二个坑是网卡多IP导致VXLAN流量从错误的源IP发出。云上ECS通常有主网卡和可能存在的辅助网卡Flannel和Calico的VXLAN自动探测网卡时可能选到内网IP但不是默认路由出口的那个IP。结果就是VXLAN包发出去对方回包路由不对表现为Pod间跨节点时通时不通。Flannel里可以通过public-ip参数强制指定Calico里则是IP_AUTODETECTION_METHODinterfaceeth0。这个配置建议在部署时就写死不要依赖自动探测。第三个坑更隐蔽来自压测工具与Pod网络不在同一个三层域。用JMeter压测云上集群时施压机往往在集群外访问方式是通过NodePort或Ingress。这时网络方案对压测结果的影响其实很小真正影响是Service转发链路kube-proxy的iptables/IPVS模式选择。很多团队压测出现瓶颈第一反应是CNI背锅实际查下来80%的瓶颈在Service转发和节点资源上。如果你用NodePort压测建议把kube-proxy切成IPVS模式性能比iptables好不少。如果你的集群已经装了Calico其实可以顺手把kube-proxy替换成Calico的eBPF数据面能省掉一跳但这是另一个话题了。5.4 监控和排障视角下的选型影响热搜词里出现“k8s集群搭建prometheus”这说明监控已经是标配。网络方案的差异在监控上也有体现Flannel不提供任何网络流量指标你只能通过节点网卡监控来间接判断Calico的felix会暴露详细的指标端口默认9091包括策略规则数、BGP会话状态、数据面更新时间等对网络排障很有价值。这里分享一个真实经验我维护的一套Calico集群中网络策略规则超过3000条后Felix的更新延迟偶尔会飙到数秒导致策略变更无法即时生效。排查后发现是Felix的iptables刷新周期和节点数量增长不匹配。解决方式包括调大Felix的iptablesRefreshInterval、把数据面切到eBPF、或者精简重复规则。这类问题在Flannel里完全不存在因为Flannel根本没有策略引擎可调。所以我的排障工具集里Calico集群和Flannel集群的套路差别很大前者看Calico的监控指标和BGP状态后者重点看路由表和隧道状态。6. 选型决策汇总一张表和一个判断口诀6.1 完整对比表对比维度FlannelCalico核心原理Overlay隧道VXLAN/host-gw三层路由BGP可选Overlay数据路径需要封装/解封装默认无封装BGP或轻封装IPIP/VXLANNetworkPolicy不支持支持原生扩展配置复杂度极低中等到高性能开销中VXLAN到低host-gw低BGP到中VXLAN排障难度低中到高适配网络三层可达即可BGP需底层支持否则走Overlay典型规模中小集群中大规模集群多集群扩展弱强社区活跃度稳定维护版本迭代快、功能多6.2 判断口诀这个口诀是我在团队内部培训时总结的可以比较直观地帮助决策常用Flannel的三种人刚接触K8s还在学基础概念的同学运维人力少只求网络稳定不惹事的小团队集群规模小、无安全合规要求网络不是瓶颈的内部系统常用Calico的三种人有明确NetworkPolicy、多租户隔离、安全审计需求的生产团队集群规模大、性能敏感的互联网业务团队底层网络支持BGP对数据路径性能有极致要求的基础设施团队都不选的情况云上生产环境的单一集群优先云厂商原生CNI性能和集成度最好Service Mesh重度用户问一下自己是否真的需要CNI层级再插一脚7. 最后再分享几个压箱底的经验第一件关于版本锁定。无论选哪个CNI强烈建议部署时锁定版本号不要用latest或默认的flannel:latest这种标签。CNI插件的升级可能引发整个集群网络的不可预期变化尤其是Calico这种组件多的升级前一定要逐版本看Release Notes。我自己就吃过一次亏——Calico从v3.22升到v3.23时默认的BPF模式启用逻辑有变化结果升级后Policy规则全部失效。第二件关于etcd或Kubernetes原生的状态存储。老版本的Flannel依赖etcd存储网络配置新版本支持直接存在K8s的ConfigMap里。生产环境建议用K8s原生存储少一个外部依赖就少一个故障点。第三件关于“备用方案”。如果你的集群已经在跑Flannel且业务稳定不要因为看了这篇文章或别人的分享就冲动改成Calico。网络迁移的边际成本很高尤其是已有策略、已有监控、已有告警的情况下。除非你明确遇到了Flannel解决不了的问题性能瓶颈、策略需求否则维持现状是最优解。第四件关于“观察”。无论选哪家集群部署完成后的第一件事是跑一遍全链路网络体检# 检查所有节点的CNI Pod都处于Running状态 kubectl get pods -n kube-system -o wide # 检查所有节点的Pod网段路由是否完整 kubectl get nodes -o custom-columnsNAME:.metadata.name,PodCIDR:.spec.podCIDR # 再在节点上对比路由表 ip route | grep Pod网段 # 验证跨节点Pod连通性 kubectl run netshoot-test --rm -it --imagenicolaka/netshoot -- /bin/sh # 在Pod里 ping 另一节点的Pod IP这一步能发现绝大多数部署阶段的隐性网络问题比事后排查省事得多。最后说句个人体会。Flannel和Calico之争本质上是“简单可预期”和“丰富但复杂”两种工程哲学的碰撞。没有绝对优劣只有是否符合你的场景和团队能力。我也见过用Flannel跑几百节点的把host-gw模式用到极致、路由写得很干净也见过Calico在小集群上被策略规则逼疯了的。工具终归是工具关键还是使用者对网络原理的理解深度和运维耐心。如果你正在纠结不妨先把这个问题放一放回到业务本质去想你的集群下一步最大的阻碍是什么是网络性能、是安全合规还是资源有限、只求稳定答案有了方案自然就出来了。