Kubernetes 网络深度解析:从 CNI 到 Service Mesh 的完整网络栈

深入 Kubernetes 网络栈,从 CNI 插件选型与 Pod 网络模型,到 Service 负载均衡与 kube-proxy 模式,再到 Service Mesh 的流量治理,结合工程实际分析架构取舍、常见误区与落地路径,帮助构建稳定、可观测的集群网络。

很多团队刚开始用 Kubernetes 时,网络问题往往第一个暴露出来,又最难排查。不是因为网络本身有多高深,而是因为 Kubernetes 的网络层不是单一组件,而是一个从底层数据面到上层控制面的完整栈。一旦出问题,可能是 CNI 配置不对,也可能是 Service 转发规则冲突,甚至是应用层重试策略不合理。这篇文章想聊的,就是这条从 CNI 到 Service Mesh 的完整链路,以及中间那些容易被忽略的工程判断。

AI technology illustration

先理清 Pod 网络模型:到底谁在负责“通”

Kubernetes 对网络有一个最基本的要求:每个 Pod 要有自己的 IP,集群内所有 Pod 之间能直接通信,不需要 NAT。这个要求看起来简单,但落在不同规模的集群和不同基础设施上,实现方式会有很大差异。真正让 Pod 之间“通”起来的,是 CNI(Container Network Interface)插件。

CNI 本身是一个标准,定义了容器运行时在创建网络时调用的接口。但很多人在讨论“CNI 插件”时,其实是在讨论具体的网络实现,比如 Flannel、Calico、Cilium。这些实现背后,承载的是不同的数据面技术和设计哲学。

一个典型的场景是:团队在自建机房用 Flannel 的 VXLAN 模式跑得挺好,迁移到云上后想利用云厂商的 VPC 路由,结果发现 Flannel 的路由模式与云网络控制器冲突,不得不切换到 Calico 的 BGP 模式。这就是 CNI 选型不仅是技术问题,也是基础设施适配问题。

常见 CNI 插件对比

下面这张表对比了目前社区使用较多的几种 CNI 插件,不是为了比出优劣,而是帮你在不同约束下做出选择。

插件 数据面 网络策略 适用场景 复杂度
Flannel VXLAN / host-gw 不支持 中小集群,简单网络
Calico BGP / IPIP / VXLAN 支持 中大型集群,需网络策略
Cilium eBPF 支持 关注可观测性与性能
Weave VXLAN 支持 快速部署,轻量网络

一个常见误区是认为 CNI 插件越强大越好。实际上,如果团队对网络策略没有强需求,也没有 eBPF 的运维能力,强行上 Cilium 只会增加排查成本。早期很多团队用 Flannel 的原因很简单:它足够稳定,且不引入额外依赖。当集群规模增长到几百节点,或者需要细粒度的网络隔离时,再考虑切换到 Calico 或 Cilium 也不迟。

Service 和 kube-proxy:从“通”到“可达”

Pod 之间通了之后,下一个问题就是服务发现与负载均衡。Kubernetes 用 Service 对象抽象一组 Pod,而真正把流量引到后端 Pod 的,是 kube-proxy 组件。看似简单,但 kube-proxy 的工作模式直接决定了集群东西向流量的转发效率和可观测性。

早期 Kubernetes 默认使用 userspace 模式,性能很差,现在几乎没人用了。目前主流是 iptables 模式和 IPVS 模式。很多团队在集群规模变大后,会突然发现 Service 的更新变慢,甚至丢包,这时候大概率是 iptables 规则数量爆炸了。

举个例子:一个 500 个 Service、每个 Service 有 10 个后端 Pod 的中型集群,iptables 规则数量可能达到数万条。当 Service 发生变化时,kube-proxy 需要重新刷入大量规则,这个过程中如果规则未完全生效,就会出现部分请求被丢弃。IPVS 模式使用内核哈希表做负载均衡,规则数量级大幅降低,转发延迟也更稳定。但 IPVS 也有自己的问题,比如对内核模块的依赖,以及早期版本无法优雅处理长连接。

下面是 iptables 模式下,一个 ClusterIP Service 的典型规则片段(简化后):

*nat
-A KUBE-SERVICES -d 10.96.0.1/32 -p tcp -m tcp --dport 443 -j KUBE-SVC-XXXX
-A KUBE-SVC-XXXX -m statistic --mode random --probability 0.333 -j KUBE-SEP-AAAA
-A KUBE-SVC-XXXX -m statistic --mode random --probability 0.500 -j KUBE-SEP-BBBB
-A KUBE-SVC-XXXX -j KUBE-SEP-CCCC
-A KUBE-SEP-AAAA -p tcp -m tcp -j DNAT --to-destination 10.244.1.5:8443

可以看到,iptables 通过随机概率实现简单的轮询负载均衡。当规则数量激增时,这种链式匹配的延迟会变得不可忽略。这也是为什么很多生产环境建议一旦集群规模超过一定阈值,就应该评估迁移到 IPVS 模式。

网络策略:安全边界到底在哪里

网络通了,流量也负载均衡了,安全隔离就提上日程。Kubernetes 的 NetworkPolicy 对象提供了一种基于 Pod 标签的防火墙规则,但它依赖 CNI 插件来实现。这就引出了另一个误区:以为安装了 NetworkPolicy 资源,就自动有了网络隔离。实际上,如果 CNI 插件不支持(比如 Flannel 的默认配置),NetworkPolicy 写了也不会生效。

在实际项目中,网络策略的落地通常比较谨慎。因为一旦错误配置,可能导致服务间突然不通,排查起来很痛苦。常见做法是先在一个测试命名空间里,把默认拒绝 ingress 的策略打开,再逐步放通需要的流量。但即使这样,随着微服务数量增加,策略的维护也会变成负担。很多团队开始意识到,需要一种更动态、更细粒度的流量控制方式,这就是 Service Mesh 进入讨论的背景。

  • 常见误区:以为 CNI 插件都支持 NetworkPolicy,部署后不验证。
  • 常见误区:把网络策略直接应用到生产环境,未先在测试环境验证允许/拒绝规则。
  • 实践建议:使用命名空间和标签分层管理策略,避免单条策略覆盖所有 Pod。

Service Mesh 到底解决了什么

当微服务数量增长到几十甚至上百个时,仅靠 kube-proxy 和 NetworkPolicy 管理流量,会暴露出几个明显的问题:无法做应用层路由(如按 HTTP header 分流)、无法统一观测每个服务的调用指标和追踪、无法在基础设施层实现重试和熔断。Service Mesh 的目标就是把这些治理能力下沉到 sidecar 代理里,让应用代码不用关心。

典型架构是以 Istio 为代表的控制平面 + 数据平面(Envoy sidecar)。每个 Pod 旁边注入一个 sidecar 容器,拦截进出流量,执行流量管理、安全、可观测性策略。这带来了很大的灵活性,但也引入了新的复杂度。

一个真实场景:团队刚开始在非生产环境试点 Istio 时,发现原本稳定的服务间调用突然出现大量超时。排查后发现,是 sidecar 的资源限制设置过低,导致 Envoy 在高并发下 CPU 被打满。调整资源配额并启用连接池设置后恢复。这种问题在传统 kube-proxy 网络里根本不会出现,因为转发逻辑在内核态,而 sidecar 代理是用户态,需要额外关注资源消耗。

Service Mesh 的数据平面转发流程通常如下(以 Istio 为例):

# 应用容器发出的请求,被 iptables 规则重定向到 Envoy sidecar
# Envoy 根据从 Pilot 获取的配置,对请求进行路由、重试、TLS
# 最终转发到目标 Pod 的 sidecar,再由目标 sidecar 转发给应用容器

这套机制让服务间通信变得透明,但排查问题也更复杂,因为请求路径变长了。很多团队在引入 Service Mesh 后发现,网络延迟增加了 2~5ms,这是 sidecar 处理带来的额外开销。对于低延迟敏感系统,需要慎重评估。

从 CNI 到 Service Mesh 的完整栈:如何做出选择

没有一种网络栈适合所有场景。小团队从 Flannel + iptables 模式开始,足够稳定;业务增长后,切换到 Calico + IPVS 可能就解决了大部分问题;只有当确实需要基于应用层特征做流量治理、且团队有足够的运维能力时,才应该考虑引入 Service Mesh。很多团队过早引入 Service Mesh,反而被 sidecar 的升级、资源消耗和排查成本拖住。

下面从几个维度总结一下不同阶段的网络栈特征:

  • 初创/小规模集群:CNI 选 Flannel 或 Calico 简单模式,kube-proxy 用 iptables,网络策略按需开启,不引入 mesh。
  • 中等规模,需要策略与性能:CNI 选 Calico 或 Cilium,kube-proxy 切到 IPVS,完善 NetworkPolicy,开始评估 mesh 的试点。
  • 大规模、微服务化:在部分服务上引入 Service Mesh(如 Istio),保留 CNI 和 IPVS 的底层转发,形成分层治理。

另一个容易忽略的点是,很多团队把 Service Mesh 当成网络问题的万能药,但忘记了一个根本原则:网络栈的每一层都有它的职责,越往上层,灵活性越高,但代价也越大。底座不稳,上层治理只会放大问题。所以,在花时间折腾 Istio 的 VirtualService 之前,先确保 CNI 和 kube-proxy 的配置是稳定的,这比什么都重要。

写在最后

Kubernetes 网络栈的深度,决定了它既是一个需要认真对待的基础层,也是一个容易过度设计的领域。从 CNI 到 Service Mesh,每个选择背后都有工程上的权衡,而这些权衡往往与技术无关,而是与团队规模、系统延迟要求和运维能力相关。希望这篇文章能帮你理清这条链路上的关键节点,在面对具体决策时,多一份从容。

原创文章,作者:fudengji,如若转载,请注明出处:https://fudengji.cn/article/419/

(0)
上一篇 1分钟前
下一篇 1分钟前

相关推荐