news 2026/10/21 21:59:34

K8s网络插件选型:从flannel到calico的原理对比与实战经验

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
K8s网络插件选型:从flannel到calico的原理对比与实战经验

Kubernetes用了一年多,中间最绕不开的一个决定就是选网络插件。flannel和calico这两个名字,几乎每个搞K8s的人都纠结过一遍。我自己的经验是从flannel起步,后来部分集群迁到了calico,中间踩了不少坑,也对这两个插件背后的设计思路有了比较深的理解。这篇文章就把我对这两个插件的使用心得、原理拆解和选型思考一次性讲清楚。

1. 为什么网络插件是K8s绕不开的一环

1.1 K8s网络模型的底层要求

Kubernetes对网络有一个硬性要求:所有Pod之间必须能够直接通信,无论它们落在哪个节点上,都不需要NAT转换。这个模型听起来简单,但在底层实现上是个不小的工程。容器从宿主机视角看只是一个个隔离的进程,它们有自己的网络命名空间,有各自的虚拟网卡和IP地址。要让这些分布在不同物理机上的“虚拟网卡”互通,就必须有一种机制把二层或三层网络打通。

这就轮到CNI(Container Network Interface)出场了。CNI是一套标准接口,Kubelet创建Pod时会调用CNI插件,把Pod的网络命名空间交给插件来配置。flannel和calico都是CNI插件,但它们的实现哲学完全不同。打个比方,flannel像是给你一条“隧道”,把各节点的容器网络串起来;而calico像是一张“真实的互联网”,每个Pod都有一个真实可路由的IP,节点之间通过路由协议直接交换数据。

1.2 插件选型决定集群的流量路径

网络插件不只是“让Pod互通”这么简单。它决定了数据包从Pod出去之后,走的是哪条路径、经过了哪些封装和解封装、能不能被安全策略拦截。这些底层差异直接反映在时延、吞吐量和运维复杂度上。很多人的第一个集群会用flannel,因为它简单、够用;但一旦集群规模变大、安全要求变高、或者跑的是对延迟敏感的业务,flannel的一些短板就会暴露出来,这时候calico往往成为更合适的选择。

这篇文章不打算做那种“A好还是B好”的站队,而是把两个插件的工作机制、部署方式、性能特征和适用场景都摊开来说,最后大家可以根据自己的业务情况做判断。

2. flannel的设计哲学:用隧道简化一切

2.1 flannel的核心思路

flannel最早由CoreOS团队开发,设计目标是用尽量简单的方式解决Pod跨节点通信。它的思路很直接:每台节点上的Pod共享一个子网,flannel为每个节点分配一个独立的子网段(例如10.244.1.0/24),然后通过VXLAN或Host-GW等后端,把这些子网连通起来。

我最常用的是VXLAN模式。VXLAN是一种隧道协议,它把Pod发出的一层数据包塞进UDP包里面,经过宿主机网络转发到目标节点后,再解封装还原成原始的二层包。这个过程对Pod完全是透明的,Pod并不知道自己被“装进信封”寄到了另一台机器。

有个类比能帮助理解:把每个节点的容器网络看成一个小岛,VXLAN就是岛与岛之间的渡轮。岛上的车(Pod的数据包)不需要知道海怎么过,只要开上渡轮就行。渡轮在海上行驶时用的是海上的航路(宿主机网络),到了目的岛再把车开下来。

2.2 flannel的三种后端模式

flannel支持多个后端,我最常用的两个是VXLAN和Host-GW,还有一个已经很少用的UDP。

VXLAN模式下,flannel会创建一块flannel.1虚拟网卡,负责VXLAN封包和解包。数据包路径是:Pod eth0 -> cni0网桥 -> flannel.1 -> 宿主机eth0 -> 对端宿主机 -> 对端flannel.1 -> 对端cni0 -> 目标Pod。这条链路多了一次隧道封装和解封装,会带来少量性能损耗,但好处是它不要求宿主机在同一个二层网络,只要三层能通就能跑。VXLAN的端口默认是8472,UDP包里的VNI是1。

Host-GW模式则直接把每个节点当作一个路由器,flannel会在节点上写入路由规则,数据包从Pod出来后直接走宿主机网络转发到目标节点,不做任何隧道封装。这种模式的转发效率在三种方式里最高,因为数据包几乎走的是原生路径。但代价是:宿主机之间必须在同一个二层网络中,而且要关闭rp_filter(反向路径过滤),否则路由会出现不对称问题。

UDP后端现在基本被淘汰了,每次收发数据包都要在内核态和用户态之间切换,性能很差,早期版本才用它。

2.3 flannel部署与配置细节

部署flannel很简单,绝大多数情况下一条kubectl apply就能搞定。部署文件里核心的配置在ConfigMap中,包括Network(Pod网段)、Backend(后端类型)等。以下是一个VXLAN后端配置的片段:

net-conf.json: | { "Network": "10.244.0.0/16", "Backend": { "Type": "vxlan", "Port": 8472 } }

这个配置里有两个值得注意的地方。一个是Network网段,需要保证和kube-controller-manager中--cluster-cidr参数一致,否则CNI分配的IP和Controller预期的范围对不上,引发IP冲突或路由混乱。另一个是Port参数,VXLAN模式默认使用内核VXLAN模块,不需要用户态进程监听UDP端口,所以这个端口更多是用于VXLAN模块识别VTEP(VXLAN Tunnel End Point)。

实际部署中还要注意一个细节:flannel要求每台节点上的docker0网桥和Pod网段不能冲突。如果之前装过其他CNI插件,或者docker的default-address-pools设置过私有网段,一定要先清理干净,否则Pod启动后IP就会错乱。我在一次测试环境里就是因为之前试过某插件,没有清理干净,结果新节点上的Pod全部跟已有Pod IP冲突,流量乱成了一锅粥。

3. calico的设计哲学:让网络回归路由

3.1 calico的三层路由模型

calico的核心思路和flannel恰好相反:不封装,直接路由。它把每个节点当路由器,Pod的IP是真实的可路由IP,节点之间通过BGP协议交换路由信息,数据包按原生路径直接送达。calico没有网桥、没有隧道,虚拟网络拓扑看起来更像一张“正经的”物理网络。

calico在每台节点上创建cali前缀的虚拟网卡(例如cali123abc),每张网卡对应一个Pod。然后通过路由规则,把目标Pod IP的下一跳指向对应的宿主机。BGP(Border Gateway Protocol)在这里扮演的角色就是把“哪个节点有哪些Pod子网”的信息广播给整个集群,让每台节点都知道如何到达任何一个Pod。

这种设计让calico的性能表现先天优于flannel的隧道模式,因为数据包没有额外封装,转发路径短,CPU开销也小。特别是在高频小包场景下,封装与否的差距会非常明显。

3.2 calico的IPIP和VXLAN封装模式

我前面说calico“不封装”,严格来说不准确。calico在跨网络场景下也会使用封装。IPIP模式是一种常见的跨子网传输方案,它将Pod发出的整个IP包作为负载,外面再套一个IP头。这个模式的好处在于,不管底层网络是否允许自由路由Pod网段,隧道都能把流量传到目标节点。代价和VXLAN类似,多了一轮封解包处理。

calico也支持VXLAN模式,它的VXLAN实现优势在于可以直接借用内核的VXLAN能力,做性能优化。但在选择时有一个关键的考量点:IPIP和VXLAN都需要宿主机间三层互通,而BGP模式下如果跨了子网,路由器的路由策略很可能会挡住Pod网段的路由通告。所以如果节点跨机房、跨VPC部署,calico的BGP模式很容易出现节点间路由不通的问题。这时要么配置IPIP或VXLAN,要么在路由器上增加静态路由策略。

3.3 calico的网络策略能力

calico另一个让flannel望尘莫及的功能是网络策略。K8s本身有NetworkPolicy API,但flannel并不实现NetworkPolicy,默认集群里网络策略是空摆设。而calico自带了一套完整的策略引擎,可以从Pod粒度、Namespace粒度、IP段粒度甚至服务账号粒度做流量控制。

我实际用过的一个例子是:一个多租户环境,不同团队共享同一个集群,其中几个业务有合规要求,只允许特定来源访问。用calico的GlobalNetworkPolicy配置之后,几行YAML就搞定了。配置片段大概长这样:

apiVersion: projectcalico.org/v3 kind: GlobalNetworkPolicy metadata: name: only-allow-frontend spec: selector: app == "payment" ingress: - action: Allow source: selector: app == "frontend" - action: Deny

这个功能在生产环境下几乎是刚需。相比之下,flannel侧没有任何原生InCluster流量管控能力,只能在宿主机层面用iptables手工撸规则,费时费力还容易出错。

3.4 calico的eBPF模式

calico还有一个更进阶的数据面:eBPF模式。这个模式用一个运行在Linux内核的eBPF程序替代原本的iptables逻辑,不仅转发性能更好,还能支持DSR(Direct Server Return)等高级负载均衡能力。启用eBPF模式后,Kubernetes的Service流量可以直接在内核里完成转发,不再走kube-proxy的用户态逻辑。

当然,eBPF模式对内核版本有要求,一般需要Linux 5.x以上,而且节点上要开启相应权限。这里不建议一上来就启用eBPF,尤其是在内核版本老、容器运行时复杂的环境里,容易引入额外变数。当业务真正碰到性能瓶颈时再考虑升级数据面,是比较稳妥的路径。

4. flannel和calico的全维度对比

4.1 一张表看清性能与功能差异

对比维度flannel(VXLAN)calico(BGP)calico(IPIP)
转发路径宿主机网络+隧道封装原生路由原生路由+IP封装
Pod IP路由不依赖BGP依赖BGP依赖BGP
跨网段支持支持(三层互通即可)一般(需路由策略配合)支持
延迟开销中(有封包解包)低中低
吞吐量中高中高
NetworkPolicy不支持完整支持完整支持
部署复杂度低中中
大规模集群有性能瓶颈良好良好

注意表中“跨网段支持”这一项,BGP模式下calico不直接支持跨子网流量,但可以通过配置路由反射器(Route Reflector)或建立节点间的BGP peer解决,只是复杂度会上升。

4.2 CPU开销对比实测感受

我在一个8节点的测试集群里做过吞吐对比。同样的业务Pod,同样大小的数据包,calico BGP模式比flannel VXLAN模式大概快20%-30%,CPU占用也低一些。这个差距在HTTP短连接请求、DNS解析、批量日志上报这类高频小包场景里格外明显。

但如果只是内部跑点定时任务、压力不大的Web应用,理论上flannel VXLAN的性能也足够用了。所以性能不该是选型的唯一标准,还要看现有集群的规模趋势、团队对网络原理的掌握程度、以及有没有安全管控需求。

4.3 运维复杂度视角

从日常运维角度看,flannel的设计目标就是“零维护”,跑起来之后基本不用管。它没有BGP、没有路由反射器,所有状态都集中在etcd或者Kubernetes的Node对象里。出现问题时的排查链路也很短:查flannel.1网卡、查路由表、查VXLAN端口,三步基本能定位。

calico的运维曲线明显陡峭一些。BGP peering、node-to-node mesh、IPPool管理、Felix日志、eBPF数据面,这些概念都会在实际使用中遇到。尤其在节点数量超过50之后,calico默认的full-mesh BGP模式会产生大量BGP会话,这时需要引入BGP Route Reflector来控制会话数量。这个操作在官方文档里有专门描述,但没有一定网络基础的人第一次看会有点懵。

5. 生产环境选型:什么时候该用哪个

5.1 选flannel的典型场景

如果你是第一次搭建Kubernetes集群、团队没有专职网络工程师、集群规模不大(比如10台左右)、业务以内部低负载应用为主,那flannel其实很合适。它最大的优点是上手成本极低,部署完就能跑,出了问题也容易排查。而且它在公有云虚拟机、物理机甚至树莓派集群上都有良好的兼容性。

碰到节点需要跨VPC或跨机房部署的情况,flannel VXLAN也是相对省心的方案,只要底层网络三层能通,隧道就能建立,不需要动云上的路由表。我自己就有一个跨机房的测试集群,直接用flannel VXLAN跑了大半年,稳定性还不错。

5.2 选calico的典型场景

如果业务对时延敏感、流量规模大、或者集群需要多租户隔离与网络策略管控,那么calico是更适合的答案。尤其是有安全合规需求的场景,calico的NetworkPolicy是flannel替代不了的能力。

另外,如果你已经有物理网络背景,理解BGP的运作方式,用calico反而是“回归常识”的选择。因为它把容器的虚拟网络当成一张真实的路由网络来管理,问题排查时的思路可以完全复用传统网络的经验。

5.3 混合部署的可能性

有人可能会问:一个集群里能不能flannel和calico混用?答案是不建议。CNI标准下,同一时间的集群必须由同一个插件管理,混用会导致路由表互相覆盖、IP分配冲突。若有测试需要,也要在不同节点集合里通过调度标签完全隔离后再实践,否则很容易出现诡异问题。

5.4 切插件时的注意事项

如果是从flannel切换到calico,不能直接删flannel再装calico,要避免节点残留路由和iptables规则。比较稳妥的顺序是:先给集群打调度锁(kubectl cordon)→ 分批排空节点上的Pod → 删掉flannel DaemonSet → 清理每个节点上flannel创建的cni0、flannel.1网卡以及对应的路由和iptables链 → 再部署calico。整个过程如果集群资源有富余,建议先拿一个测试集群演练一遍再动手。

6. 实际部署与排查过程记录

6.1 一台新节点接入集群的完整步骤

以calico为例,假设有一个K8s集群已经在运行,现在要加一台新节点。如果是二进制方式部署的Kubernetes,新节点上需要保证以下几点:

  • kubelet已启动并成功注册到集群
  • kube-proxy已运行,确保Service的iptables规则正常注入
  • 确认/etc/cni/net.d/里没有残留的flannel或其他CNI配置

然后执行kubectl apply -f calico.yaml,calico的DaemonSet会在新节点上自动启动,创建对应的cali网卡和路由规则。正常情况下新节点的Pod就能拿到IP并跟其他节点互通。

6.2 flannel部署后的常见验证命令

部署完成后,我的习惯是先验证数据面再验证控制面。验证命令参考如下:

# 查看flannel pod状态 kubectl get pods -n kube-flannel # 查看本机flannel网卡是否存在 ip link show flannel.1 # 查看节点间路由是否正常 ip route | grep 10.244 # 跨节点ping测试 kubectl exec -it <pod-a> -- ping <pod-b-ip>

如果Pod之间ping不通过,优先检查VXLAN的VTEP表。ip -d link show flannel.1可以看到详细的VXLAN信息;bridge fdb show | grep flannel.1可以看到对端节点的MAC地址记录。多数情况下,问题出在UDP端口被防火墙挡了,或者节点的物理网卡MTU值过大导致分片丢弃。

6.3 calico部署后的诊断命令

calico的排查工具比较全,我常用的命令包括:

# 查看BGP peer状态 calicoctl node status # 查看节点分配的IP池 calicoctl get ipPool # 查看路由表 ip route | grep 192.168 # 查看某Pod的endpoint状态 calicoctl get workloadEndpoint | grep <pod-name>

遇到过的一个典型问题是:新节点加入后,节点上业务Pod可以互相通信,但集群里的DNS(CoreDNS)偶尔超时。排查后发现新节点的默认路由指向了一个旧的网关,导致数据包从错误网关出去了。因此在节点初始化时,需要先确认默认路由和防火墙都有正确配置,再部署Pod。

7. 用了一段时间后的真实体会

用flannel和calico都跑过生产集群之后,我现在的看法是:选网络插件没有绝对的标准答案,只有适合当下场景的答案。刚开始做K8s时,团队对网络理解不深,用flannel快速建集群是一个非常务实的决定,它降低了门槛,让团队把更多精力花在应用本身。当集群规模扩大、多租户需求出现、安全审计要求提上日程的时候,再切换到calico,有前面打下的基础,迁移过程也还算可控。

有一个技巧想分享给正在评估的人:不要光看官方文档上的特性对比,最好拿自己的业务Pod在同等网络环境下做一次A/B压测。不用太复杂,跑一个返回当前节点IP和时延的HTTP服务,分别部署在两个插件环境里,用相同的负载工具打两轮,数据出来就很清楚自己业务适合哪种模式了。这个实验比任何人告诉你“哪个好”都更有说服力。

还有一点是:网络插件升级不像普通Docker镜像那样无感,每次大版本变更前务必做好节点路由表和iptables快照备份。报错时不要只看Pod日志,dmesg和journalctl -u kubelet里往往藏着更关键的线索。

希望这些实践经验能帮你在flannel和calico之间做一个更清晰的判断。真到了具体的业务场景里,如果你有其他特殊情况或者有趣的性能和网络配置经验,也欢迎一起交流讨论。

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

六边形网格生成器hexgen:地理空间建模与游戏AI的高效底座

简介&#xff1a;hexgen 是一款基于 Python 开发的六角形世界地图生成器&#xff0c;面向游戏开发者、桌游&#xff08;如 DnD&#xff09;设计者及地理模拟爱好者&#xff0c;用于快速生成可定制的随机行星表面地图&#xff0c;并支持按需划分领土单元&#xff0c;解决手工绘制…

作者头像 李华
网站建设 2026/10/21 21:56:37

临时文件自动化清理工具:从扫描策略到误删事故复盘

今天聊一个我自己都在用的工具&#xff1a;临时文件自动化工具。 说个典型场景。某天我登上一台个人开发机&#xff0c;顺手看了一眼磁盘占用&#xff0c; /tmp 已经占了 31G&#xff0c;用户缓存目录也有十几 G。第一反应当然是手动清理&#xff0c;但删了不到十分钟我就意…

作者头像 李华
网站建设 2026/10/21 21:52:50

自动化与脚本实战:从重复劳动到高效运维的必经之路

从“自动化与脚本”说起&#xff1a;把重复劳动交给机器&#xff0c;是技术人最划算的投资 做技术这些年&#xff0c;我见过太多人把时间耗在“明明能一键完成&#xff0c;却非要手动折腾”的事情上。批量改文件名、每天刷新报表、定时备份数据、跨系统同步信息……这些活儿单看…

作者头像 李华
网站建设 2026/10/21 21:52:25

知识工作浏览器插件集:从采集到输出的低摩擦工作流

先给结论&#xff1a;知识工作的效率瓶颈&#xff0c;往往不在打字速度&#xff0c;而在信息从“看到”变成“可用”的那段链条。我手上的这套knowledge-work-plugins&#xff0c;是一组围绕知识工作者日常场景的浏览器扩展集合&#xff1a;网页里读到一段值得留存的内容&#…

作者头像 李华
网站建设 2026/10/21 21:52:01

模板匹配实现银行卡号识别:从原理到OpenCV落地实践

最近在复盘手头这个模拟项目X&#xff1a;从一张银行卡照片里自动把卡号读出来。技术选型的时候&#xff0c;我第一个想到的竟然不是深度学习方案&#xff0c;而是计算机视觉里的老牌方法——模板匹配。模板匹配做银行卡号识别&#xff0c;听起来确实有点复古&#xff0c;但真正…

作者头像 李华
网站建设 2026/10/21 21:51:22

AIGC十年演进复盘:从玩具到生产工具的技术逻辑与落地经验

2015年我刚开始接触AI生成内容的时候&#xff0c;圈子里最流行的玩法还是让模型续写小说。续出来的东西大多数时候像梦话&#xff0c;偶尔冒出一两句惊为天人&#xff0c;但没人真敢把它当生产力用。十年过去&#xff0c;AIGC这个词已经从技术圈的术语变成了几乎人人都聊过的话…

作者头像 李华